diff --git a/configure b/configure index c505af5c4d3..4c5fa4aaa60 100755 --- a/configure +++ b/configure @@ -939,6 +939,13 @@ then putvar CFG_ENABLE_CLANG fi +if [ -z "$CFG_DISABLE_LIBCPP" -a -n "$CFG_ENABLE_CLANG" ] +then + CFG_USING_LIBCPP="1" +else + CFG_USING_LIBCPP="0" +fi + # Same with jemalloc. save the setting here. if [ -n "$CFG_DISABLE_JEMALLOC" ] then @@ -1682,7 +1689,7 @@ do CXXFLAGS="$CXXFLAGS $LLVM_CXXFLAGS" LDFLAGS="$LDFLAGS $LLVM_LDFLAGS" - if [ -z "$CFG_DISABLE_LIBCPP" ] && [ -n "$CFG_USING_CLANG" ]; then + if [ "$CFG_USING_LIBCPP" != "0" ]; then LLVM_OPTS="$LLVM_OPTS --enable-libcpp" fi @@ -1743,6 +1750,7 @@ putvar CFG_AARCH64_LINUX_ANDROID_NDK putvar CFG_ARM_LINUX_ANDROIDEABI_NDK putvar CFG_I686_LINUX_ANDROID_NDK putvar CFG_MANDIR +putvar CFG_USING_LIBCPP # Avoid spurious warnings from clang by feeding it original source on # ccache-miss rather than preprocessed input. diff --git a/mk/llvm.mk b/mk/llvm.mk index b2a90f583f7..6d5e9169367 100644 --- a/mk/llvm.mk +++ b/mk/llvm.mk @@ -80,10 +80,16 @@ endif # LLVM linkage: +# Note: Filter with llvm-config so that optional targets which aren't present +# don't cause errors (ie PNaCl's target is only present within PNaCl's LLVM +# fork). LLVM_LINKAGE_PATH_$(1):=$$(abspath $$(RT_OUTPUT_DIR_$(1))/llvmdeps.rs) $$(LLVM_LINKAGE_PATH_$(1)): $(S)src/etc/mklldeps.py $$(LLVM_CONFIG_$(1)) - $(Q)$(CFG_PYTHON) "$$<" "$$@" "$$(LLVM_COMPONENTS)" "$$(CFG_ENABLE_LLVM_STATIC_STDCPP)" \ - $$(LLVM_CONFIG_$(1)) "$(CFG_STDCPP_NAME)" + $(Q)$(CFG_PYTHON) "$$<" "$$@" "$$(filter $$(shell \ + $$(LLVM_CONFIG_$(1)) --components), \ + $(LLVM_OPTIONAL_COMPONENTS)) $(LLVM_REQUIRED_COMPONENTS)" \ + "$$(CFG_ENABLE_LLVM_STATIC_STDCPP)" $$(LLVM_CONFIG_$(1)) \ + "$(CFG_STDCPP_NAME)" "$$(CFG_USING_LIBCPP)" endef $(foreach host,$(CFG_HOST), \ @@ -94,7 +100,9 @@ $(foreach host,$(CFG_HOST), \ # This can't be done in target.mk because it's included before this file. define LLVM_LINKAGE_DEPS -$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.rustc_llvm: $$(LLVM_LINKAGE_PATH_$(2)) +$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.rustc_llvm: $$(LLVM_LINKAGE_PATH_$(3)) +RUSTFLAGS$(1)_rustc_llvm_T_$(3) += $$(shell echo $$(LLVM_ALL_COMPONENTS_$(3)) | tr '-' '_' |\ + sed -e 's/^ //;s/\([^ ]*\)/\-\-cfg have_component_\1/g') endef $(foreach source,$(CFG_HOST), \ diff --git a/mk/main.mk b/mk/main.mk index d03769d9132..f2ff4f1c3a2 100644 --- a/mk/main.mk +++ b/mk/main.mk @@ -276,9 +276,18 @@ endif # LLVM macros ###################################################################### -LLVM_COMPONENTS=x86 arm aarch64 mips powerpc ipo bitreader bitwriter linker asmparser mcjit \ +LLVM_OPTIONAL_COMPONENTS=x86 arm aarch64 mips powerpc +LLVM_REQUIRED_COMPONENTS=ipo bitreader bitwriter linker asmparser mcjit \ interpreter instrumentation +ifneq ($(CFG_LLVM_ROOT),) +# Ensure we only try to link targets that the installed LLVM actually has: +LLVM_COMPONENTS := $(filter $(shell $(CFG_LLVM_ROOT)/bin/llvm-config$(X_$(CFG_BUILD)) --components),\ + $(LLVM_OPTIONAL_COMPONENTS)) $(LLVM_REQUIRED_COMPONENTS) +else +LLVM_COMPONENTS := $(LLVM_OPTIONAL_COMPONENTS) $(LLVM_REQUIRED_COMPONENTS) +endif + # Only build these LLVM tools LLVM_TOOLS=bugpoint llc llvm-ar llvm-as llvm-dis llvm-mc opt llvm-extract @@ -314,6 +323,8 @@ LLVM_HOST_TRIPLE_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --host-target) LLVM_AS_$(1)=$$(CFG_LLVM_INST_DIR_$(1))/bin/llvm-as$$(X_$(1)) LLC_$(1)=$$(CFG_LLVM_INST_DIR_$(1))/bin/llc$$(X_$(1)) +LLVM_ALL_COMPONENTS_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --components) + endef $(foreach host,$(CFG_HOST), \ @@ -476,7 +487,7 @@ endif endif LD_LIBRARY_PATH_ENV_HOSTDIR$(1)_T_$(2)_H_$(3) := \ - $$(CURDIR)/$$(HLIB$(1)_H_$(3)) + $$(CURDIR)/$$(HLIB$(1)_H_$(3)):$$(CFG_LLVM_INST_DIR_$(3))/lib LD_LIBRARY_PATH_ENV_TARGETDIR$(1)_T_$(2)_H_$(3) := \ $$(CURDIR)/$$(TLIB1_T_$(2)_H_$(CFG_BUILD)) diff --git a/mk/target.mk b/mk/target.mk index f1b5f9e3155..9d5e633c3c6 100644 --- a/mk/target.mk +++ b/mk/target.mk @@ -131,6 +131,7 @@ $$(TBIN$(1)_T_$(2)_H_$(3))/$(4)$$(X_$(2)): \ @$$(call E, rustc: $$@) $$(STAGE$(1)_T_$(2)_H_$(3)) \ $$(STDCPP_LIBDIR_RUSTFLAGS_$(2)) \ + $$(LLVM_LIBDIR_RUSTFLAGS_$(2)) \ -o $$@ $$< --cfg $(4) endef diff --git a/mk/tests.mk b/mk/tests.mk index b41eaba1900..bd7414a3bb6 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -1072,7 +1072,9 @@ $(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \ "$$(LD_LIBRARY_PATH_ENV_TARGETDIR$(1)_T_$(2)_H_$(3))" \ $(1) \ $$(S) \ - $(3) + $(3) \ + "$$(LLVM_LIBDIR_RUSTFLAGS_$(3))" \ + "$$(LLVM_ALL_COMPONENTS_$(3))" @touch -r $$@.start_time $$@ && rm $$@.start_time else # FIXME #11094 - The above rule doesn't work right for multiple targets diff --git a/src/etc/maketest.py b/src/etc/maketest.py index c2958caddc4..34c2cdbef35 100644 --- a/src/etc/maketest.py +++ b/src/etc/maketest.py @@ -53,6 +53,8 @@ putenv('HOST_RPATH_DIR', os.path.abspath(sys.argv[10])) putenv('TARGET_RPATH_DIR', os.path.abspath(sys.argv[11])) putenv('RUST_BUILD_STAGE', sys.argv[12]) putenv('S', os.path.abspath(sys.argv[13])) +putenv('RUSTFLAGS', sys.argv[15]) +putenv('LLVM_COMPONENTS', sys.argv[16]) putenv('PYTHON', sys.executable) os.putenv('TARGET', target_triple) diff --git a/src/etc/mklldeps.py b/src/etc/mklldeps.py index 215fa1cdd1b..8381e4f7040 100644 --- a/src/etc/mklldeps.py +++ b/src/etc/mklldeps.py @@ -18,6 +18,7 @@ components = sys.argv[2].split() # splits on whitespace enable_static = sys.argv[3] llvm_config = sys.argv[4] stdcpp_name = sys.argv[5] +use_libcpp = sys.argv[6] f.write("""// Copyright 2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at @@ -44,11 +45,25 @@ def run(args): sys.exit(1) return out +def runErr(args): + proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = proc.communicate() + + if err: + return False, out + else: + return True, out + f.write("\n") +args = [llvm_config, '--shared-mode'] +args.extend(components) +llvm_shared, out = runErr(args) +if llvm_shared: + llvm_shared = 'shared' in out + # LLVM libs args = [llvm_config, '--libs', '--system-libs'] - args.extend(components) out = run(args) for lib in out.strip().replace("\n", ' ').split(' '): @@ -63,8 +78,7 @@ for lib in out.strip().replace("\n", ' ').split(' '): elif lib[0] == '-': lib = lib.strip()[1:] f.write("#[link(name = \"" + lib + "\"") - # LLVM libraries are all static libraries - if 'LLVM' in lib: + if not llvm_shared and 'LLVM' in lib: f.write(", kind = \"static\"") f.write(")]\n") @@ -83,7 +97,7 @@ else: # Note that we use `cfg_attr` here because on MSVC the C++ standard library # is not c++ or stdc++, but rather the linker takes care of linking the # right standard library. - if 'stdlib=libc++' in out: + if use_libcpp != "0" or 'stdlib=libc++' in out: f.write("#[cfg_attr(not(target_env = \"msvc\"), link(name = \"c++\"))]\n") else: f.write("#[cfg_attr(not(target_env = \"msvc\"), link(name = \"" + stdcpp_name + "\"))]\n") diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index 2b9adf5490a..0f05db86742 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -33,6 +33,7 @@ #![feature(link_args)] #![feature(staged_api)] #![feature(linked_from)] +#![feature(concat_idents)] extern crate libc; #[macro_use] #[no_link] extern crate rustc_bitflags; @@ -2327,6 +2328,37 @@ pub unsafe fn debug_loc_to_string(c: ContextRef, tr: DebugLocRef) -> String { .expect("got a non-UTF8 DebugLoc from LLVM") } +pub fn initialize_available_targets() { + macro_rules! init_target( + ($cfg:ident $arch:ident) => { { + #[cfg($cfg)] + fn init() { + unsafe { + let f = concat_idents!(LLVMInitialize, $arch, TargetInfo); + f(); + let f = concat_idents!(LLVMInitialize, $arch, Target); + f(); + let f = concat_idents!(LLVMInitialize, $arch, TargetMC); + f(); + let f = concat_idents!(LLVMInitialize, $arch, AsmPrinter); + f(); + let f = concat_idents!(LLVMInitialize, $arch, AsmParser); + f(); + } + } + #[cfg(not($cfg))] + fn init() { } + init(); + } } + ); + + init_target!(have_component_powerpc PowerPC); + init_target!(have_component_mips Mips); + init_target!(have_component_aarch64 AArch64); + init_target!(have_component_arm ARM); + init_target!(have_component_x86 X86); +} + // The module containing the native LLVM dependencies, generated by the build system // Note that this must come after the rustllvm extern declaration so that // parts of LLVM that rustllvm depends on aren't thrown away by the linker. diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index c553843f858..4815a399d99 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -961,39 +961,7 @@ pub unsafe fn configure_llvm(sess: &Session) { llvm::LLVMInitializePasses(); - // Only initialize the platforms supported by Rust here, because - // using --llvm-root will have multiple platforms that rustllvm - // doesn't actually link to and it's pointless to put target info - // into the registry that Rust cannot generate machine code for. - llvm::LLVMInitializeX86TargetInfo(); - llvm::LLVMInitializeX86Target(); - llvm::LLVMInitializeX86TargetMC(); - llvm::LLVMInitializeX86AsmPrinter(); - llvm::LLVMInitializeX86AsmParser(); - - llvm::LLVMInitializeARMTargetInfo(); - llvm::LLVMInitializeARMTarget(); - llvm::LLVMInitializeARMTargetMC(); - llvm::LLVMInitializeARMAsmPrinter(); - llvm::LLVMInitializeARMAsmParser(); - - llvm::LLVMInitializeAArch64TargetInfo(); - llvm::LLVMInitializeAArch64Target(); - llvm::LLVMInitializeAArch64TargetMC(); - llvm::LLVMInitializeAArch64AsmPrinter(); - llvm::LLVMInitializeAArch64AsmParser(); - - llvm::LLVMInitializeMipsTargetInfo(); - llvm::LLVMInitializeMipsTarget(); - llvm::LLVMInitializeMipsTargetMC(); - llvm::LLVMInitializeMipsAsmPrinter(); - llvm::LLVMInitializeMipsAsmParser(); - - llvm::LLVMInitializePowerPCTargetInfo(); - llvm::LLVMInitializePowerPCTarget(); - llvm::LLVMInitializePowerPCTargetMC(); - llvm::LLVMInitializePowerPCAsmPrinter(); - llvm::LLVMInitializePowerPCAsmParser(); + llvm::initialize_available_targets(); llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int, llvm_args.as_ptr()); diff --git a/src/test/run-make/execution-engine/Makefile b/src/test/run-make/execution-engine/Makefile index ef646c5bf5d..4c818cd99e2 100644 --- a/src/test/run-make/execution-engine/Makefile +++ b/src/test/run-make/execution-engine/Makefile @@ -4,6 +4,8 @@ # This is a basic test of LLVM ExecutionEngine functionality using compiled # Rust code built using the `rustc` crate. +ifeq ($(filter executionengine,$(LLVM_COMPONENTS)),executionengine) + ifneq ($(shell uname),FreeBSD) all: $(RUSTC) test.rs @@ -12,3 +14,8 @@ else all: endif + +else +all: + +endif diff --git a/src/test/run-make/simd-ffi/Makefile b/src/test/run-make/simd-ffi/Makefile index dc0fcec1980..e9c974a0137 100644 --- a/src/test/run-make/simd-ffi/Makefile +++ b/src/test/run-make/simd-ffi/Makefile @@ -1,15 +1,28 @@ -include ../tools.mk +TARGETS = +ifeq ($(filter arm,$(LLVM_COMPONENTS)),arm) # construct a fairly exhaustive list of platforms that we # support. These ones don't follow a pattern -TARGETS=arm-linux-androideabi arm-unknown-linux-gnueabihf arm-unknown-linux-gnueabi +TARGETS += arm-linux-androideabi arm-unknown-linux-gnueabihf arm-unknown-linux-gnueabi +endif + +ifeq ($(filter x86,$(LLVM_COMPONENTS)),x86) +X86_ARCHS = i686 x86_64 +else +X86_ARCHS = +endif # these ones do, each OS lists the architectures it supports -LINUX=aarch64 i686 x86_64 mips mipsel -WINDOWS=i686 x86_64 +LINUX=$(filter aarch64 mips,$(LLVM_COMPONENTS)) $(X86_ARCHS) +ifeq ($(filter mips,$(LLVM_COMPONENTS)),mips) +LINUX += mipsel +endif + +WINDOWS=$(X86_ARCHS) # fails with: failed to get iphonesimulator SDK path: no such file or directory #IOS=i386 aarch64 armv7 -DARWIN=i686 x86_64 +DARWIN=$(X86_ARCHS) $(foreach arch,$(LINUX),$(eval TARGETS += $(arch)-unknown-linux-gnu)) $(foreach arch,$(WINDOWS),$(eval TARGETS += $(arch)-pc-windows-gnu)) diff --git a/src/test/run-make/tools.mk b/src/test/run-make/tools.mk index 23af568697f..88cf2a2b031 100644 --- a/src/test/run-make/tools.mk +++ b/src/test/run-make/tools.mk @@ -6,7 +6,7 @@ TARGET_RPATH_ENV = \ $(LD_LIB_PATH_ENVVAR)="$(TMPDIR):$(TARGET_RPATH_DIR):$($(LD_LIB_PATH_ENVVAR))" BARE_RUSTC := $(HOST_RPATH_ENV) $(RUSTC) -RUSTC := $(BARE_RUSTC) --out-dir $(TMPDIR) -L $(TMPDIR) +RUSTC := $(BARE_RUSTC) --out-dir $(TMPDIR) -L $(TMPDIR) $(RUSTFLAGS) #CC := $(CC) -L $(TMPDIR) HTMLDOCCK := $(PYTHON) $(S)/src/etc/htmldocck.py