Implement flexible target specification

Removes all target-specific knowledge from rustc. Some targets have changed
during this, but none of these should be very visible outside of
cross-compilation. The changes make our targets more consistent.

iX86-unknown-linux-gnu is now only available as i686-unknown-linux-gnu. We
used to accept any value of X greater than 1. i686 was released in 1995, and
should encompass the bare minimum of what Rust supports on x86 CPUs.

The only two windows targets are now i686-pc-windows-gnu and
x86_64-pc-windows-gnu.

The iOS target has been renamed from arm-apple-ios to arm-apple-darwin.

A complete list of the targets we accept now:

arm-apple-darwin
arm-linux-androideabi
arm-unknown-linux-gnueabi
arm-unknown-linux-gnueabihf

i686-apple-darwin
i686-pc-windows-gnu
i686-unknown-freebsd
i686-unknown-linux-gnu

mips-unknown-linux-gnu
mipsel-unknown-linux-gnu

x86_64-apple-darwin
x86_64-unknown-freebsd
x86_64-unknown-linux-gnu
x86_64-pc-windows-gnu

Closes #16093

[breaking-change]
This commit is contained in:
Corey Richardson 2014-07-23 11:56:36 -07:00
parent 82fb413d37
commit 6b130e3dd9
77 changed files with 1609 additions and 810 deletions

57
configure vendored
View File

@ -291,6 +291,22 @@ envopt() {
fi fi
} }
to_llvm_triple() {
case $1 in
i686-w64-mingw32) echo i686-pc-windows-gnu ;;
x86_64-w64-mingw32) echo x86_64-pc-windows-gnu ;;
*) echo $1 ;;
esac
}
to_gnu_triple() {
case $1 in
i686-pc-windows-gnu) echo i686-w64-mingw32 ;;
x86_64-pc-windows-gnu) echo x86_64-w64-mingw32 ;;
*) echo $1 ;;
esac
}
msg "looking for configure programs" msg "looking for configure programs"
need_cmd cmp need_cmd cmp
need_cmd mkdir need_cmd mkdir
@ -350,37 +366,40 @@ case $CFG_OSTYPE in
# instead, msys defines $MSYSTEM which is MINGW32 on i686 and # instead, msys defines $MSYSTEM which is MINGW32 on i686 and
# MINGW64 on x86_64. # MINGW64 on x86_64.
CFG_CPUTYPE=i686 CFG_CPUTYPE=i686
CFG_OSTYPE=w64-mingw32 CFG_OSTYPE=pc-windows-gnu
if [ "$MSYSTEM" = MINGW64 ] if [ "$MSYSTEM" = MINGW64 ]
then then
CFG_CPUTYPE=x86_64 CFG_CPUTYPE=x86_64
CFG_OSTYPE=w64-mingw32
fi fi
;; ;;
MSYS*)
CFG_OSTYPE=pc-windows-gnu
;;
# Thad's Cygwin identifers below # Thad's Cygwin identifers below
# Vista 32 bit # Vista 32 bit
CYGWIN_NT-6.0) CYGWIN_NT-6.0)
CFG_OSTYPE=pc-mingw32 CFG_OSTYPE=pc-windows-gnu
CFG_CPUTYPE=i686 CFG_CPUTYPE=i686
;; ;;
# Vista 64 bit # Vista 64 bit
CYGWIN_NT-6.0-WOW64) CYGWIN_NT-6.0-WOW64)
CFG_OSTYPE=w64-mingw32 CFG_OSTYPE=pc-windows-gnu
CFG_CPUTYPE=x86_64 CFG_CPUTYPE=x86_64
;; ;;
# Win 7 32 bit # Win 7 32 bit
CYGWIN_NT-6.1) CYGWIN_NT-6.1)
CFG_OSTYPE=pc-mingw32 CFG_OSTYPE=pc-windows-gnu
CFG_CPUTYPE=i686 CFG_CPUTYPE=i686
;; ;;
# Win 7 64 bit # Win 7 64 bit
CYGWIN_NT-6.1-WOW64) CYGWIN_NT-6.1-WOW64)
CFG_OSTYPE=w64-mingw32 CFG_OSTYPE=pc-windows-gnu
CFG_CPUTYPE=x86_64 CFG_CPUTYPE=x86_64
;; ;;
@ -466,7 +485,6 @@ opt llvm-assertions 1 "build LLVM with assertions"
opt debug 1 "build with extra debug fun" opt debug 1 "build with extra debug fun"
opt ratchet-bench 0 "ratchet benchmarks" opt ratchet-bench 0 "ratchet benchmarks"
opt fast-make 0 "use .gitmodules as timestamp for submodule deps" opt fast-make 0 "use .gitmodules as timestamp for submodule deps"
opt mingw-cross 0 "cross-compile for win32 using mingw"
opt ccache 0 "invoke gcc/clang via ccache to reuse object files between builds" opt ccache 0 "invoke gcc/clang via ccache to reuse object files between builds"
opt local-rust 0 "use an installed rustc rather than downloading a snapshot" opt local-rust 0 "use an installed rustc rather than downloading a snapshot"
opt llvm-static-stdcpp 0 "statically link to libstdc++ for LLVM" opt llvm-static-stdcpp 0 "statically link to libstdc++ for LLVM"
@ -487,7 +505,6 @@ valopt llvm-root "" "set LLVM root"
valopt jemalloc-root "" "set directory where libjemalloc_pic.a is located" valopt jemalloc-root "" "set directory where libjemalloc_pic.a is located"
valopt build "${DEFAULT_BUILD}" "GNUs ./configure syntax LLVM build triple" valopt build "${DEFAULT_BUILD}" "GNUs ./configure syntax LLVM build triple"
valopt android-cross-path "/opt/ndk_standalone" "Android NDK standalone path" valopt android-cross-path "/opt/ndk_standalone" "Android NDK standalone path"
valopt mingw32-cross-path "" "MinGW32 cross compiler path"
# Many of these are saved below during the "writing configuration" step # Many of these are saved below during the "writing configuration" step
# (others are conditionally saved). # (others are conditionally saved).
@ -501,12 +518,18 @@ valopt_nosave target "${CFG_HOST}" "GNUs ./configure syntax LLVM target triples"
valopt_nosave mandir "${CFG_PREFIX}/share/man" "install man pages in PATH" valopt_nosave mandir "${CFG_PREFIX}/share/man" "install man pages in PATH"
valopt_nosave release-channel "dev" "the name of the release channel to build" valopt_nosave release-channel "dev" "the name of the release channel to build"
# Temporarily support old triples until buildbots get updated
CFG_BUILD=$(to_llvm_triple $CFG_BUILD)
putvar CFG_BUILD # Yes, this creates a duplicate entry, but the last one wins.
CFG_HOST=$(to_llvm_triple $CFG_HOST)
CFG_TARGET=$(to_llvm_triple $CFG_TARGET)
# On windows we just store the libraries in the bin directory because # On windows we just store the libraries in the bin directory because
# there's no rpath. This is where the build system itself puts libraries; # there's no rpath. This is where the build system itself puts libraries;
# --libdir is used to configure the installation directory. # --libdir is used to configure the installation directory.
# FIXME: This needs to parameterized over target triples. Do it in platform.mk # FIXME: This needs to parameterized over target triples. Do it in platform.mk
CFG_LIBDIR_RELATIVE=lib CFG_LIBDIR_RELATIVE=lib
if [ "$CFG_OSTYPE" = "pc-mingw32" ] || [ "$CFG_OSTYPE" = "w64-mingw32" ] if [ "$CFG_OSTYPE" = "pc-windows-gnu" ]
then then
CFG_LIBDIR_RELATIVE=bin CFG_LIBDIR_RELATIVE=bin
fi fi
@ -632,7 +655,7 @@ then
fi fi
BIN_SUF= BIN_SUF=
if [ "$CFG_OSTYPE" = "pc-mingw32" ] || [ "$CFG_OSTYPE" = "w64-mingw32" ] if [ "$CFG_OSTYPE" = "pc-windows-gnu" ]
then then
BIN_SUF=.exe BIN_SUF=.exe
fi fi
@ -1100,12 +1123,15 @@ do
if [ ${do_reconfigure} -ne 0 ] if [ ${do_reconfigure} -ne 0 ]
then then
msg "configuring LLVM for $t" # LLVM's configure doesn't recognize the new Windows triples yet
gnu_t=$(to_gnu_triple $t)
msg "configuring LLVM for $gnu_t"
LLVM_TARGETS="--enable-targets=x86,x86_64,arm,mips" LLVM_TARGETS="--enable-targets=x86,x86_64,arm,mips"
LLVM_BUILD="--build=$t" LLVM_BUILD="--build=$gnu_t"
LLVM_HOST="--host=$t" LLVM_HOST="--host=$gnu_t"
LLVM_TARGET="--target=$t" LLVM_TARGET="--target=$gnu_t"
# Disable unused LLVM features # Disable unused LLVM features
LLVM_OPTS="$LLVM_DBG_OPTS $LLVM_ASSERTION_OPTS --disable-docs --enable-bindings=none" LLVM_OPTS="$LLVM_DBG_OPTS $LLVM_ASSERTION_OPTS --disable-docs --enable-bindings=none"
@ -1119,7 +1145,7 @@ do
# (llvm's configure tries to find pthread first, so we have to disable it explicitly.) # (llvm's configure tries to find pthread first, so we have to disable it explicitly.)
# Also note that pthreads works badly on mingw-w64 systems: #8996 # Also note that pthreads works badly on mingw-w64 systems: #8996
case "$CFG_BUILD" in case "$CFG_BUILD" in
(*-mingw32) (*-windows-*)
LLVM_OPTS="$LLVM_OPTS --disable-pthreads" LLVM_OPTS="$LLVM_OPTS --disable-pthreads"
;; ;;
esac esac
@ -1269,6 +1295,7 @@ putvar CFG_HOST
putvar CFG_TARGET putvar CFG_TARGET
putvar CFG_LIBDIR_RELATIVE putvar CFG_LIBDIR_RELATIVE
putvar CFG_DISABLE_MANAGE_SUBMODULES putvar CFG_DISABLE_MANAGE_SUBMODULES
putvar CFG_ANDROID_CROSS_PATH
putvar CFG_MANDIR putvar CFG_MANDIR
# Avoid spurious warnings from clang by feeding it original source on # Avoid spurious warnings from clang by feeding it original source on

View File

@ -3,7 +3,7 @@ CFG_SDK_NAME_arm-apple-ios = iphoneos
CFG_SDK_ARCHS_arm-apple-ios = armv7 CFG_SDK_ARCHS_arm-apple-ios = armv7
ifneq ($(findstring darwin,$(CFG_OSTYPE)),) ifneq ($(findstring darwin,$(CFG_OSTYPE)),)
CFG_IOS_SDK = $(shell xcrun --show-sdk-path -sdk iphoneos 2>/dev/null) CFG_IOS_SDK = $(shell xcrun --show-sdk-path -sdk iphoneos 2>/dev/null)
CFG_IOS_FLAGS = -target armv7-apple-darwin -isysroot $(CFG_IOS_SDK) -mios-version-min=7.0 CFG_IOS_FLAGS = -target armv7-apple-ios -isysroot $(CFG_IOS_SDK) -mios-version-min=7.0
CC_arm-apple-ios = $(shell xcrun -find -sdk iphoneos clang) CC_arm-apple-ios = $(shell xcrun -find -sdk iphoneos clang)
CXX_arm-apple-ios = $(shell xcrun -find -sdk iphoneos clang++) CXX_arm-apple-ios = $(shell xcrun -find -sdk iphoneos clang++)
CPP_arm-apple-ios = $(shell xcrun -find -sdk iphoneos clang++) CPP_arm-apple-ios = $(shell xcrun -find -sdk iphoneos clang++)
@ -32,3 +32,4 @@ CFG_RUN_arm-apple-ios = $(2)
CFG_RUN_TARG_arm-apple-ios = $(call CFG_RUN_arm-apple-ios,,$(2)) CFG_RUN_TARG_arm-apple-ios = $(call CFG_RUN_arm-apple-ios,,$(2))
RUSTC_FLAGS_arm-apple-ios := -C relocation_model=pic RUSTC_FLAGS_arm-apple-ios := -C relocation_model=pic
RUSTC_CROSS_FLAGS_arm-apple-ios :=-C relocation_model=pic RUSTC_CROSS_FLAGS_arm-apple-ios :=-C relocation_model=pic
CFG_GNU_TRIPLE_arm-apple-ios := arm-apple-ios

View File

@ -26,3 +26,4 @@ CFG_RUN_arm-linux-androideabi=
CFG_RUN_TARG_arm-linux-androideabi= CFG_RUN_TARG_arm-linux-androideabi=
RUSTC_FLAGS_arm-linux-androideabi := RUSTC_FLAGS_arm-linux-androideabi :=
RUSTC_CROSS_FLAGS_arm-linux-androideabi := RUSTC_CROSS_FLAGS_arm-linux-androideabi :=
CFG_GNU_TRIPLE_arm-linux-androideabi := arm-linux-androideabi

View File

@ -27,3 +27,4 @@ CFG_RUN_arm-unknown-linux-gnueabi=$(2)
CFG_RUN_TARG_arm-unknown-linux-gnueabi=$(call CFG_RUN_arm-unknown-linux-gnueabi,,$(2)) CFG_RUN_TARG_arm-unknown-linux-gnueabi=$(call CFG_RUN_arm-unknown-linux-gnueabi,,$(2))
RUSTC_FLAGS_arm-unknown-linux-gnueabi := RUSTC_FLAGS_arm-unknown-linux-gnueabi :=
RUSTC_CROSS_FLAGS_arm-unknown-linux-gnueabi := RUSTC_CROSS_FLAGS_arm-unknown-linux-gnueabi :=
CFG_GNU_TRIPLE_arm-unknown-linux-gnueabi := arm-unknown-linux-gnueabi

View File

@ -27,3 +27,4 @@ CFG_RUN_arm-unknown-linux-gnueabihf=$(2)
CFG_RUN_TARG_arm-unknown-linux-gnueabihf=$(call CFG_RUN_arm-unknown-linux-gnueabihf,,$(2)) CFG_RUN_TARG_arm-unknown-linux-gnueabihf=$(call CFG_RUN_arm-unknown-linux-gnueabihf,,$(2))
RUSTC_FLAGS_arm-unknown-linux-gnueabihf := -C target-feature=+v6,+vfp2 RUSTC_FLAGS_arm-unknown-linux-gnueabihf := -C target-feature=+v6,+vfp2
RUSTC_CROSS_FLAGS_arm-unknown-linux-gnueabihf := RUSTC_CROSS_FLAGS_arm-unknown-linux-gnueabihf :=
CFG_GNU_TRIPLE_arm-unknown-linux-gnueabihf := arm-unknown-linux-gnueabihf

View File

@ -31,3 +31,4 @@ CFG_LDPATH_i386-apple-ios =
CFG_RUN_i386-apple-ios = $(2) CFG_RUN_i386-apple-ios = $(2)
CFG_RUN_TARG_i386-apple-ios = $(call CFG_RUN_i386-apple-ios,,$(2)) CFG_RUN_TARG_i386-apple-ios = $(call CFG_RUN_i386-apple-ios,,$(2))
CFG_JEMALLOC_CFLAGS_i386-apple-ios = -target i386-apple-ios -Wl,-syslibroot $(CFG_IOSSIM_SDK) -Wl,-no_compact_unwind CFG_JEMALLOC_CFLAGS_i386-apple-ios = -target i386-apple-ios -Wl,-syslibroot $(CFG_IOSSIM_SDK) -Wl,-no_compact_unwind
CFG_GNU_TRIPLE_i386-apple-ios := i386-apple-ios

View File

@ -1,29 +0,0 @@
# i586-mingw32msvc configuration
CC_i586-mingw32msvc=$(CFG_MINGW32_CROSS_PATH)/bin/i586-mingw32msvc-gcc
CXX_i586-mingw32msvc=$(CFG_MINGW32_CROSS_PATH)/bin/i586-mingw32msvc-g++
CPP_i586-mingw32msvc=$(CFG_MINGW32_CROSS_PATH)/bin/i586-mingw32msvc-cpp
AR_i586-mingw32msvc=$(CFG_MINGW32_CROSS_PATH)/bin/i586-mingw32msvc-ar
CFG_LIB_NAME_i586-mingw32msvc=$(1).dll
CFG_STATIC_LIB_NAME_i586-mingw32msvc=$(1).lib
CFG_LIB_GLOB_i586-mingw32msvc=$(1)-*.dll
CFG_LIB_DSYM_GLOB_i586-mingw32msvc=$(1)-*.dylib.dSYM
CFG_CFLAGS_i586-mingw32msvc := -march=i586 -m32 $(CFLAGS)
CFG_GCCISH_CFLAGS_i586-mingw32msvc := -Wall -Werror -g -march=i586 -m32 $(CFLAGS)
CFG_GCCISH_CXXFLAGS_i586-mingw32msvc := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_i586-mingw32msvc := -shared -g -m32
CFG_GCCISH_DEF_FLAG_i586-mingw32msvc :=
CFG_GCCISH_PRE_LIB_FLAGS_i586-mingw32msvc :=
CFG_GCCISH_POST_LIB_FLAGS_i586-mingw32msvc :=
CFG_DEF_SUFFIX_i586-mingw32msvc := .mingw32.def
CFG_LLC_FLAGS_i586-mingw32msvc :=
CFG_INSTALL_NAME_i586-mingw32msvc =
CFG_EXE_SUFFIX_i586-mingw32msvc := .exe
CFG_WINDOWSY_i586-mingw32msvc := 1
CFG_UNIXY_i586-mingw32msvc :=
CFG_PATH_MUNGE_i586-mingw32msvc := $(strip perl -i.bak -p \
-e 's@\\(\S)@/\1@go;' \
-e 's@^/([a-zA-Z])/@\1:/@o;')
CFG_LDPATH_i586-mingw32msvc :=
CFG_RUN_i586-mingw32msvc=
CFG_RUN_TARG_i586-mingw32msvc=

View File

@ -24,4 +24,4 @@ CFG_PATH_MUNGE_i686-apple-darwin := true
CFG_LDPATH_i686-apple-darwin := CFG_LDPATH_i686-apple-darwin :=
CFG_RUN_i686-apple-darwin=$(2) CFG_RUN_i686-apple-darwin=$(2)
CFG_RUN_TARG_i686-apple-darwin=$(call CFG_RUN_i686-apple-darwin,,$(2)) CFG_RUN_TARG_i686-apple-darwin=$(call CFG_RUN_i686-apple-darwin,,$(2))
CFG_GNU_TRIPLE_i686-apple-darwin := i686-apple-darwin

View File

@ -0,0 +1,28 @@
# i686-pc-windows-gnu configuration
CROSS_PREFIX_i686-pc-windows-gnu=i686-pc-windows-gnu-
CC_i686-pc-windows-gnu=gcc
CXX_i686-pc-windows-gnu=g++
CPP_i686-pc-windows-gnu=gcc -E
AR_i686-pc-windows-gnu=ar
CFG_LIB_NAME_i686-pc-windows-gnu=$(1).dll
CFG_STATIC_LIB_NAME_i686-pc-windows-gnu=$(1).lib
CFG_LIB_GLOB_i686-pc-windows-gnu=$(1)-*.dll
CFG_LIB_DSYM_GLOB_i686-pc-windows-gnu=$(1)-*.dylib.dSYM
CFG_CFLAGS_i686-pc-windows-gnu := -march=i686 -m32 -D_WIN32_WINNT=0x0600 $(CFLAGS)
CFG_GCCISH_CFLAGS_i686-pc-windows-gnu := -Wall -Werror -g -m32 -D_WIN32_WINNT=0x0600 $(CFLAGS)
CFG_GCCISH_CXXFLAGS_i686-pc-windows-gnu := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_i686-pc-windows-gnu := -shared -g -m32
CFG_GCCISH_DEF_FLAG_i686-pc-windows-gnu :=
CFG_GCCISH_PRE_LIB_FLAGS_i686-pc-windows-gnu :=
CFG_GCCISH_POST_LIB_FLAGS_i686-pc-windows-gnu :=
CFG_DEF_SUFFIX_i686-pc-windows-gnu := .windows.def
CFG_LLC_FLAGS_i686-pc-windows-gnu :=
CFG_INSTALL_NAME_i686-pc-windows-gnu =
CFG_EXE_SUFFIX_i686-pc-windows-gnu := .exe
CFG_WINDOWSY_i686-pc-windows-gnu := 1
CFG_UNIXY_i686-pc-windows-gnu :=
CFG_PATH_MUNGE_i686-pc-windows-gnu :=
CFG_LDPATH_i686-pc-windows-gnu :=$(CFG_LDPATH_i686-pc-windows-gnu):$(PATH)
CFG_RUN_i686-pc-windows-gnu=PATH="$(CFG_LDPATH_i686-pc-windows-gnu):$(1)" $(2)
CFG_RUN_TARG_i686-pc-windows-gnu=$(call CFG_RUN_i686-pc-windows-gnu,$(HLIB$(1)_H_$(CFG_BUILD)),$(2))
CFG_GNU_TRIPLE_i686-pc-windows-gnu := i686-w64-mingw32

View File

@ -24,4 +24,4 @@ CFG_PATH_MUNGE_i686-unknown-linux-gnu := true
CFG_LDPATH_i686-unknown-linux-gnu := CFG_LDPATH_i686-unknown-linux-gnu :=
CFG_RUN_i686-unknown-linux-gnu=$(2) CFG_RUN_i686-unknown-linux-gnu=$(2)
CFG_RUN_TARG_i686-unknown-linux-gnu=$(call CFG_RUN_i686-unknown-linux-gnu,,$(2)) CFG_RUN_TARG_i686-unknown-linux-gnu=$(call CFG_RUN_i686-unknown-linux-gnu,,$(2))
CFG_GNU_TRIPLE_i686-unknown-linux-gnu := i686-unknown-linux-gnu

View File

@ -1,31 +0,0 @@
# i686-w64-mingw32 configuration
CROSS_PREFIX_i686-w64-mingw32=i686-w64-mingw32-
CC_i686-w64-mingw32=gcc
CXX_i686-w64-mingw32=g++
CPP_i686-w64-mingw32=gcc -E
AR_i686-w64-mingw32=ar
CFG_LIB_NAME_i686-w64-mingw32=$(1).dll
CFG_STATIC_LIB_NAME_i686-w64-mingw32=$(1).lib
CFG_LIB_GLOB_i686-w64-mingw32=$(1)-*.dll
CFG_LIB_DSYM_GLOB_i686-w64-mingw32=$(1)-*.dylib.dSYM
CFG_CFLAGS_i686-w64-mingw32 := -march=i686 -m32 -D_WIN32_WINNT=0x0600 $(CFLAGS)
CFG_GCCISH_CFLAGS_i686-w64-mingw32 := -Wall -Werror -g -m32 -D_WIN32_WINNT=0x0600 $(CFLAGS)
CFG_GCCISH_CXXFLAGS_i686-w64-mingw32 := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_i686-w64-mingw32 := -shared -g -m32
CFG_GCCISH_DEF_FLAG_i686-w64-mingw32 :=
CFG_GCCISH_PRE_LIB_FLAGS_i686-w64-mingw32 :=
CFG_GCCISH_POST_LIB_FLAGS_i686-w64-mingw32 :=
CFG_DEF_SUFFIX_i686-w64-mingw32 := .mingw32.def
CFG_LLC_FLAGS_i686-w64-mingw32 :=
CFG_INSTALL_NAME_i686-w64-mingw32 =
CFG_EXE_SUFFIX_i686-w64-mingw32 := .exe
CFG_WINDOWSY_i686-w64-mingw32 := 1
CFG_UNIXY_i686-w64-mingw32 :=
CFG_PATH_MUNGE_i686-w64-mingw32 :=
CFG_LDPATH_i686-w64-mingw32 :=$(CFG_LDPATH_i686-w64-mingw32):$(PATH)
CFG_RUN_i686-w64-mingw32=PATH="$(CFG_LDPATH_i686-w64-mingw32):$(1)" $(2)
CFG_RUN_TARG_i686-w64-mingw32=$(call CFG_RUN_i686-w64-mingw32,$(HLIB$(1)_H_$(CFG_BUILD)),$(2))
# Stop rustc from OOMing when building itself (I think)
RUSTC_FLAGS_i686-w64-mingw32=-C link-args="-Wl,--large-address-aware"
RUSTC_CROSS_FLAGS_i686-w64-mingw32 :=

View File

@ -25,3 +25,4 @@ CFG_LDPATH_mips-unknown-linux-gnu :=
CFG_RUN_mips-unknown-linux-gnu= CFG_RUN_mips-unknown-linux-gnu=
CFG_RUN_TARG_mips-unknown-linux-gnu= CFG_RUN_TARG_mips-unknown-linux-gnu=
RUSTC_FLAGS_mips-unknown-linux-gnu := -C target-cpu=mips32r2 -C target-feature="+mips32r2,+o32" -C soft-float RUSTC_FLAGS_mips-unknown-linux-gnu := -C target-cpu=mips32r2 -C target-feature="+mips32r2,+o32" -C soft-float
CFG_GNU_TRIPLE_mips-unknown-linux-gnu := mips-unknown-linux-gnu

View File

@ -1,27 +0,0 @@
# mipsel-linux configuration
CC_mipsel-linux=mipsel-linux-gcc
CXX_mipsel-linux=mipsel-linux-g++
CPP_mipsel-linux=mipsel-linux-gcc
AR_mipsel-linux=mipsel-linux-ar
CFG_LIB_NAME_mipsel-linux=lib$(1).so
CFG_STATIC_LIB_NAME_mipsel-linux=lib$(1).a
CFG_LIB_GLOB_mipsel-linux=lib$(1)-*.so
CFG_LIB_DSYM_GLOB_mipsel-linux=lib$(1)-*.dylib.dSYM
CFG_CFLAGS_mipsel-linux := -mips32 -mabi=32 $(CFLAGS)
CFG_GCCISH_CFLAGS_mipsel-linux := -Wall -g -fPIC -mips32 -mabi=32 $(CFLAGS)
CFG_GCCISH_CXXFLAGS_mipsel-linux := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_mipsel-linux := -shared -fPIC -g -mips32
CFG_GCCISH_DEF_FLAG_mipsel-linux := -Wl,--export-dynamic,--dynamic-list=
CFG_GCCISH_PRE_LIB_FLAGS_mipsel-linux := -Wl,-whole-archive
CFG_GCCISH_POST_LIB_FLAGS_mipsel-linux := -Wl,-no-whole-archive
CFG_DEF_SUFFIX_mipsel-linux := .linux.def
CFG_LLC_FLAGS_mipsel-linux :=
CFG_INSTALL_NAME_mipsel-linux =
CFG_EXE_SUFFIX_mipsel-linux :=
CFG_WINDOWSY_mipsel-linux :=
CFG_UNIXY_mipsel-linux := 1
CFG_PATH_MUNGE_mipsel-linux := true
CFG_LDPATH_mipsel-linux :=
CFG_RUN_mipsel-linux=
CFG_RUN_TARG_mipsel-linux=
RUSTC_FLAGS_mipsel-linux := -C target-cpu=mips32 -C target-feature="+mips32,+o32"

View File

@ -0,0 +1,28 @@
# mipsel-unknown-linux-gnu configuration
CC_mipsel-unknown-linux-gnu=mipsel-unknown-linux-gnu-gcc
CXX_mipsel-unknown-linux-gnu=mipsel-unknown-linux-gnu-g++
CPP_mipsel-unknown-linux-gnu=mipsel-unknown-linux-gnu-gcc
AR_mipsel-unknown-linux-gnu=mipsel-unknown-linux-gnu-ar
CFG_LIB_NAME_mipsel-unknown-linux-gnu=lib$(1).so
CFG_STATIC_LIB_NAME_mipsel-unknown-linux-gnu=lib$(1).a
CFG_LIB_GLOB_mipsel-unknown-linux-gnu=lib$(1)-*.so
CFG_LIB_DSYM_GLOB_mipsel-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
CFG_CFLAGS_mipsel-unknown-linux-gnu := -mips32 -mabi=32 $(CFLAGS)
CFG_GCCISH_CFLAGS_mipsel-unknown-linux-gnu := -Wall -g -fPIC -mips32 -mabi=32 $(CFLAGS)
CFG_GCCISH_CXXFLAGS_mipsel-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_mipsel-unknown-linux-gnu := -shared -fPIC -g -mips32
CFG_GCCISH_DEF_FLAG_mipsel-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
CFG_GCCISH_PRE_LIB_FLAGS_mipsel-unknown-linux-gnu := -Wl,-whole-archive
CFG_GCCISH_POST_LIB_FLAGS_mipsel-unknown-linux-gnu := -Wl,-no-whole-archive
CFG_DEF_SUFFIX_mipsel-unknown-linux-gnu := .linux.def
CFG_LLC_FLAGS_mipsel-unknown-linux-gnu :=
CFG_INSTALL_NAME_mipsel-unknown-linux-gnu =
CFG_EXE_SUFFIX_mipsel-unknown-linux-gnu :=
CFG_WINDOWSY_mipsel-unknown-linux-gnu :=
CFG_UNIXY_mipsel-unknown-linux-gnu := 1
CFG_PATH_MUNGE_mipsel-unknown-linux-gnu := true
CFG_LDPATH_mipsel-unknown-linux-gnu :=
CFG_RUN_mipsel-unknown-linux-gnu=
CFG_RUN_TARG_mipsel-unknown-linux-gnu=
RUSTC_FLAGS_mipsel-unknown-linux-gnu := -C target-cpu=mips32 -C target-feature="+mips32,+o32"
CFG_GNU_TRIPLE_mipsel-unknown-linux-gnu := mipsel-unknown-linux-gnu

View File

@ -24,3 +24,4 @@ CFG_PATH_MUNGE_x86_64-apple-darwin := true
CFG_LDPATH_x86_64-apple-darwin := CFG_LDPATH_x86_64-apple-darwin :=
CFG_RUN_x86_64-apple-darwin=$(2) CFG_RUN_x86_64-apple-darwin=$(2)
CFG_RUN_TARG_x86_64-apple-darwin=$(call CFG_RUN_x86_64-apple-darwin,,$(2)) CFG_RUN_TARG_x86_64-apple-darwin=$(call CFG_RUN_x86_64-apple-darwin,,$(2))
CFG_GNU_TRIPLE_x86_64-apple-darwin := x86_64-apple-darwin

View File

@ -0,0 +1,28 @@
# x86_64-pc-windows-gnu configuration
CROSS_PREFIX_x86_64-pc-windows-gnu=x86_64-pc-windows-gnu-
CC_x86_64-pc-windows-gnu=gcc
CXX_x86_64-pc-windows-gnu=g++
CPP_x86_64-pc-windows-gnu=gcc -E
AR_x86_64-pc-windows-gnu=ar
CFG_LIB_NAME_x86_64-pc-windows-gnu=$(1).dll
CFG_STATIC_LIB_NAME_x86_64-pc-windows-gnu=$(1).lib
CFG_LIB_GLOB_x86_64-pc-windows-gnu=$(1)-*.dll
CFG_LIB_DSYM_GLOB_x86_64-pc-windows-gnu=$(1)-*.dylib.dSYM
CFG_CFLAGS_x86_64-pc-windows-gnu := -m64 -D_WIN32_WINNT=0x0600 $(CFLAGS)
CFG_GCCISH_CFLAGS_x86_64-pc-windows-gnu := -Wall -Werror -g -m64 -D_WIN32_WINNT=0x0600 $(CFLAGS)
CFG_GCCISH_CXXFLAGS_x86_64-pc-windows-gnu := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_x86_64-pc-windows-gnu := -shared -g -m64
CFG_GCCISH_DEF_FLAG_x86_64-pc-windows-gnu :=
CFG_GCCISH_PRE_LIB_FLAGS_x86_64-pc-windows-gnu :=
CFG_GCCISH_POST_LIB_FLAGS_x86_64-pc-windows-gnu :=
CFG_DEF_SUFFIX_x86_64-pc-windows-gnu := .windows.def
CFG_LLC_FLAGS_x86_64-pc-windows-gnu :=
CFG_INSTALL_NAME_x86_64-pc-windows-gnu =
CFG_EXE_SUFFIX_x86_64-pc-windows-gnu := .exe
CFG_WINDOWSY_x86_64-pc-windows-gnu := 1
CFG_UNIXY_x86_64-pc-windows-gnu :=
CFG_PATH_MUNGE_x86_64-pc-windows-gnu :=
CFG_LDPATH_x86_64-pc-windows-gnu :=$(CFG_LDPATH_x86_64-pc-windows-gnu):$(PATH)
CFG_RUN_x86_64-pc-windows-gnu=PATH="$(CFG_LDPATH_x86_64-pc-windows-gnu):$(1)" $(2)
CFG_RUN_TARG_x86_64-pc-windows-gnu=$(call CFG_RUN_x86_64-pc-windows-gnu,$(HLIB$(1)_H_$(CFG_BUILD)),$(2))
CFG_GNU_TRIPLE_x86_64-pc-windows-gnu := x86_64-w64-mingw32

View File

@ -23,3 +23,4 @@ CFG_PATH_MUNGE_x86_64-unknown-dragonfly :=
CFG_LDPATH_x86_64-unknown-dragonfly := CFG_LDPATH_x86_64-unknown-dragonfly :=
CFG_RUN_x86_64-unknown-dragonfly=$(2) CFG_RUN_x86_64-unknown-dragonfly=$(2)
CFG_RUN_TARG_x86_64-unknown-dragonfly=$(call CFG_RUN_x86_64-unknown-dragonfly,,$(2)) CFG_RUN_TARG_x86_64-unknown-dragonfly=$(call CFG_RUN_x86_64-unknown-dragonfly,,$(2))
CFG_GNU_TRIPLE_x86_64-unknown-dragonfly := x86_64-unknown-dragonfly

View File

@ -23,3 +23,4 @@ CFG_PATH_MUNGE_x86_64-unknown-freebsd :=
CFG_LDPATH_x86_64-unknown-freebsd := CFG_LDPATH_x86_64-unknown-freebsd :=
CFG_RUN_x86_64-unknown-freebsd=$(2) CFG_RUN_x86_64-unknown-freebsd=$(2)
CFG_RUN_TARG_x86_64-unknown-freebsd=$(call CFG_RUN_x86_64-unknown-freebsd,,$(2)) CFG_RUN_TARG_x86_64-unknown-freebsd=$(call CFG_RUN_x86_64-unknown-freebsd,,$(2))
CFG_GNU_TRIPLE_x86_64-unknown-freebsd := x86_64-unknown-freebsd

View File

@ -24,3 +24,5 @@ CFG_PATH_MUNGE_x86_64-unknown-linux-gnu := true
CFG_LDPATH_x86_64-unknown-linux-gnu := CFG_LDPATH_x86_64-unknown-linux-gnu :=
CFG_RUN_x86_64-unknown-linux-gnu=$(2) CFG_RUN_x86_64-unknown-linux-gnu=$(2)
CFG_RUN_TARG_x86_64-unknown-linux-gnu=$(call CFG_RUN_x86_64-unknown-linux-gnu,,$(2)) CFG_RUN_TARG_x86_64-unknown-linux-gnu=$(call CFG_RUN_x86_64-unknown-linux-gnu,,$(2))
CFG_GNU_TRIPLE_x86_64-unknown-linux-gnu := x86_64-unknown-linux-gnu

View File

@ -1,28 +0,0 @@
# x86_64-w64-mingw32 configuration
CROSS_PREFIX_x86_64-w64-mingw32=x86_64-w64-mingw32-
CC_x86_64-w64-mingw32=gcc
CXX_x86_64-w64-mingw32=g++
CPP_x86_64-w64-mingw32=gcc -E
AR_x86_64-w64-mingw32=ar
CFG_LIB_NAME_x86_64-w64-mingw32=$(1).dll
CFG_STATIC_LIB_NAME_x86_64-w64-mingw32=$(1).lib
CFG_LIB_GLOB_x86_64-w64-mingw32=$(1)-*.dll
CFG_LIB_DSYM_GLOB_x86_64-w64-mingw32=$(1)-*.dylib.dSYM
CFG_CFLAGS_x86_64-w64-mingw32 := -m64 -D_WIN32_WINNT=0x0600 $(CFLAGS)
CFG_GCCISH_CFLAGS_x86_64-w64-mingw32 := -Wall -Werror -g -m64 -D_WIN32_WINNT=0x0600 $(CFLAGS)
CFG_GCCISH_CXXFLAGS_x86_64-w64-mingw32 := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_x86_64-w64-mingw32 := -shared -g -m64
CFG_GCCISH_DEF_FLAG_x86_64-w64-mingw32 :=
CFG_GCCISH_PRE_LIB_FLAGS_x86_64-w64-mingw32 :=
CFG_GCCISH_POST_LIB_FLAGS_x86_64-w64-mingw32 :=
CFG_DEF_SUFFIX_x86_64-w64-mingw32 := .mingw32.def
CFG_LLC_FLAGS_x86_64-w64-mingw32 :=
CFG_INSTALL_NAME_x86_64-w64-mingw32 =
CFG_EXE_SUFFIX_x86_64-w64-mingw32 := .exe
CFG_WINDOWSY_x86_64-w64-mingw32 := 1
CFG_UNIXY_x86_64-w64-mingw32 :=
CFG_PATH_MUNGE_x86_64-w64-mingw32 :=
CFG_LDPATH_x86_64-w64-mingw32 :=$(CFG_LDPATH_x86_64-w64-mingw32):$(PATH)
CFG_RUN_x86_64-w64-mingw32=PATH="$(CFG_LDPATH_x86_64-w64-mingw32):$(1)" $(2)
CFG_RUN_TARG_x86_64-w64-mingw32=$(call CFG_RUN_x86_64-w64-mingw32,$(HLIB$(1)_H_$(CFG_BUILD)),$(2))
RUSTC_CROSS_FLAGS_x86_64-w64-mingw32 :=

View File

@ -311,7 +311,6 @@ export CFG_RELEASE
export CFG_PACKAGE_NAME export CFG_PACKAGE_NAME
export CFG_BUILD export CFG_BUILD
export CFG_LLVM_ROOT export CFG_LLVM_ROOT
export CFG_ENABLE_MINGW_CROSS
export CFG_PREFIX export CFG_PREFIX
export CFG_LIBDIR export CFG_LIBDIR
export CFG_LIBDIR_RELATIVE export CFG_LIBDIR_RELATIVE

View File

@ -176,7 +176,7 @@ $$(JEMALLOC_LOCAL_$(1)): $$(JEMALLOC_DEPS) $$(MKFILE_DEPS)
@$$(call E, make: jemalloc) @$$(call E, make: jemalloc)
cd "$$(JEMALLOC_BUILD_DIR_$(1))"; "$(S)src/jemalloc/configure" \ cd "$$(JEMALLOC_BUILD_DIR_$(1))"; "$(S)src/jemalloc/configure" \
$$(JEMALLOC_ARGS_$(1)) --with-jemalloc-prefix=je_ $(CFG_JEMALLOC_FLAGS) \ $$(JEMALLOC_ARGS_$(1)) --with-jemalloc-prefix=je_ $(CFG_JEMALLOC_FLAGS) \
--build=$(CFG_BUILD) --host=$(1) \ --build=$$(CFG_GNU_TRIPLE_$(CFG_BUILD)) --host=$$(CFG_GNU_TRIPLE_$(1)) \
CC="$$(CC_$(1))" \ CC="$$(CC_$(1))" \
AR="$$(AR_$(1))" \ AR="$$(AR_$(1))" \
RANLIB="$$(AR_$(1)) s" \ RANLIB="$$(AR_$(1)) s" \

View File

@ -75,9 +75,8 @@ def full_snapshot_name(date, rev, platform, hsh):
def get_kernel(triple): def get_kernel(triple):
os_name = triple.split('-')[-1] os_name = triple.split('-')[2]
#scrub(os.getenv("CFG_ENABLE_MINGW_CROSS")): if os_name == "windows":
if os_name == "nt" or os_name == "mingw32":
return "winnt" return "winnt"
if os_name == "darwin": if os_name == "darwin":
return "macos" return "macos"

View File

@ -19,7 +19,7 @@ use driver::config::NoDebugInfo;
use driver::session::Session; use driver::session::Session;
use driver::config; use driver::config;
use metadata::common::LinkMeta; use metadata::common::LinkMeta;
use metadata::{encoder, cstore, filesearch, csearch, loader, creader}; use metadata::{encoder, cstore, filesearch, csearch, creader};
use middle::trans::context::CrateContext; use middle::trans::context::CrateContext;
use middle::trans::common::gensym_name; use middle::trans::common::gensym_name;
use middle::ty; use middle::ty;
@ -36,7 +36,6 @@ use std::str;
use std::string::String; use std::string::String;
use flate; use flate;
use serialize::hex::ToHex; use serialize::hex::ToHex;
use syntax::abi;
use syntax::ast; use syntax::ast;
use syntax::ast_map::{PathElem, PathElems, PathName}; use syntax::ast_map::{PathElem, PathElems, PathName};
use syntax::ast_map; use syntax::ast_map;
@ -363,17 +362,8 @@ pub fn mangle_internal_name_by_path_and_seq(path: PathElems, flav: &str) -> Stri
pub fn get_cc_prog(sess: &Session) -> String { pub fn get_cc_prog(sess: &Session) -> String {
match sess.opts.cg.linker { match sess.opts.cg.linker {
Some(ref linker) => return linker.to_string(), Some(ref linker) => return linker.to_string(),
None => {} None => sess.target.target.options.linker.clone(),
} }
// In the future, FreeBSD will use clang as default compiler.
// It would be flexible to use cc (system's default C compiler)
// instead of hard-coded gcc.
// For Windows, there is no cc command, so we add a condition to make it use gcc.
match sess.targ_cfg.os {
abi::OsWindows => "gcc",
_ => "cc",
}.to_string()
} }
pub fn remove(sess: &Session, path: &Path) { pub fn remove(sess: &Session, path: &Path) {
@ -397,7 +387,7 @@ pub fn link_binary(sess: &Session,
for &crate_type in sess.crate_types.borrow().iter() { for &crate_type in sess.crate_types.borrow().iter() {
if invalid_output_for_target(sess, crate_type) { if invalid_output_for_target(sess, crate_type) {
sess.bug(format!("invalid output type `{}` for target os `{}`", sess.bug(format!("invalid output type `{}` for target os `{}`",
crate_type, sess.targ_cfg.os).as_slice()); crate_type, sess.opts.target_triple).as_slice());
} }
let out_file = link_binary_output(sess, trans, crate_type, outputs, let out_file = link_binary_output(sess, trans, crate_type, outputs,
crate_name); crate_name);
@ -427,17 +417,20 @@ pub fn link_binary(sess: &Session,
/// interaction with Rust code through static library is the only /// interaction with Rust code through static library is the only
/// option for now /// option for now
pub fn default_output_for_target(sess: &Session) -> config::CrateType { pub fn default_output_for_target(sess: &Session) -> config::CrateType {
match sess.targ_cfg.os { if !sess.target.target.options.executables {
abi::OsiOS => config::CrateTypeStaticlib, config::CrateTypeStaticlib
_ => config::CrateTypeExecutable } else {
config::CrateTypeExecutable
} }
} }
/// Checks if target supports crate_type as output /// Checks if target supports crate_type as output
pub fn invalid_output_for_target(sess: &Session, pub fn invalid_output_for_target(sess: &Session,
crate_type: config::CrateType) -> bool { crate_type: config::CrateType) -> bool {
match (sess.targ_cfg.os, crate_type) { match (sess.target.target.options.dynamic_linking,
(abi::OsiOS, config::CrateTypeDylib) => true, sess.target.target.options.executables, crate_type) {
(false, _, config::CrateTypeDylib) => true,
(_, false, config::CrateTypeExecutable) => true,
_ => false _ => false
} }
} }
@ -459,15 +452,8 @@ pub fn filename_for_input(sess: &Session,
out_filename.with_filename(format!("lib{}.rlib", libname)) out_filename.with_filename(format!("lib{}.rlib", libname))
} }
config::CrateTypeDylib => { config::CrateTypeDylib => {
let (prefix, suffix) = match sess.targ_cfg.os { let (prefix, suffix) = (sess.target.target.options.dll_prefix.as_slice(),
abi::OsWindows => (loader::WIN32_DLL_PREFIX, loader::WIN32_DLL_SUFFIX), sess.target.target.options.dll_suffix.as_slice());
abi::OsMacos => (loader::MACOS_DLL_PREFIX, loader::MACOS_DLL_SUFFIX),
abi::OsLinux => (loader::LINUX_DLL_PREFIX, loader::LINUX_DLL_SUFFIX),
abi::OsAndroid => (loader::ANDROID_DLL_PREFIX, loader::ANDROID_DLL_SUFFIX),
abi::OsFreebsd => (loader::FREEBSD_DLL_PREFIX, loader::FREEBSD_DLL_SUFFIX),
abi::OsDragonfly => (loader::DRAGONFLY_DLL_PREFIX, loader::DRAGONFLY_DLL_SUFFIX),
abi::OsiOS => unreachable!(),
};
out_filename.with_filename(format!("{}{}{}", out_filename.with_filename(format!("{}{}{}",
prefix, prefix,
libname, libname,
@ -477,15 +463,8 @@ pub fn filename_for_input(sess: &Session,
out_filename.with_filename(format!("lib{}.a", libname)) out_filename.with_filename(format!("lib{}.a", libname))
} }
config::CrateTypeExecutable => { config::CrateTypeExecutable => {
match sess.targ_cfg.os { let suffix = sess.target.target.options.exe_suffix.as_slice();
abi::OsWindows => out_filename.with_extension("exe"), out_filename.with_filename(format!("{}{}", libname, suffix))
abi::OsMacos |
abi::OsLinux |
abi::OsAndroid |
abi::OsFreebsd |
abi::OsDragonfly |
abi::OsiOS => out_filename.clone(),
}
} }
} }
} }
@ -562,7 +541,8 @@ fn link_rlib<'a>(sess: &'a Session,
handler: handler, handler: handler,
dst: out_filename.clone(), dst: out_filename.clone(),
lib_search_paths: archive_search_paths(sess), lib_search_paths: archive_search_paths(sess),
os: sess.targ_cfg.os, slib_prefix: sess.target.target.options.staticlib_prefix.clone(),
slib_suffix: sess.target.target.options.staticlib_suffix.clone(),
maybe_ar_prog: sess.opts.cg.ar.clone() maybe_ar_prog: sess.opts.cg.ar.clone()
}; };
let mut ab = ArchiveBuilder::create(config); let mut ab = ArchiveBuilder::create(config);
@ -581,12 +561,12 @@ fn link_rlib<'a>(sess: &'a Session,
// symbol table of the archive. // symbol table of the archive.
ab.update_symbols(); ab.update_symbols();
let mut ab = match sess.targ_cfg.os { let mut ab = match sess.target.target.options.is_like_osx {
// For OSX/iOS, we must be careful to update symbols only when adding // For OSX/iOS, we must be careful to update symbols only when adding
// object files. We're about to start adding non-object files, so run // object files. We're about to start adding non-object files, so run
// `ar` now to process the object files. // `ar` now to process the object files.
abi::OsMacos | abi::OsiOS => ab.build().extend(), true => ab.build().extend(),
_ => ab, false => ab,
}; };
// Note that it is important that we add all of our non-object "magical // Note that it is important that we add all of our non-object "magical
@ -686,6 +666,13 @@ fn link_rlib<'a>(sess: &'a Session,
remove(sess, &bc_filename); remove(sess, &bc_filename);
} }
} }
// After adding all files to the archive, we need to update the
// symbol table of the archive. This currently dies on OSX (see
// #11162), and isn't necessary there anyway
if !sess.target.target.options.is_like_osx {
ab.update_symbols();
}
} }
None => {} None => {}
@ -734,11 +721,13 @@ fn write_rlib_bytecode_object_v1<T: Writer>(writer: &mut T,
// metadata file). // metadata file).
fn link_staticlib(sess: &Session, obj_filename: &Path, out_filename: &Path) { fn link_staticlib(sess: &Session, obj_filename: &Path, out_filename: &Path) {
let ab = link_rlib(sess, None, obj_filename, out_filename); let ab = link_rlib(sess, None, obj_filename, out_filename);
let mut ab = match sess.targ_cfg.os { let mut ab = match sess.target.target.options.is_like_osx {
abi::OsMacos | abi::OsiOS => ab.build().extend(), true => ab.build().extend(),
_ => ab, false => ab,
}; };
ab.add_native_library("morestack").unwrap(); if sess.target.target.options.morestack {
ab.add_native_library("morestack").unwrap();
}
ab.add_native_library("compiler-rt").unwrap(); ab.add_native_library("compiler-rt").unwrap();
let crates = sess.cstore.get_used_crates(cstore::RequireStatic); let crates = sess.cstore.get_used_crates(cstore::RequireStatic);
@ -791,9 +780,13 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
let pname = get_cc_prog(sess); let pname = get_cc_prog(sess);
let mut cmd = Command::new(pname.as_slice()); let mut cmd = Command::new(pname.as_slice());
cmd.args(sess.targ_cfg.target_strs.cc_args.as_slice()); cmd.args(sess.target.target.options.pre_link_args.as_slice());
link_args(&mut cmd, sess, dylib, tmpdir.path(), link_args(&mut cmd, sess, dylib, tmpdir.path(),
trans, obj_filename, out_filename); trans, obj_filename, out_filename);
cmd.args(sess.target.target.options.post_link_args.as_slice());
if !sess.target.target.options.no_compiler_rt {
cmd.arg("-lcompiler-rt");
}
if (sess.opts.debugging_opts & config::PRINT_LINK_ARGS) != 0 { if (sess.opts.debugging_opts & config::PRINT_LINK_ARGS) != 0 {
println!("{}", &cmd); println!("{}", &cmd);
@ -831,16 +824,15 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
// On OSX, debuggers need this utility to get run to do some munging of // On OSX, debuggers need this utility to get run to do some munging of
// the symbols // the symbols
if (sess.targ_cfg.os == abi::OsMacos || sess.targ_cfg.os == abi::OsiOS) if sess.target.target.options.is_like_osx && sess.opts.debuginfo != NoDebugInfo {
&& (sess.opts.debuginfo != NoDebugInfo) { match Command::new("dsymutil").arg(out_filename).output() {
match Command::new("dsymutil").arg(out_filename).output() { Ok(..) => {}
Ok(..) => {} Err(e) => {
Err(e) => { sess.err(format!("failed to run dsymutil: {}", e).as_slice());
sess.err(format!("failed to run dsymutil: {}", e).as_slice()); sess.abort_if_errors();
sess.abort_if_errors();
}
} }
} }
}
} }
fn link_args(cmd: &mut Command, fn link_args(cmd: &mut Command,
@ -854,10 +846,15 @@ fn link_args(cmd: &mut Command,
// The default library location, we need this to find the runtime. // The default library location, we need this to find the runtime.
// The location of crates will be determined as needed. // The location of crates will be determined as needed.
let lib_path = sess.target_filesearch().get_lib_path(); let lib_path = sess.target_filesearch().get_lib_path();
// target descriptor
let t = &sess.target.target;
cmd.arg("-L").arg(&lib_path); cmd.arg("-L").arg(&lib_path);
cmd.arg("-o").arg(out_filename).arg(obj_filename); cmd.arg("-o").arg(out_filename).arg(obj_filename);
// Stack growth requires statically linking a __morestack function. Note // Stack growth requires statically linking a __morestack function. Note
// that this is listed *before* all other libraries. Due to the usage of the // that this is listed *before* all other libraries. Due to the usage of the
// --as-needed flag below, the standard library may only be useful for its // --as-needed flag below, the standard library may only be useful for its
@ -874,17 +871,15 @@ fn link_args(cmd: &mut Command,
// all contents of this library. This way we're guaranteed that the linker // all contents of this library. This way we're guaranteed that the linker
// will include the __morestack symbol 100% of the time, always resolving // will include the __morestack symbol 100% of the time, always resolving
// references to it even if the object above didn't use it. // references to it even if the object above didn't use it.
match sess.targ_cfg.os { if t.options.morestack {
abi::OsMacos | abi::OsiOS => { if t.options.is_like_osx {
let morestack = lib_path.join("libmorestack.a"); let morestack = lib_path.join("libmorestack.a");
let mut v = b"-Wl,-force_load,".to_vec(); let mut v = b"-Wl,-force_load,".to_vec();
v.push_all(morestack.as_vec()); v.push_all(morestack.as_vec());
cmd.arg(v.as_slice()); cmd.arg(v.as_slice());
} } else {
_ => { cmd.args(["-Wl,--whole-archive", "-lmorestack", "-Wl,--no-whole-archive"]);
cmd.args(["-Wl,--whole-archive", "-lmorestack",
"-Wl,--no-whole-archive"]);
} }
} }
@ -895,60 +890,10 @@ fn link_args(cmd: &mut Command,
cmd.arg(obj_filename.with_extension("metadata.o")); cmd.arg(obj_filename.with_extension("metadata.o"));
} }
// We want to prevent the compiler from accidentally leaking in any system
// libraries, so we explicitly ask gcc to not link to any libraries by
// default. Note that this does not happen for windows because windows pulls
// in some large number of libraries and I couldn't quite figure out which
// subset we wanted.
//
// FIXME(#11937) we should invoke the system linker directly
if sess.targ_cfg.os != abi::OsWindows {
cmd.arg("-nodefaultlibs");
}
// Rust does its' own LTO // Rust does its' own LTO
cmd.arg("-fno-lto"); cmd.arg("-fno-lto");
// clang fails hard if -fno-use-linker-plugin is passed if t.options.is_like_osx {
if sess.targ_cfg.os == abi::OsWindows {
cmd.arg("-fno-use-linker-plugin");
}
// If we're building a dylib, we don't use --gc-sections because LLVM has
// already done the best it can do, and we also don't want to eliminate the
// metadata. If we're building an executable, however, --gc-sections drops
// the size of hello world from 1.8MB to 597K, a 67% reduction.
if !dylib && sess.targ_cfg.os != abi::OsMacos && sess.targ_cfg.os != abi::OsiOS {
cmd.arg("-Wl,--gc-sections");
}
let used_link_args = sess.cstore.get_used_link_args().borrow();
// Dynamically linked executables can be compiled as position independent if the default
// relocation model of position independent code is not changed. This is a requirement to take
// advantage of ASLR, as otherwise the functions in the executable are not randomized and can
// be used during an exploit of a vulnerability in any code.
if sess.targ_cfg.os == abi::OsLinux {
let mut args = sess.opts.cg.link_args.iter().chain(used_link_args.iter());
if !dylib && sess.opts.cg.relocation_model.as_slice() == "pic" &&
!args.any(|x| x.as_slice() == "-static") {
cmd.arg("-pie");
}
}
if sess.targ_cfg.os == abi::OsLinux || sess.targ_cfg.os == abi::OsDragonfly {
// GNU-style linkers will use this to omit linking to libraries which
// don't actually fulfill any relocations, but only for libraries which
// follow this flag. Thus, use it before specifying libraries to link to.
cmd.arg("-Wl,--as-needed");
// GNU-style linkers support optimization with -O. GNU ld doesn't need a
// numeric argument, but other linkers do.
if sess.opts.optimize == config::Default ||
sess.opts.optimize == config::Aggressive {
cmd.arg("-Wl,-O1");
}
} else if sess.targ_cfg.os == abi::OsMacos || sess.targ_cfg.os == abi::OsiOS {
// The dead_strip option to the linker specifies that functions and data // The dead_strip option to the linker specifies that functions and data
// unreachable by the entry point will be removed. This is quite useful // unreachable by the entry point will be removed. This is quite useful
// with Rust's compilation model of compiling libraries at a time into // with Rust's compilation model of compiling libraries at a time into
@ -959,67 +904,58 @@ fn link_args(cmd: &mut Command,
// won't get much benefit from dylibs because LLVM will have already // won't get much benefit from dylibs because LLVM will have already
// stripped away as much as it could. This has not been seen to impact // stripped away as much as it could. This has not been seen to impact
// link times negatively. // link times negatively.
//
// -dead_strip can't be part of the pre_link_args because it's also used for partial
// linking when using multiple codegen units (-r). So we insert it here.
cmd.arg("-Wl,-dead_strip"); cmd.arg("-Wl,-dead_strip");
} }
if sess.targ_cfg.os == abi::OsWindows { // If we're building a dylib, we don't use --gc-sections because LLVM has
if sess.targ_cfg.arch == abi::X86 { // already done the best it can do, and we also don't want to eliminate the
// Make sure that we link to the dynamic libgcc, otherwise cross-module // metadata. If we're building an executable, however, --gc-sections drops
// DWARF stack unwinding will not work. // the size of hello world from 1.8MB to 597K, a 67% reduction.
// This behavior may be overridden by -Clink-args="-static-libgcc" if !dylib && !t.options.is_like_osx {
cmd.arg("-shared-libgcc"); cmd.arg("-Wl,--gc-sections");
} else { }
// On Win64 unwinding is handled by the OS, so we can link libgcc statically.
cmd.arg("-static-libgcc");
}
// And here, we see obscure linker flags #45. On windows, it has been let used_link_args = sess.cstore.get_used_link_args().borrow();
// found to be necessary to have this flag to compile liblibc.
//
// First a bit of background. On Windows, the file format is not ELF,
// but COFF (at least according to LLVM). COFF doesn't officially allow
// for section names over 8 characters, apparently. Our metadata
// section, ".note.rustc", you'll note is over 8 characters.
//
// On more recent versions of gcc on mingw, apparently the section name
// is *not* truncated, but rather stored elsewhere in a separate lookup
// table. On older versions of gcc, they apparently always truncated the
// section names (at least in some cases). Truncating the section name
// actually creates "invalid" objects [1] [2], but only for some
// introspection tools, not in terms of whether it can be loaded.
//
// Long story short, passing this flag forces the linker to *not*
// truncate section names (so we can find the metadata section after
// it's compiled). The real kicker is that rust compiled just fine on
// windows for quite a long time *without* this flag, so I have no idea
// why it suddenly started failing for liblibc. Regardless, we
// definitely don't want section name truncation, so we're keeping this
// flag for windows.
//
// [1] - https://sourceware.org/bugzilla/show_bug.cgi?id=13130
// [2] - https://code.google.com/p/go/issues/detail?id=2139
cmd.arg("-Wl,--enable-long-section-names");
// Always enable DEP (NX bit) when it is available if t.options.position_independant_executables {
cmd.arg("-Wl,--nxcompat"); let empty_vec = Vec::new();
let empty_str = String::new();
// Mark all dynamic libraries and executables as compatible with ASLR let args = sess.opts.cg.link_args.as_ref().unwrap_or(&empty_vec);
// FIXME #16514: ASLR is disabled on Windows due to MinGW-w64 bugs: let mut args = args.iter().chain(used_link_args.iter());
// FIXME #17098: ASLR breaks gdb on Windows if !dylib
// FIXME #17684: ASLR breaks thread-local storage on Windows && (t.options.relocation_model.as_slice() == "pic"
//cmd.arg("-Wl,--dynamicbase"); || sess.opts.cg.relocation_model.as_ref()
.unwrap_or(&empty_str).as_slice() == "pic")
// Mark all dynamic libraries and executables as compatible with the larger 4GiB address && !args.any(|x| x.as_slice() == "-static") {
// space available to x86 Windows binaries on x86_64. cmd.arg("-pie");
if sess.targ_cfg.arch == abi::X86 {
cmd.arg("-Wl,--large-address-aware");
} }
} }
if sess.targ_cfg.os == abi::OsAndroid { if t.options.linker_is_gnu {
// Many of the symbols defined in compiler-rt are also defined in libgcc. // GNU-style linkers support optimization with -O. GNU ld doesn't need a
// Android linker doesn't like that by default. // numeric argument, but other linkers do.
cmd.arg("-Wl,--allow-multiple-definition"); if sess.opts.optimize == config::Default ||
sess.opts.optimize == config::Aggressive {
cmd.arg("-Wl,-O1");
}
}
// We want to prevent the compiler from accidentally leaking in any system
// libraries, so we explicitly ask gcc to not link to any libraries by
// default. Note that this does not happen for windows because windows pulls
// in some large number of libraries and I couldn't quite figure out which
// subset we wanted.
if !t.options.is_like_windows {
cmd.arg("-nodefaultlibs");
}
// Mark all dynamic libraries and executables as compatible with ASLR
// FIXME #17098: ASLR breaks gdb
if t.options.is_like_windows && sess.opts.debuginfo == NoDebugInfo {
// cmd.arg("-Wl,--dynamicbase");
} }
// Take careful note of the ordering of the arguments we pass to the linker // Take careful note of the ordering of the arguments we pass to the linker
@ -1063,7 +999,7 @@ fn link_args(cmd: &mut Command,
if dylib { if dylib {
// On mac we need to tell the linker to let this library be rpathed // On mac we need to tell the linker to let this library be rpathed
if sess.targ_cfg.os == abi::OsMacos { if sess.target.target.options.is_like_osx {
cmd.args(["-dynamiclib", "-Wl,-dylib"]); cmd.args(["-dynamiclib", "-Wl,-dylib"]);
if sess.opts.cg.rpath { if sess.opts.cg.rpath {
@ -1076,18 +1012,6 @@ fn link_args(cmd: &mut Command,
} }
} }
if sess.targ_cfg.os == abi::OsFreebsd {
cmd.args(["-L/usr/local/lib",
"-L/usr/local/lib/gcc46",
"-L/usr/local/lib/gcc44"]);
}
else if sess.targ_cfg.os == abi::OsDragonfly {
cmd.args(["-L/usr/local/lib",
"-L/usr/lib/gcc47",
"-L/usr/lib/gcc44"]);
}
// FIXME (#2397): At some point we want to rpath our guesses as to // FIXME (#2397): At some point we want to rpath our guesses as to
// where extern libraries might live, based on the // where extern libraries might live, based on the
// addl_lib_search_paths // addl_lib_search_paths
@ -1103,27 +1027,20 @@ fn link_args(cmd: &mut Command,
path path
}; };
let rpath_config = RPathConfig { let rpath_config = RPathConfig {
os: sess.targ_cfg.os,
used_crates: sess.cstore.get_used_crates(cstore::RequireDynamic), used_crates: sess.cstore.get_used_crates(cstore::RequireDynamic),
out_filename: out_filename.clone(), out_filename: out_filename.clone(),
has_rpath: sess.target.target.options.has_rpath,
is_like_osx: sess.target.target.options.is_like_osx,
get_install_prefix_lib_path: get_install_prefix_lib_path, get_install_prefix_lib_path: get_install_prefix_lib_path,
realpath: ::util::fs::realpath realpath: ::util::fs::realpath
}; };
cmd.args(rpath::get_rpath_flags(rpath_config).as_slice()); cmd.args(rpath::get_rpath_flags(rpath_config).as_slice());
} }
// compiler-rt contains implementations of low-level LLVM helpers. This is
// used to resolve symbols from the object file we just created, as well as
// any system static libraries that may be expecting gcc instead. Most
// symbols in libgcc also appear in compiler-rt.
//
// This is the end of the command line, so this library is used to resolve
// *all* undefined symbols in all other libraries, and this is intentional.
cmd.arg("-lcompiler-rt");
// Finally add all the linker arguments provided on the command line along // Finally add all the linker arguments provided on the command line along
// with any #[link_args] attributes found inside the crate // with any #[link_args] attributes found inside the crate
cmd.args(sess.opts.cg.link_args.as_slice()); let empty = Vec::new();
cmd.args(sess.opts.cg.link_args.as_ref().unwrap_or(&empty).as_slice());
cmd.args(used_link_args.as_slice()); cmd.args(used_link_args.as_slice());
} }
@ -1152,8 +1069,7 @@ fn add_local_native_libraries(cmd: &mut Command, sess: &Session) {
// For those that support this, we ensure we pass the option if the library // For those that support this, we ensure we pass the option if the library
// was flagged "static" (most defaults are dynamic) to ensure that if // was flagged "static" (most defaults are dynamic) to ensure that if
// libfoo.a and libfoo.so both exist that the right one is chosen. // libfoo.a and libfoo.so both exist that the right one is chosen.
let takes_hints = sess.targ_cfg.os != abi::OsMacos && let takes_hints = !sess.target.target.options.is_like_osx;
sess.targ_cfg.os != abi::OsiOS;
let libs = sess.cstore.get_used_libraries(); let libs = sess.cstore.get_used_libraries();
let libs = libs.borrow(); let libs = libs.borrow();
@ -1184,7 +1100,8 @@ fn add_local_native_libraries(cmd: &mut Command, sess: &Session) {
// -force_load is the OSX equivalent of --whole-archive, but it // -force_load is the OSX equivalent of --whole-archive, but it
// involves passing the full path to the library to link. // involves passing the full path to the library to link.
let lib = archive::find_library(l.as_slice(), let lib = archive::find_library(l.as_slice(),
sess.targ_cfg.os, sess.target.target.options.staticlib_prefix.as_slice(),
sess.target.target.options.staticlib_suffix.as_slice(),
search_path.as_slice(), search_path.as_slice(),
&sess.diagnostic().handler); &sess.diagnostic().handler);
let mut v = b"-Wl,-force_load,".to_vec(); let mut v = b"-Wl,-force_load,".to_vec();
@ -1257,7 +1174,7 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session,
// Converts a library file-stem into a cc -l argument // Converts a library file-stem into a cc -l argument
fn unlib<'a>(config: &config::Config, stem: &'a [u8]) -> &'a [u8] { fn unlib<'a>(config: &config::Config, stem: &'a [u8]) -> &'a [u8] {
if stem.starts_with("lib".as_bytes()) && config.os != abi::OsWindows { if stem.starts_with("lib".as_bytes()) && !config.target.options.is_like_windows {
stem[3..] stem[3..]
} else { } else {
stem stem
@ -1315,7 +1232,8 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session,
handler: handler, handler: handler,
dst: dst.clone(), dst: dst.clone(),
lib_search_paths: archive_search_paths(sess), lib_search_paths: archive_search_paths(sess),
os: sess.targ_cfg.os, slib_prefix: sess.target.target.options.staticlib_prefix.clone(),
slib_suffix: sess.target.target.options.staticlib_suffix.clone(),
maybe_ar_prog: sess.opts.cg.ar.clone() maybe_ar_prog: sess.opts.cg.ar.clone()
}; };
let mut archive = Archive::open(config); let mut archive = Archive::open(config);
@ -1342,7 +1260,7 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session,
if !dir.is_empty() { cmd.arg("-L").arg(dir); } if !dir.is_empty() { cmd.arg("-L").arg(dir); }
let mut v = "-l".as_bytes().to_vec(); let mut v = "-l".as_bytes().to_vec();
v.push_all(unlib(&sess.targ_cfg, cratepath.filestem().unwrap())); v.push_all(unlib(&sess.target, cratepath.filestem().unwrap()));
cmd.arg(v.as_slice()); cmd.arg(v.as_slice());
} }
} }

View File

@ -18,7 +18,6 @@ use llvm;
use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef, ContextRef}; use llvm::{ModuleRef, TargetMachineRef, PassManagerRef, DiagnosticInfoRef, ContextRef};
use llvm::SMDiagnosticRef; use llvm::SMDiagnosticRef;
use util::common::time; use util::common::time;
use syntax::abi;
use syntax::codemap; use syntax::codemap;
use syntax::diagnostic; use syntax::diagnostic;
use syntax::diagnostic::{Emitter, Handler, Level, mk_handler}; use syntax::diagnostic::{Emitter, Handler, Level, mk_handler};
@ -150,20 +149,8 @@ impl Emitter for SharedEmitter {
// Note that without those flags various linking errors might // Note that without those flags various linking errors might
// arise as some of intrinsics are converted into function calls // arise as some of intrinsics are converted into function calls
// and nobody provides implementations those functions // and nobody provides implementations those functions
fn target_feature<'a>(sess: &'a Session) -> &'a str { fn target_feature(sess: &Session) -> String {
match sess.targ_cfg.os { format!("{},{}", sess.target.target.options.features, sess.opts.cg.target_feature)
abi::OsAndroid => {
if "" == sess.opts.cg.target_feature.as_slice() {
"+v7"
} else {
sess.opts.cg.target_feature.as_slice()
}
},
abi::OsiOS if sess.targ_cfg.arch == abi::Arm => {
"+v7,+thumb2,+vfp3,+neon"
},
_ => sess.opts.cg.target_feature.as_slice()
}
} }
fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel { fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel {
@ -176,7 +163,11 @@ fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel {
} }
fn create_target_machine(sess: &Session) -> TargetMachineRef { fn create_target_machine(sess: &Session) -> TargetMachineRef {
let reloc_model = match sess.opts.cg.relocation_model.as_slice() { let reloc_model_arg = match sess.opts.cg.relocation_model {
Some(ref s) => s.as_slice(),
None => sess.target.target.options.relocation_model.as_slice()
};
let reloc_model = match reloc_model_arg {
"pic" => llvm::RelocPIC, "pic" => llvm::RelocPIC,
"static" => llvm::RelocStatic, "static" => llvm::RelocStatic,
"default" => llvm::RelocDefault, "default" => llvm::RelocDefault,
@ -195,22 +186,22 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef {
let use_softfp = sess.opts.cg.soft_float; let use_softfp = sess.opts.cg.soft_float;
// FIXME: #11906: Omitting frame pointers breaks retrieving the value of a parameter. // FIXME: #11906: Omitting frame pointers breaks retrieving the value of a parameter.
// FIXME: #11954: mac64 unwinding may not work with fp elim
let no_fp_elim = (sess.opts.debuginfo != NoDebugInfo) || let no_fp_elim = (sess.opts.debuginfo != NoDebugInfo) ||
(sess.targ_cfg.os == abi::OsMacos && !sess.target.target.options.eliminate_frame_pointer;
sess.targ_cfg.arch == abi::X86_64);
let any_library = sess.crate_types.borrow().iter().any(|ty| { let any_library = sess.crate_types.borrow().iter().any(|ty| {
*ty != config::CrateTypeExecutable *ty != config::CrateTypeExecutable
}); });
// OSX has -dead_strip, which doesn't rely on ffunction_sections let ffunction_sections = sess.target.target.options.function_sections;
// FIXME(#13846) this should be enabled for windows
let ffunction_sections = sess.targ_cfg.os != abi::OsMacos &&
sess.targ_cfg.os != abi::OsWindows;
let fdata_sections = ffunction_sections; let fdata_sections = ffunction_sections;
let code_model = match sess.opts.cg.code_model.as_slice() { let code_model_arg = match sess.opts.cg.code_model {
Some(ref s) => s.as_slice(),
None => sess.target.target.options.code_model.as_slice()
};
let code_model = match code_model_arg {
"default" => llvm::CodeModelDefault, "default" => llvm::CodeModelDefault,
"small" => llvm::CodeModelSmall, "small" => llvm::CodeModelSmall,
"kernel" => llvm::CodeModelKernel, "kernel" => llvm::CodeModelKernel,
@ -226,11 +217,15 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef {
} }
}; };
let triple = sess.targ_cfg.target_strs.target_triple.as_slice(); let triple = sess.target.target.llvm_target.as_slice();
let tm = unsafe { let tm = unsafe {
triple.with_c_str(|t| { triple.with_c_str(|t| {
sess.opts.cg.target_cpu.as_slice().with_c_str(|cpu| { let cpu = match sess.opts.cg.target_cpu {
Some(ref s) => s.as_slice(),
None => sess.target.target.options.cpu.as_slice()
};
cpu.with_c_str(|cpu| {
target_feature(sess).with_c_str(|features| { target_feature(sess).with_c_str(|features| {
llvm::LLVMRustCreateTargetMachine( llvm::LLVMRustCreateTargetMachine(
t, cpu, features, t, cpu, features,
@ -692,7 +687,7 @@ pub fn run_passes(sess: &Session,
// the desired path. This will give the correct behavior whether or // the desired path. This will give the correct behavior whether or
// not GCC adds --force-exe-suffix. // not GCC adds --force-exe-suffix.
let windows_output_path = let windows_output_path =
if sess.targ_cfg.os == abi::OsWindows { if sess.target.target.options.is_like_windows {
Some(output_path.with_extension("o.exe")) Some(output_path.with_extension("o.exe"))
} else { } else {
None None
@ -701,7 +696,7 @@ pub fn run_passes(sess: &Session,
let pname = get_cc_prog(sess); let pname = get_cc_prog(sess);
let mut cmd = Command::new(pname.as_slice()); let mut cmd = Command::new(pname.as_slice());
cmd.args(sess.targ_cfg.target_strs.cc_args.as_slice()); cmd.args(sess.target.target.options.pre_link_args.as_slice());
cmd.arg("-nostdlib"); cmd.arg("-nostdlib");
for index in range(0, trans.modules.len()) { for index in range(0, trans.modules.len()) {
@ -712,6 +707,8 @@ pub fn run_passes(sess: &Session,
.arg("-o") .arg("-o")
.arg(windows_output_path.as_ref().unwrap_or(output_path)); .arg(windows_output_path.as_ref().unwrap_or(output_path));
cmd.args(sess.target.target.options.post_link_args.as_slice());
if (sess.opts.debugging_opts & config::PRINT_LINK_ARGS) != 0 { if (sess.opts.debugging_opts & config::PRINT_LINK_ARGS) != 0 {
println!("{}", &cmd); println!("{}", &cmd);
} }

View File

@ -17,17 +17,15 @@ use driver::session::Session;
use back; use back;
use back::write; use back::write;
use back::target_strs; use rustc_back::target::Target;
use back::{arm, x86, x86_64, mips, mipsel};
use lint; use lint;
use metadata::cstore; use metadata::cstore;
use syntax::abi;
use syntax::ast; use syntax::ast;
use syntax::ast::{IntTy, UintTy}; use syntax::ast::{IntTy, UintTy};
use syntax::attr; use syntax::attr;
use syntax::attr::AttrMetaMethods; use syntax::attr::AttrMetaMethods;
use syntax::diagnostic::{ColorConfig, Auto, Always, Never}; use syntax::diagnostic::{ColorConfig, Auto, Always, Never, SpanHandler};
use syntax::parse; use syntax::parse;
use syntax::parse::token::InternedString; use syntax::parse::token::InternedString;
@ -41,9 +39,7 @@ use std::fmt;
use llvm; use llvm;
pub struct Config { pub struct Config {
pub os: abi::Os, pub target: Target,
pub arch: abi::Architecture,
pub target_strs: target_strs::t,
pub int_type: IntTy, pub int_type: IntTy,
pub uint_type: UintTy, pub uint_type: UintTy,
} }
@ -291,6 +287,13 @@ macro_rules! cgoptions(
} }
} }
fn parse_opt_bool(slot: &mut Option<bool>, v: Option<&str>) -> bool {
match v {
Some(..) => false,
None => { *slot = Some(true); true }
}
}
fn parse_opt_string(slot: &mut Option<String>, v: Option<&str>) -> bool { fn parse_opt_string(slot: &mut Option<String>, v: Option<&str>) -> bool {
match v { match v {
Some(s) => { *slot = Some(s.to_string()); true }, Some(s) => { *slot = Some(s.to_string()); true },
@ -318,6 +321,18 @@ macro_rules! cgoptions(
} }
} }
fn parse_opt_list(slot: &mut Option<Vec<String>>, v: Option<&str>)
-> bool {
match v {
Some(s) => {
let v = s.words().map(|s| s.to_string()).collect();
*slot = Some(v);
true
},
None => false,
}
}
fn parse_uint(slot: &mut uint, v: Option<&str>) -> bool { fn parse_uint(slot: &mut uint, v: Option<&str>) -> bool {
use std::from_str::FromStr; use std::from_str::FromStr;
match v.and_then(FromStr::from_str) { match v.and_then(FromStr::from_str) {
@ -351,11 +366,11 @@ cgoptions!(
"tool to assemble archives with"), "tool to assemble archives with"),
linker: Option<String> = (None, parse_opt_string, linker: Option<String> = (None, parse_opt_string,
"system linker to link outputs with"), "system linker to link outputs with"),
link_args: Vec<String> = (Vec::new(), parse_list, link_args: Option<Vec<String>> = (None, parse_opt_list,
"extra arguments to pass to the linker (space separated)"), "extra arguments to pass to the linker (space separated)"),
lto: bool = (false, parse_bool, lto: bool = (false, parse_bool,
"perform LLVM link-time optimizations"), "perform LLVM link-time optimizations"),
target_cpu: String = ("generic".to_string(), parse_string, target_cpu: Option<String> = (None, parse_opt_string,
"select target processor (llc -mcpu=help for details)"), "select target processor (llc -mcpu=help for details)"),
target_feature: String = ("".to_string(), parse_string, target_feature: String = ("".to_string(), parse_string,
"target specific attributes (llc -mattr=help for details)"), "target specific attributes (llc -mattr=help for details)"),
@ -379,11 +394,11 @@ cgoptions!(
"prefer dynamic linking to static linking"), "prefer dynamic linking to static linking"),
no_integrated_as: bool = (false, parse_bool, no_integrated_as: bool = (false, parse_bool,
"use an external assembler rather than LLVM's integrated one"), "use an external assembler rather than LLVM's integrated one"),
no_redzone: bool = (false, parse_bool, no_redzone: Option<bool> = (None, parse_opt_bool,
"disable the use of the redzone"), "disable the use of the redzone"),
relocation_model: String = ("pic".to_string(), parse_string, relocation_model: Option<String> = (None, parse_opt_string,
"choose the relocation model to use (llc -relocation-model for details)"), "choose the relocation model to use (llc -relocation-model for details)"),
code_model: String = ("default".to_string(), parse_string, code_model: Option<String> = (None, parse_opt_string,
"choose the code model to use (llc -code-model for details)"), "choose the code model to use (llc -code-model for details)"),
metadata: Vec<String> = (Vec::new(), parse_list, metadata: Vec<String> = (Vec::new(), parse_list,
"metadata to mangle symbol names with"), "metadata to mangle symbol names with"),
@ -437,40 +452,27 @@ pub fn default_lib_output() -> CrateType {
} }
pub fn default_configuration(sess: &Session) -> ast::CrateConfig { pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
let tos = match sess.targ_cfg.os { use syntax::parse::token::intern_and_get_ident as intern;
abi::OsWindows => InternedString::new("windows"),
abi::OsMacos => InternedString::new("macos"),
abi::OsLinux => InternedString::new("linux"),
abi::OsAndroid => InternedString::new("android"),
abi::OsFreebsd => InternedString::new("freebsd"),
abi::OsDragonfly => InternedString::new("dragonfly"),
abi::OsiOS => InternedString::new("ios"),
};
// ARM is bi-endian, however using NDK seems to default let end = sess.target.target.target_endian.as_slice();
// to little-endian unless a flag is provided. let arch = sess.target.target.arch.as_slice();
let (end,arch,wordsz) = match sess.targ_cfg.arch { let wordsz = sess.target.target.target_word_size.as_slice();
abi::X86 => ("little", "x86", "32"), let os = sess.target.target.target_os.as_slice();
abi::X86_64 => ("little", "x86_64", "64"),
abi::Arm => ("little", "arm", "32"),
abi::Mips => ("big", "mips", "32"),
abi::Mipsel => ("little", "mipsel", "32")
};
let fam = match sess.targ_cfg.os { let fam = match sess.target.target.options.is_like_windows {
abi::OsWindows => InternedString::new("windows"), true => InternedString::new("windows"),
_ => InternedString::new("unix") false => InternedString::new("unix")
}; };
let mk = attr::mk_name_value_item_str; let mk = attr::mk_name_value_item_str;
return vec!(// Target bindings. return vec!(// Target bindings.
attr::mk_word_item(fam.clone()), attr::mk_word_item(fam.clone()),
mk(InternedString::new("target_os"), tos), mk(InternedString::new("target_os"), intern(os)),
mk(InternedString::new("target_family"), fam), mk(InternedString::new("target_family"), fam),
mk(InternedString::new("target_arch"), InternedString::new(arch)), mk(InternedString::new("target_arch"), intern(arch)),
mk(InternedString::new("target_endian"), InternedString::new(end)), mk(InternedString::new("target_endian"), intern(end)),
mk(InternedString::new("target_word_size"), mk(InternedString::new("target_word_size"),
InternedString::new(wordsz)) intern(wordsz))
); );
} }
@ -495,78 +497,23 @@ pub fn build_configuration(sess: &Session) -> ast::CrateConfig {
v v
} }
pub fn get_os(triple: &str) -> Option<abi::Os> { pub fn build_target_config(opts: &Options, sp: &SpanHandler) -> Config {
for &(name, os) in os_names.iter() { let target = match Target::search(opts.target_triple.as_slice()) {
if triple.contains(name) { return Some(os) } Ok(t) => t,
Err(e) => {
sp.handler().fatal((format!("Error loading target specification: {}", e)).as_slice());
} }
None
}
#[allow(non_upper_case_globals)]
static os_names : &'static [(&'static str, abi::Os)] = &[
("mingw32", abi::OsWindows),
("win32", abi::OsWindows),
("windows", abi::OsWindows),
("darwin", abi::OsMacos),
("android", abi::OsAndroid),
("linux", abi::OsLinux),
("freebsd", abi::OsFreebsd),
("dragonfly", abi::OsDragonfly),
("ios", abi::OsiOS)];
pub fn get_arch(triple: &str) -> Option<abi::Architecture> {
for &(arch, abi) in architecture_abis.iter() {
if triple.contains(arch) { return Some(abi) }
}
None
}
#[allow(non_upper_case_globals)]
static architecture_abis : &'static [(&'static str, abi::Architecture)] = &[
("i386", abi::X86),
("i486", abi::X86),
("i586", abi::X86),
("i686", abi::X86),
("i786", abi::X86),
("x86_64", abi::X86_64),
("arm", abi::Arm),
("xscale", abi::Arm),
("thumb", abi::Arm),
("mipsel", abi::Mipsel),
("mips", abi::Mips)];
pub fn build_target_config(sopts: &Options) -> Config {
let os = match get_os(sopts.target_triple.as_slice()) {
Some(os) => os,
None => early_error("unknown operating system")
}; };
let arch = match get_arch(sopts.target_triple.as_slice()) {
Some(arch) => arch, let (int_type, uint_type) = match target.target_word_size.as_slice() {
None => { "32" => (ast::TyI32, ast::TyU32),
early_error(format!("unknown architecture: {}", "64" => (ast::TyI64, ast::TyU64),
sopts.target_triple.as_slice()).as_slice()) w => sp.handler().fatal((format!("target specification was invalid: unrecognized \
} target-word-size {}", w)).as_slice())
};
let (int_type, uint_type) = match arch {
abi::X86 => (ast::TyI32, ast::TyU32),
abi::X86_64 => (ast::TyI64, ast::TyU64),
abi::Arm => (ast::TyI32, ast::TyU32),
abi::Mips => (ast::TyI32, ast::TyU32),
abi::Mipsel => (ast::TyI32, ast::TyU32)
};
let target_triple = sopts.target_triple.clone();
let target_strs = match arch {
abi::X86 => x86::get_target_strs(target_triple, os),
abi::X86_64 => x86_64::get_target_strs(target_triple, os),
abi::Arm => arm::get_target_strs(target_triple, os),
abi::Mips => mips::get_target_strs(target_triple, os),
abi::Mipsel => mipsel::get_target_strs(target_triple, os)
}; };
Config { Config {
os: os, target: target,
arch: arch,
target_strs: target_strs,
int_type: int_type, int_type: int_type,
uint_type: uint_type, uint_type: uint_type,
} }

View File

@ -749,8 +749,8 @@ pub fn collect_crate_types(session: &Session,
if !res { if !res {
session.warn(format!("dropping unsupported crate type `{}` \ session.warn(format!("dropping unsupported crate type `{}` \
for target os `{}`", for target `{}`",
*crate_type, session.targ_cfg.os).as_slice()); *crate_type, session.opts.target_triple).as_slice());
} }
res res

View File

@ -435,7 +435,7 @@ pub fn early_warn(msg: &str) {
pub fn list_metadata(sess: &Session, path: &Path, pub fn list_metadata(sess: &Session, path: &Path,
out: &mut io::Writer) -> io::IoResult<()> { out: &mut io::Writer) -> io::IoResult<()> {
metadata::loader::list_file_metadata(sess.targ_cfg.os, path, out) metadata::loader::list_file_metadata(sess.target.target.options.is_like_osx, path, out)
} }
/// Run a procedure which will detect failures in the compiler and print nicer /// Run a procedure which will detect failures in the compiler and print nicer

View File

@ -32,7 +32,7 @@ use std::cell::{Cell, RefCell};
// Represents the data associated with a compilation // Represents the data associated with a compilation
// session for a single crate. // session for a single crate.
pub struct Session { pub struct Session {
pub targ_cfg: config::Config, pub target: config::Config,
pub opts: config::Options, pub opts: config::Options,
pub cstore: CStore, pub cstore: CStore,
pub parse_sess: ParseSess, pub parse_sess: ParseSess,
@ -219,7 +219,7 @@ pub fn build_session_(sopts: config::Options,
local_crate_source_file: Option<Path>, local_crate_source_file: Option<Path>,
span_diagnostic: diagnostic::SpanHandler) span_diagnostic: diagnostic::SpanHandler)
-> Session { -> Session {
let target_cfg = config::build_target_config(&sopts); let target_cfg = config::build_target_config(&sopts, &span_diagnostic);
let p_s = parse::new_parse_sess_special_handler(span_diagnostic); let p_s = parse::new_parse_sess_special_handler(span_diagnostic);
let default_sysroot = match sopts.maybe_sysroot { let default_sysroot = match sopts.maybe_sysroot {
Some(_) => None, Some(_) => None,
@ -236,7 +236,7 @@ pub fn build_session_(sopts: config::Options,
); );
let sess = Session { let sess = Session {
targ_cfg: target_cfg, target: target_cfg,
opts: sopts, opts: sopts,
cstore: CStore::new(token::get_ident_interner()), cstore: CStore::new(token::get_ident_interner()),
parse_sess: p_s, parse_sess: p_s,

View File

@ -210,7 +210,7 @@ impl LintPass for TypeLimits {
ast::LitInt(v, ast::SignedIntLit(_, ast::Plus)) | ast::LitInt(v, ast::SignedIntLit(_, ast::Plus)) |
ast::LitInt(v, ast::UnsuffixedIntLit(ast::Plus)) => { ast::LitInt(v, ast::UnsuffixedIntLit(ast::Plus)) => {
let int_type = if t == ast::TyI { let int_type = if t == ast::TyI {
cx.sess().targ_cfg.int_type cx.sess().target.int_type
} else { t }; } else { t };
let (min, max) = int_ty_range(int_type); let (min, max) = int_ty_range(int_type);
let negative = self.negated_expr_id == e.id; let negative = self.negated_expr_id == e.id;
@ -227,7 +227,7 @@ impl LintPass for TypeLimits {
}, },
ty::ty_uint(t) => { ty::ty_uint(t) => {
let uint_type = if t == ast::TyU { let uint_type = if t == ast::TyU {
cx.sess().targ_cfg.uint_type cx.sess().target.uint_type
} else { t }; } else { t };
let (min, max) = uint_ty_range(uint_type); let (min, max) = uint_ty_range(uint_type);
let lit_val: u64 = match lit.node { let lit_val: u64 = match lit.node {

View File

@ -14,7 +14,7 @@
use back::svh::Svh; use back::svh::Svh;
use driver::session::Session; use driver::session::Session;
use driver::{driver, config}; use driver::driver;
use metadata::cstore; use metadata::cstore;
use metadata::cstore::{CStore, CrateSource}; use metadata::cstore::{CStore, CrateSource};
use metadata::decoder; use metadata::decoder;
@ -237,6 +237,9 @@ fn visit_item(e: &Env, i: &ast::Item) {
Some(k) => { Some(k) => {
if k.equiv(&("static")) { if k.equiv(&("static")) {
cstore::NativeStatic cstore::NativeStatic
} else if e.sess.target.target.options.is_like_osx
&& k.equiv(&("framework")) {
cstore::NativeFramework
} else if k.equiv(&("framework")) { } else if k.equiv(&("framework")) {
cstore::NativeFramework cstore::NativeFramework
} else { } else {
@ -285,8 +288,7 @@ fn register_native_lib(sess: &Session, span: Option<Span>, name: String,
} }
return return
} }
let is_osx = sess.targ_cfg.os == abi::OsMacos || let is_osx = sess.target.target.options.is_like_osx;
sess.targ_cfg.os == abi::OsiOS;
if kind == cstore::NativeFramework && !is_osx { if kind == cstore::NativeFramework && !is_osx {
let msg = "native frameworks are only available on OSX targets"; let msg = "native frameworks are only available on OSX targets";
match span { match span {
@ -400,8 +402,7 @@ fn resolve_crate<'a>(e: &mut Env,
crate_name: name, crate_name: name,
hash: hash.map(|a| &*a), hash: hash.map(|a| &*a),
filesearch: e.sess.target_filesearch(), filesearch: e.sess.target_filesearch(),
os: e.sess.targ_cfg.os, triple: e.sess.opts.target_triple.as_slice(),
triple: e.sess.targ_cfg.target_strs.target_triple.as_slice(),
root: root, root: root,
rejected_via_hash: vec!(), rejected_via_hash: vec!(),
rejected_via_triple: vec!(), rejected_via_triple: vec!(),
@ -451,10 +452,9 @@ impl<'a> PluginMetadataReader<'a> {
pub fn read_plugin_metadata(&mut self, krate: &ast::ViewItem) -> PluginMetadata { pub fn read_plugin_metadata(&mut self, krate: &ast::ViewItem) -> PluginMetadata {
let info = extract_crate_info(&self.env, krate).unwrap(); let info = extract_crate_info(&self.env, krate).unwrap();
let target_triple = self.env.sess.targ_cfg.target_strs.target_triple.as_slice(); let target_triple = self.env.sess.opts.target_triple.as_slice();
let is_cross = target_triple != driver::host_triple(); let is_cross = target_triple != driver::host_triple();
let mut should_link = info.should_link && !is_cross; let mut should_link = info.should_link && !is_cross;
let os = config::get_os(driver::host_triple()).unwrap();
let mut load_ctxt = loader::Context { let mut load_ctxt = loader::Context {
sess: self.env.sess, sess: self.env.sess,
span: krate.span, span: krate.span,
@ -463,7 +463,6 @@ impl<'a> PluginMetadataReader<'a> {
hash: None, hash: None,
filesearch: self.env.sess.host_filesearch(), filesearch: self.env.sess.host_filesearch(),
triple: driver::host_triple(), triple: driver::host_triple(),
os: os,
root: &None, root: &None,
rejected_via_hash: vec!(), rejected_via_hash: vec!(),
rejected_via_triple: vec!(), rejected_via_triple: vec!(),
@ -475,7 +474,6 @@ impl<'a> PluginMetadataReader<'a> {
// try loading from target crates (only valid if there are // try loading from target crates (only valid if there are
// no syntax extensions) // no syntax extensions)
load_ctxt.triple = target_triple; load_ctxt.triple = target_triple;
load_ctxt.os = self.env.sess.targ_cfg.os;
load_ctxt.filesearch = self.env.sess.target_filesearch(); load_ctxt.filesearch = self.env.sess.target_filesearch();
let lib = load_ctxt.load_library_crate(); let lib = load_ctxt.load_library_crate();
if decoder::get_plugin_registrar_fn(lib.metadata.as_slice()).is_some() { if decoder::get_plugin_registrar_fn(lib.metadata.as_slice()).is_some() {

View File

@ -2071,8 +2071,7 @@ fn encode_metadata_inner(wr: &mut SeekableMemWriter, parms: EncodeParams, krate:
encode_crate_name(&mut rbml_w, ecx.link_meta.crate_name.as_slice()); encode_crate_name(&mut rbml_w, ecx.link_meta.crate_name.as_slice());
encode_crate_triple(&mut rbml_w, encode_crate_triple(&mut rbml_w,
tcx.sess tcx.sess
.targ_cfg .opts
.target_strs
.target_triple .target_triple
.as_slice()); .as_slice());
encode_hash(&mut rbml_w, &ecx.link_meta.crate_hash); encode_hash(&mut rbml_w, &ecx.link_meta.crate_hash);

View File

@ -222,7 +222,6 @@ use metadata::cstore::{MetadataBlob, MetadataVec, MetadataArchive};
use metadata::decoder; use metadata::decoder;
use metadata::encoder; use metadata::encoder;
use metadata::filesearch::{FileSearch, FileMatches, FileDoesntMatch}; use metadata::filesearch::{FileSearch, FileMatches, FileDoesntMatch};
use syntax::abi;
use syntax::codemap::Span; use syntax::codemap::Span;
use syntax::diagnostic::SpanHandler; use syntax::diagnostic::SpanHandler;
use util::fs; use util::fs;
@ -240,24 +239,6 @@ use std::collections::hash_map::{Occupied, Vacant};
use flate; use flate;
use time; use time;
pub const MACOS_DLL_PREFIX: &'static str = "lib";
pub const MACOS_DLL_SUFFIX: &'static str = ".dylib";
pub const WIN32_DLL_PREFIX: &'static str = "";
pub const WIN32_DLL_SUFFIX: &'static str = ".dll";
pub const LINUX_DLL_PREFIX: &'static str = "lib";
pub const LINUX_DLL_SUFFIX: &'static str = ".so";
pub const FREEBSD_DLL_PREFIX: &'static str = "lib";
pub const FREEBSD_DLL_SUFFIX: &'static str = ".so";
pub const DRAGONFLY_DLL_PREFIX: &'static str = "lib";
pub const DRAGONFLY_DLL_SUFFIX: &'static str = ".so";
pub const ANDROID_DLL_PREFIX: &'static str = "lib";
pub const ANDROID_DLL_SUFFIX: &'static str = ".so";
pub struct CrateMismatch { pub struct CrateMismatch {
path: Path, path: Path,
got: String, got: String,
@ -270,7 +251,6 @@ pub struct Context<'a> {
pub crate_name: &'a str, pub crate_name: &'a str,
pub hash: Option<&'a Svh>, pub hash: Option<&'a Svh>,
pub triple: &'a str, pub triple: &'a str,
pub os: abi::Os,
pub filesearch: FileSearch<'a>, pub filesearch: FileSearch<'a>,
pub root: &'a Option<CratePaths>, pub root: &'a Option<CratePaths>,
pub rejected_via_hash: Vec<CrateMismatch>, pub rejected_via_hash: Vec<CrateMismatch>,
@ -387,9 +367,7 @@ impl<'a> Context<'a> {
let dypair = self.dylibname(); let dypair = self.dylibname();
// want: crate_name.dir_part() + prefix + crate_name.file_part + "-" // want: crate_name.dir_part() + prefix + crate_name.file_part + "-"
let dylib_prefix = dypair.map(|(prefix, _)| { let dylib_prefix = format!("{}{}", dypair.ref0(), self.crate_name);
format!("{}{}", prefix, self.crate_name)
});
let rlib_prefix = format!("lib{}", self.crate_name); let rlib_prefix = format!("lib{}", self.crate_name);
let mut candidates = HashMap::new(); let mut candidates = HashMap::new();
@ -416,13 +394,9 @@ impl<'a> Context<'a> {
file.ends_with(".rlib") { file.ends_with(".rlib") {
(file.slice(rlib_prefix.len(), file.len() - ".rlib".len()), (file.slice(rlib_prefix.len(), file.len() - ".rlib".len()),
true) true)
} else if dypair.map_or(false, |(_, suffix)| { } else if file.starts_with(dylib_prefix.as_slice()) &&
file.starts_with(dylib_prefix.as_ref().unwrap().as_slice()) && file.ends_with(dypair.ref1().as_slice()) {
file.ends_with(suffix) (file.slice(dylib_prefix.len(), file.len() - dypair.ref1().len()),
}) {
let (_, suffix) = dypair.unwrap();
let dylib_prefix = dylib_prefix.as_ref().unwrap().as_slice();
(file.slice(dylib_prefix.len(), file.len() - suffix.len()),
false) false)
} else { } else {
return FileDoesntMatch return FileDoesntMatch
@ -530,7 +504,8 @@ impl<'a> Context<'a> {
for lib in m.into_iter() { for lib in m.into_iter() {
info!("{} reading metadata from: {}", flavor, lib.display()); info!("{} reading metadata from: {}", flavor, lib.display());
let metadata = match get_metadata_section(self.os, &lib) { let metadata = match get_metadata_section(self.sess.target.target.options.is_like_osx,
&lib) {
Ok(blob) => { Ok(blob) => {
if self.crate_matches(blob.as_slice(), &lib) { if self.crate_matches(blob.as_slice(), &lib) {
blob blob
@ -617,16 +592,9 @@ impl<'a> Context<'a> {
// Returns the corresponding (prefix, suffix) that files need to have for // Returns the corresponding (prefix, suffix) that files need to have for
// dynamic libraries // dynamic libraries
fn dylibname(&self) -> Option<(&'static str, &'static str)> { fn dylibname(&self) -> (String, String) {
match self.os { let t = &self.sess.target.target;
abi::OsWindows => Some((WIN32_DLL_PREFIX, WIN32_DLL_SUFFIX)), (t.options.dll_prefix.clone(), t.options.dll_suffix.clone())
abi::OsMacos => Some((MACOS_DLL_PREFIX, MACOS_DLL_SUFFIX)),
abi::OsLinux => Some((LINUX_DLL_PREFIX, LINUX_DLL_SUFFIX)),
abi::OsAndroid => Some((ANDROID_DLL_PREFIX, ANDROID_DLL_SUFFIX)),
abi::OsFreebsd => Some((FREEBSD_DLL_PREFIX, FREEBSD_DLL_SUFFIX)),
abi::OsDragonfly => Some((DRAGONFLY_DLL_PREFIX, DRAGONFLY_DLL_SUFFIX)),
abi::OsiOS => None,
}
} }
fn find_commandline_library(&mut self) -> Option<Library> { fn find_commandline_library(&mut self) -> Option<Library> {
@ -660,13 +628,9 @@ impl<'a> Context<'a> {
if file.starts_with("lib") && file.ends_with(".rlib") { if file.starts_with("lib") && file.ends_with(".rlib") {
return true return true
} else { } else {
match dylibname { let (ref prefix, ref suffix) = dylibname;
Some((prefix, suffix)) => { if file.starts_with(prefix.as_slice()) && file.ends_with(suffix.as_slice()) {
if file.starts_with(prefix) && file.ends_with(suffix) { return true
return true
}
}
None => {}
} }
} }
sess.err(format!("extern location for {} is of an unknown type: {}", sess.err(format!("extern location for {} is of an unknown type: {}",
@ -726,15 +690,15 @@ impl ArchiveMetadata {
} }
// Just a small wrapper to time how long reading metadata takes. // Just a small wrapper to time how long reading metadata takes.
fn get_metadata_section(os: abi::Os, filename: &Path) -> Result<MetadataBlob, String> { fn get_metadata_section(is_osx: bool, filename: &Path) -> Result<MetadataBlob, String> {
let start = time::precise_time_ns(); let start = time::precise_time_ns();
let ret = get_metadata_section_imp(os, filename); let ret = get_metadata_section_imp(is_osx, filename);
info!("reading {} => {}ms", filename.filename_display(), info!("reading {} => {}ms", filename.filename_display(),
(time::precise_time_ns() - start) / 1000000); (time::precise_time_ns() - start) / 1000000);
return ret; return ret;
} }
fn get_metadata_section_imp(os: abi::Os, filename: &Path) -> Result<MetadataBlob, String> { fn get_metadata_section_imp(is_osx: bool, filename: &Path) -> Result<MetadataBlob, String> {
if !filename.exists() { if !filename.exists() {
return Err(format!("no such file: '{}'", filename.display())); return Err(format!("no such file: '{}'", filename.display()));
} }
@ -780,7 +744,7 @@ fn get_metadata_section_imp(os: abi::Os, filename: &Path) -> Result<MetadataBlob
let name = string::raw::from_buf_len(name_buf as *const u8, let name = string::raw::from_buf_len(name_buf as *const u8,
name_len as uint); name_len as uint);
debug!("get_metadata_section: name {}", name); debug!("get_metadata_section: name {}", name);
if read_meta_section_name(os).as_slice() == name.as_slice() { if read_meta_section_name(is_osx).as_slice() == name.as_slice() {
let cbuf = llvm::LLVMGetSectionContents(si.llsi); let cbuf = llvm::LLVMGetSectionContents(si.llsi);
let csz = llvm::LLVMGetSectionSize(si.llsi) as uint; let csz = llvm::LLVMGetSectionSize(si.llsi) as uint;
let mut found = let mut found =
@ -821,34 +785,26 @@ fn get_metadata_section_imp(os: abi::Os, filename: &Path) -> Result<MetadataBlob
} }
} }
pub fn meta_section_name(os: abi::Os) -> Option<&'static str> { pub fn meta_section_name(is_osx: bool) -> &'static str {
match os { if is_osx {
abi::OsMacos => Some("__DATA,__note.rustc"), "__DATA,__note.rustc"
abi::OsiOS => Some("__DATA,__note.rustc"), } else {
abi::OsWindows => Some(".note.rustc"), ".note.rustc"
abi::OsLinux => Some(".note.rustc"),
abi::OsAndroid => Some(".note.rustc"),
abi::OsFreebsd => Some(".note.rustc"),
abi::OsDragonfly => Some(".note.rustc"),
} }
} }
pub fn read_meta_section_name(os: abi::Os) -> &'static str { pub fn read_meta_section_name(is_osx: bool) -> &'static str {
match os { if is_osx {
abi::OsMacos => "__note.rustc", "__note.rustc"
abi::OsiOS => unreachable!(), } else {
abi::OsWindows => ".note.rustc", ".note.rustc"
abi::OsLinux => ".note.rustc",
abi::OsAndroid => ".note.rustc",
abi::OsFreebsd => ".note.rustc",
abi::OsDragonfly => ".note.rustc"
} }
} }
// A diagnostic function for dumping crate metadata to an output stream // A diagnostic function for dumping crate metadata to an output stream
pub fn list_file_metadata(os: abi::Os, path: &Path, pub fn list_file_metadata(is_osx: bool, path: &Path,
out: &mut io::Writer) -> io::IoResult<()> { out: &mut io::Writer) -> io::IoResult<()> {
match get_metadata_section(os, path) { match get_metadata_section(is_osx, path) {
Ok(bytes) => decoder::list_crate_metadata(bytes.as_slice(), out), Ok(bytes) => decoder::list_crate_metadata(bytes.as_slice(), out),
Err(msg) => { Err(msg) => {
write!(out, "{}\n", msg) write!(out, "{}\n", msg)

View File

@ -135,13 +135,13 @@ fn calculate_type(sess: &session::Session,
sess.cstore.iter_crate_data(|cnum, data| { sess.cstore.iter_crate_data(|cnum, data| {
let src = sess.cstore.get_used_crate_source(cnum).unwrap(); let src = sess.cstore.get_used_crate_source(cnum).unwrap();
if src.dylib.is_some() { if src.dylib.is_some() {
add_library(sess, cnum, cstore::RequireDynamic, &mut formats);
debug!("adding dylib: {}", data.name); debug!("adding dylib: {}", data.name);
add_library(sess, cnum, cstore::RequireDynamic, &mut formats);
let deps = csearch::get_dylib_dependency_formats(&sess.cstore, cnum); let deps = csearch::get_dylib_dependency_formats(&sess.cstore, cnum);
for &(depnum, style) in deps.iter() { for &(depnum, style) in deps.iter() {
add_library(sess, depnum, style, &mut formats);
debug!("adding {}: {}", style, debug!("adding {}: {}", style,
sess.cstore.get_crate_data(depnum).name.clone()); sess.cstore.get_crate_data(depnum).name.clone());
add_library(sess, depnum, style, &mut formats);
} }
} }
}); });
@ -160,9 +160,9 @@ fn calculate_type(sess: &session::Session,
let src = sess.cstore.get_used_crate_source(cnum).unwrap(); let src = sess.cstore.get_used_crate_source(cnum).unwrap();
if src.dylib.is_none() && !formats.contains_key(&cnum) { if src.dylib.is_none() && !formats.contains_key(&cnum) {
assert!(src.rlib.is_some()); assert!(src.rlib.is_some());
debug!("adding staticlib: {}", data.name);
add_library(sess, cnum, cstore::RequireStatic, &mut formats); add_library(sess, cnum, cstore::RequireStatic, &mut formats);
ret[cnum as uint - 1] = Some(cstore::RequireStatic); ret[cnum as uint - 1] = Some(cstore::RequireStatic);
debug!("adding staticlib: {}", data.name);
} }
}); });

View File

@ -62,7 +62,6 @@ use middle::trans::type_::Type;
use middle::trans::type_of; use middle::trans::type_of;
use middle::ty; use middle::ty;
use middle::ty::Disr; use middle::ty::Disr;
use syntax::abi::{X86, X86_64, Arm, Mips, Mipsel};
use syntax::ast; use syntax::ast;
use syntax::attr; use syntax::attr;
use syntax::attr::IntType; use syntax::attr::IntType;
@ -410,14 +409,12 @@ fn range_to_inttype(cx: &CrateContext, hint: Hint, bounds: &IntBounds) -> IntTyp
return ity; return ity;
} }
attr::ReprExtern => { attr::ReprExtern => {
attempts = match cx.sess().targ_cfg.arch { attempts = match cx.sess().target.target.arch.as_slice() {
X86 | X86_64 => at_least_32,
// WARNING: the ARM EABI has two variants; the one corresponding to `at_least_32` // WARNING: the ARM EABI has two variants; the one corresponding to `at_least_32`
// appears to be used on Linux and NetBSD, but some systems may use the variant // appears to be used on Linux and NetBSD, but some systems may use the variant
// corresponding to `choose_shortest`. However, we don't run on those yet...? // corresponding to `choose_shortest`. However, we don't run on those yet...?
Arm => at_least_32, "arm" => at_least_32,
Mips => at_least_32, _ => at_least_32,
Mipsel => at_least_32,
} }
} }
attr::ReprAny => { attr::ReprAny => {

View File

@ -87,8 +87,7 @@ use std::cell::{Cell, RefCell};
use std::collections::HashSet; use std::collections::HashSet;
use std::rc::Rc; use std::rc::Rc;
use std::{i8, i16, i32, i64}; use std::{i8, i16, i32, i64};
use syntax::abi::{X86, X86_64, Arm, Mips, Mipsel, Rust, RustCall}; use syntax::abi::{Rust, RustCall, RustIntrinsic, Abi};
use syntax::abi::{RustIntrinsic, Abi, OsWindows};
use syntax::ast_util::local_def; use syntax::ast_util::local_def;
use syntax::attr::AttrMetaMethods; use syntax::attr::AttrMetaMethods;
use syntax::attr; use syntax::attr;
@ -193,7 +192,8 @@ pub fn decl_fn(ccx: &CrateContext, name: &str, cc: llvm::CallConv,
llvm::SetFunctionAttribute(llfn, llvm::NoReturnAttribute); llvm::SetFunctionAttribute(llfn, llvm::NoReturnAttribute);
} }
if ccx.tcx().sess.opts.cg.no_redzone { if ccx.tcx().sess.opts.cg.no_redzone
.unwrap_or(ccx.tcx().sess.target.target.options.disable_redzone) {
llvm::SetFunctionAttribute(llfn, llvm::NoRedZoneAttribute) llvm::SetFunctionAttribute(llfn, llvm::NoRedZoneAttribute)
} }
@ -934,17 +934,16 @@ pub fn trans_external_path(ccx: &CrateContext, did: ast::DefId, t: ty::t) -> Val
let name = csearch::get_symbol(&ccx.sess().cstore, did); let name = csearch::get_symbol(&ccx.sess().cstore, did);
match ty::get(t).sty { match ty::get(t).sty {
ty::ty_bare_fn(ref fn_ty) => { ty::ty_bare_fn(ref fn_ty) => {
match fn_ty.abi.for_target(ccx.sess().targ_cfg.os, match ccx.sess().target.target.adjust_abi(fn_ty.abi) {
ccx.sess().targ_cfg.arch) { Rust | RustCall => {
Some(Rust) | Some(RustCall) => {
get_extern_rust_fn(ccx, t, name.as_slice(), did) get_extern_rust_fn(ccx, t, name.as_slice(), did)
} }
Some(RustIntrinsic) => { RustIntrinsic => {
ccx.sess().bug("unexpected intrinsic in trans_external_path") ccx.sess().bug("unexpected intrinsic in trans_external_path")
} }
Some(..) | None => { _ => {
foreign::register_foreign_item_fn(ccx, fn_ty.abi, t, foreign::register_foreign_item_fn(ccx, fn_ty.abi, t,
name.as_slice(), None) name.as_slice())
} }
} }
} }
@ -1143,9 +1142,10 @@ pub fn call_lifetime_end(cx: Block, ptr: ValueRef) {
pub fn call_memcpy(cx: Block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef, align: u32) { pub fn call_memcpy(cx: Block, dst: ValueRef, src: ValueRef, n_bytes: ValueRef, align: u32) {
let _icx = push_ctxt("call_memcpy"); let _icx = push_ctxt("call_memcpy");
let ccx = cx.ccx(); let ccx = cx.ccx();
let key = match ccx.sess().targ_cfg.arch { let key = match ccx.sess().target.target.target_word_size.as_slice() {
X86 | Arm | Mips | Mipsel => "llvm.memcpy.p0i8.p0i8.i32", "32" => "llvm.memcpy.p0i8.p0i8.i32",
X86_64 => "llvm.memcpy.p0i8.p0i8.i64" "64" => "llvm.memcpy.p0i8.p0i8.i64",
tws => panic!("Unsupported target word size for memcpy: {}", tws),
}; };
let memcpy = ccx.get_intrinsic(&key); let memcpy = ccx.get_intrinsic(&key);
let src_ptr = PointerCast(cx, src, Type::i8p(ccx)); let src_ptr = PointerCast(cx, src, Type::i8p(ccx));
@ -1187,9 +1187,10 @@ fn memzero(b: &Builder, llptr: ValueRef, ty: ty::t) {
let llty = type_of::type_of(ccx, ty); let llty = type_of::type_of(ccx, ty);
let intrinsic_key = match ccx.sess().targ_cfg.arch { let intrinsic_key = match ccx.sess().target.target.target_word_size.as_slice() {
X86 | Arm | Mips | Mipsel => "llvm.memset.p0i8.i32", "32" => "llvm.memset.p0i8.i32",
X86_64 => "llvm.memset.p0i8.i64" "64" => "llvm.memset.p0i8.i64",
tws => panic!("Unsupported target word size for memset: {}", tws),
}; };
let llintrinsicfn = ccx.get_intrinsic(&intrinsic_key); let llintrinsicfn = ccx.get_intrinsic(&intrinsic_key);
@ -2583,7 +2584,7 @@ pub fn create_entry_wrapper(ccx: &CrateContext,
// FIXME: #16581: Marking a symbol in the executable with `dllexport` // FIXME: #16581: Marking a symbol in the executable with `dllexport`
// linkage forces MinGW's linker to output a `.reloc` section for ASLR // linkage forces MinGW's linker to output a `.reloc` section for ASLR
if ccx.sess().targ_cfg.os == OsWindows { if ccx.sess().target.target.options.is_like_windows {
unsafe { llvm::LLVMRustSetDLLExportStorageClass(llfn) } unsafe { llvm::LLVMRustSetDLLExportStorageClass(llfn) }
} }
@ -2803,9 +2804,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
let abi = ccx.tcx().map.get_foreign_abi(id); let abi = ccx.tcx().map.get_foreign_abi(id);
let ty = ty::node_id_to_type(ccx.tcx(), ni.id); let ty = ty::node_id_to_type(ccx.tcx(), ni.id);
let name = foreign::link_name(&*ni); let name = foreign::link_name(&*ni);
foreign::register_foreign_item_fn(ccx, abi, ty, foreign::register_foreign_item_fn(ccx, abi, ty, name.get().as_slice())
name.get().as_slice(),
Some(ni.span))
} }
ast::ForeignItemStatic(..) => { ast::ForeignItemStatic(..) => {
foreign::register_static(ccx, &*ni) foreign::register_static(ccx, &*ni)
@ -2946,8 +2945,8 @@ pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> Vec<u8> {
}); });
unsafe { unsafe {
llvm::LLVMSetInitializer(llglobal, llconst); llvm::LLVMSetInitializer(llglobal, llconst);
let name = loader::meta_section_name(cx.sess().targ_cfg.os); let name = loader::meta_section_name(cx.sess().target.target.options.is_like_osx);
name.unwrap_or("rust_metadata").with_c_str(|buf| { name.with_c_str(|buf| {
llvm::LLVMSetSection(llglobal, buf) llvm::LLVMSetSection(llglobal, buf)
}); });
} }

View File

@ -17,8 +17,6 @@ use middle::trans::cabi_x86_win64;
use middle::trans::cabi_arm; use middle::trans::cabi_arm;
use middle::trans::cabi_mips; use middle::trans::cabi_mips;
use middle::trans::type_::Type; use middle::trans::type_::Type;
use syntax::abi::{X86, X86_64, Arm, Mips, Mipsel};
use syntax::abi::{OsWindows};
#[deriving(Clone, PartialEq)] #[deriving(Clone, PartialEq)]
pub enum ArgKind { pub enum ArgKind {
@ -107,16 +105,16 @@ pub fn compute_abi_info(ccx: &CrateContext,
atys: &[Type], atys: &[Type],
rty: Type, rty: Type,
ret_def: bool) -> FnType { ret_def: bool) -> FnType {
match ccx.sess().targ_cfg.arch { match ccx.sess().target.target.arch.as_slice() {
X86 => cabi_x86::compute_abi_info(ccx, atys, rty, ret_def), "x86" => cabi_x86::compute_abi_info(ccx, atys, rty, ret_def),
X86_64 => "x86_64" => if ccx.sess().target.target.options.is_like_windows {
if ccx.sess().targ_cfg.os == OsWindows { cabi_x86_win64::compute_abi_info(ccx, atys, rty, ret_def)
cabi_x86_win64::compute_abi_info(ccx, atys, rty, ret_def) } else {
} else { cabi_x86_64::compute_abi_info(ccx, atys, rty, ret_def)
cabi_x86_64::compute_abi_info(ccx, atys, rty, ret_def) },
}, "arm" => cabi_arm::compute_abi_info(ccx, atys, rty, ret_def),
Arm => cabi_arm::compute_abi_info(ccx, atys, rty, ret_def), "mips" => cabi_mips::compute_abi_info(ccx, atys, rty, ret_def),
Mips => cabi_mips::compute_abi_info(ccx, atys, rty, ret_def), a => ccx.sess().fatal((format!("unrecognized arch \"{}\" in target specification", a))
Mipsel => cabi_mips::compute_abi_info(ccx, atys, rty, ret_def), .as_slice()),
} }
} }

View File

@ -13,7 +13,6 @@ use middle::trans::cabi::{ArgType, FnType};
use middle::trans::type_::Type; use middle::trans::type_::Type;
use super::common::*; use super::common::*;
use super::machine::*; use super::machine::*;
use syntax::abi::{OsWindows, OsMacos, OsiOS};
pub fn compute_abi_info(ccx: &CrateContext, pub fn compute_abi_info(ccx: &CrateContext,
atys: &[Type], atys: &[Type],
@ -34,19 +33,17 @@ pub fn compute_abi_info(ccx: &CrateContext,
// Clang's ABI handling is in lib/CodeGen/TargetInfo.cpp // Clang's ABI handling is in lib/CodeGen/TargetInfo.cpp
enum Strategy { RetValue(Type), RetPointer } enum Strategy { RetValue(Type), RetPointer }
let strategy = match ccx.sess().targ_cfg.os { let t = &ccx.sess().target.target;
OsWindows | OsMacos | OsiOS => { let strategy = if t.options.is_like_osx || t.options.is_like_windows {
match llsize_of_alloc(ccx, rty) { match llsize_of_alloc(ccx, rty) {
1 => RetValue(Type::i8(ccx)), 1 => RetValue(Type::i8(ccx)),
2 => RetValue(Type::i16(ccx)), 2 => RetValue(Type::i16(ccx)),
4 => RetValue(Type::i32(ccx)), 4 => RetValue(Type::i32(ccx)),
8 => RetValue(Type::i64(ccx)), 8 => RetValue(Type::i64(ccx)),
_ => RetPointer _ => RetPointer
}
}
_ => {
RetPointer
} }
} else {
RetPointer
}; };
match strategy { match strategy {

View File

@ -34,7 +34,6 @@ use std::c_str::ToCStr;
use std::ptr; use std::ptr;
use std::rc::Rc; use std::rc::Rc;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use syntax::abi;
use syntax::ast; use syntax::ast;
use syntax::parse::token::InternedString; use syntax::parse::token::InternedString;
@ -220,16 +219,16 @@ unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextR
let llmod = mod_name.with_c_str(|buf| { let llmod = mod_name.with_c_str(|buf| {
llvm::LLVMModuleCreateWithNameInContext(buf, llcx) llvm::LLVMModuleCreateWithNameInContext(buf, llcx)
}); });
sess.targ_cfg sess.target
.target_strs .target
.data_layout .data_layout
.as_slice() .as_slice()
.with_c_str(|buf| { .with_c_str(|buf| {
llvm::LLVMSetDataLayout(llmod, buf); llvm::LLVMSetDataLayout(llmod, buf);
}); });
sess.targ_cfg sess.target
.target_strs .target
.target_triple .llvm_target
.as_slice() .as_slice()
.with_c_str(|buf| { .with_c_str(|buf| {
llvm::LLVMRustSetNormalizedTarget(llmod, buf); llvm::LLVMRustSetNormalizedTarget(llmod, buf);
@ -378,8 +377,8 @@ impl LocalCrateContext {
let td = mk_target_data(shared.tcx let td = mk_target_data(shared.tcx
.sess .sess
.targ_cfg .target
.target_strs .target
.data_layout .data_layout
.as_slice()); .as_slice());
@ -531,16 +530,8 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
} }
} }
// Although there is an experimental implementation of LLVM which
// supports SS on armv7 it wasn't approved by Apple, see:
// http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20140505/216350.html
// It looks like it might be never accepted to upstream LLVM.
//
// So far the decision was to disable them in default builds
// but it could be enabled (with patched LLVM)
pub fn is_split_stack_supported(&self) -> bool { pub fn is_split_stack_supported(&self) -> bool {
let ref cfg = self.sess().targ_cfg; self.sess().target.target.options.morestack
(cfg.os != abi::OsiOS || cfg.arch != abi::Arm) && cfg.os != abi::OsWindows
} }

View File

@ -211,7 +211,7 @@ use std::ptr;
use std::rc::{Rc, Weak}; use std::rc::{Rc, Weak};
use syntax::util::interner::Interner; use syntax::util::interner::Interner;
use syntax::codemap::{Span, Pos}; use syntax::codemap::{Span, Pos};
use syntax::{abi, ast, codemap, ast_util, ast_map}; use syntax::{ast, codemap, ast_util, ast_map};
use syntax::ast_util::PostExpansionMethod; use syntax::ast_util::PostExpansionMethod;
use syntax::parse::token; use syntax::parse::token;
use syntax::parse::token::special_idents; use syntax::parse::token::special_idents;
@ -750,8 +750,7 @@ pub fn finalize(cx: &CrateContext) {
// instruct LLVM to emit an older version of dwarf, however, // instruct LLVM to emit an older version of dwarf, however,
// for OS X to understand. For more info see #11352 // for OS X to understand. For more info see #11352
// This can be overridden using --llvm-opts -dwarf-version,N. // This can be overridden using --llvm-opts -dwarf-version,N.
if cx.sess().targ_cfg.os == abi::OsMacos || if cx.sess().target.target.options.is_like_osx {
cx.sess().targ_cfg.os == abi::OsiOS {
"Dwarf Version".with_c_str( "Dwarf Version".with_c_str(
|s| llvm::LLVMRustAddModuleFlag(cx.llmod(), s, 2)); |s| llvm::LLVMRustAddModuleFlag(cx.llmod(), s, 2));
} }

View File

@ -34,7 +34,7 @@ use syntax::parse::token::{InternedString, special_idents};
use syntax::parse::token; use syntax::parse::token;
use syntax::{ast}; use syntax::{ast};
use syntax::{attr, ast_map}; use syntax::{attr, ast_map};
use util::ppaux::{Repr, UserString}; use util::ppaux::Repr;
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Type definitions // Type definitions
@ -70,39 +70,35 @@ struct LlvmSignature {
// Calls to external functions // Calls to external functions
pub fn llvm_calling_convention(ccx: &CrateContext, pub fn llvm_calling_convention(ccx: &CrateContext,
abi: Abi) -> Option<CallConv> { abi: Abi) -> CallConv {
let os = ccx.sess().targ_cfg.os; match ccx.sess().target.target.adjust_abi(abi) {
let arch = ccx.sess().targ_cfg.arch; RustIntrinsic => {
abi.for_target(os, arch).map(|abi| { // Intrinsics are emitted at the call site
match abi { ccx.sess().bug("asked to register intrinsic fn");
RustIntrinsic => {
// Intrinsics are emitted at the call site
ccx.sess().bug("asked to register intrinsic fn");
}
Rust => {
// FIXME(#3678) Implement linking to foreign fns with Rust ABI
ccx.sess().unimpl("foreign functions with Rust ABI");
}
RustCall => {
// FIXME(#3678) Implement linking to foreign fns with Rust ABI
ccx.sess().unimpl("foreign functions with RustCall ABI");
}
// It's the ABI's job to select this, not us.
System => ccx.sess().bug("system abi should be selected elsewhere"),
Stdcall => llvm::X86StdcallCallConv,
Fastcall => llvm::X86FastcallCallConv,
C => llvm::CCallConv,
Win64 => llvm::X86_64_Win64,
// These API constants ought to be more specific...
Cdecl => llvm::CCallConv,
Aapcs => llvm::CCallConv,
} }
})
Rust => {
// FIXME(#3678) Implement linking to foreign fns with Rust ABI
ccx.sess().unimpl("foreign functions with Rust ABI");
}
RustCall => {
// FIXME(#3678) Implement linking to foreign fns with Rust ABI
ccx.sess().unimpl("foreign functions with RustCall ABI");
}
// It's the ABI's job to select this, not us.
System => ccx.sess().bug("system abi should be selected elsewhere"),
Stdcall => llvm::X86StdcallCallConv,
Fastcall => llvm::X86FastcallCallConv,
C => llvm::CCallConv,
Win64 => llvm::X86_64_Win64,
// These API constants ought to be more specific...
Cdecl => llvm::CCallConv,
Aapcs => llvm::CCallConv,
}
} }
pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> { pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> {
@ -191,7 +187,7 @@ pub fn register_static(ccx: &CrateContext,
} }
pub fn register_foreign_item_fn(ccx: &CrateContext, abi: Abi, fty: ty::t, pub fn register_foreign_item_fn(ccx: &CrateContext, abi: Abi, fty: ty::t,
name: &str, span: Option<Span>) -> ValueRef { name: &str) -> ValueRef {
/*! /*!
* Registers a foreign function found in a library. * Registers a foreign function found in a library.
* Just adds a LLVM global. * Just adds a LLVM global.
@ -204,25 +200,7 @@ pub fn register_foreign_item_fn(ccx: &CrateContext, abi: Abi, fty: ty::t,
fty.repr(ccx.tcx()), fty.repr(ccx.tcx()),
name); name);
let cc = match llvm_calling_convention(ccx, abi) { let cc = llvm_calling_convention(ccx, abi);
Some(cc) => cc,
None => {
match span {
Some(s) => {
ccx.sess().span_fatal(s,
format!("ABI `{}` has no suitable calling convention \
for target architecture",
abi.user_string(ccx.tcx())).as_slice())
}
None => {
ccx.sess().fatal(
format!("ABI `{}` has no suitable calling convention \
for target architecture",
abi.user_string(ccx.tcx())).as_slice())
}
}
}
};
// Register the function as a C extern fn // Register the function as a C extern fn
let tys = foreign_types_for_fn_ty(ccx, fty); let tys = foreign_types_for_fn_ty(ccx, fty);
@ -375,16 +353,7 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
llargs_foreign.push(llarg_foreign); llargs_foreign.push(llarg_foreign);
} }
let cc = match llvm_calling_convention(ccx, fn_abi) { let cc = llvm_calling_convention(ccx, fn_abi);
Some(cc) => cc,
None => {
// FIXME(#8357) We really ought to report a span here
ccx.sess().fatal(
format!("ABI string `{}` has no suitable ABI \
for target architecture",
fn_abi.user_string(ccx.tcx())).as_slice());
}
};
// A function pointer is called without the declaration available, so we have to apply // A function pointer is called without the declaration available, so we have to apply
// any attributes with ABI implications directly to the call instruction. // any attributes with ABI implications directly to the call instruction.
@ -498,8 +467,7 @@ pub fn trans_foreign_mod(ccx: &CrateContext, foreign_mod: &ast::ForeignMod) {
abi => { abi => {
let ty = ty::node_id_to_type(ccx.tcx(), foreign_item.id); let ty = ty::node_id_to_type(ccx.tcx(), foreign_item.id);
register_foreign_item_fn(ccx, abi, ty, register_foreign_item_fn(ccx, abi, ty,
lname.get().as_slice(), lname.get().as_slice());
Some(foreign_item.span));
// Unlike for other items, we shouldn't call // Unlike for other items, we shouldn't call
// `base::update_linkage` here. Foreign items have // `base::update_linkage` here. Foreign items have
// special linkage requirements, which are handled // special linkage requirements, which are handled
@ -548,8 +516,7 @@ pub fn decl_rust_fn_with_foreign_abi(ccx: &CrateContext,
let llfn_ty = lltype_for_fn_from_foreign_types(ccx, &tys); let llfn_ty = lltype_for_fn_from_foreign_types(ccx, &tys);
let cconv = match ty::get(t).sty { let cconv = match ty::get(t).sty {
ty::ty_bare_fn(ref fn_ty) => { ty::ty_bare_fn(ref fn_ty) => {
let c = llvm_calling_convention(ccx, fn_ty.abi); llvm_calling_convention(ccx, fn_ty.abi)
c.unwrap_or(llvm::CCallConv)
} }
_ => panic!("expected bare fn in decl_rust_fn_with_foreign_abi") _ => panic!("expected bare fn in decl_rust_fn_with_foreign_abi")
}; };
@ -572,8 +539,7 @@ pub fn register_rust_fn_with_foreign_abi(ccx: &CrateContext,
let t = ty::node_id_to_type(ccx.tcx(), node_id); let t = ty::node_id_to_type(ccx.tcx(), node_id);
let cconv = match ty::get(t).sty { let cconv = match ty::get(t).sty {
ty::ty_bare_fn(ref fn_ty) => { ty::ty_bare_fn(ref fn_ty) => {
let c = llvm_calling_convention(ccx, fn_ty.abi); llvm_calling_convention(ccx, fn_ty.abi)
c.unwrap_or(llvm::CCallConv)
} }
_ => panic!("expected bare fn in register_rust_fn_with_foreign_abi") _ => panic!("expected bare fn in register_rust_fn_with_foreign_abi")
}; };

View File

@ -17,7 +17,6 @@ use llvm::{Float, Double, X86_FP80, PPC_FP128, FP128};
use middle::trans::context::CrateContext; use middle::trans::context::CrateContext;
use syntax::ast; use syntax::ast;
use syntax::abi::{X86, X86_64, Arm, Mips, Mipsel};
use std::c_str::ToCStr; use std::c_str::ToCStr;
use std::mem; use std::mem;
@ -105,9 +104,10 @@ impl Type {
} }
pub fn int(ccx: &CrateContext) -> Type { pub fn int(ccx: &CrateContext) -> Type {
match ccx.tcx().sess.targ_cfg.arch { match ccx.tcx().sess.target.target.target_word_size.as_slice() {
X86 | Arm | Mips | Mipsel => Type::i32(ccx), "32" => Type::i32(ccx),
X86_64 => Type::i64(ccx) "64" => Type::i64(ccx),
tws => panic!("Unsupported target word size for int: {}", tws),
} }
} }

View File

@ -4840,7 +4840,7 @@ pub fn check_enum_variants(ccx: &CrateCtxt,
ast::TyU16 => disr as u16 as Disr == disr, ast::TyU16 => disr as u16 as Disr == disr,
ast::TyU32 => disr as u32 as Disr == disr, ast::TyU32 => disr as u32 as Disr == disr,
ast::TyU64 => disr as u64 as Disr == disr, ast::TyU64 => disr as u64 as Disr == disr,
ast::TyU => uint_in_range(ccx, ccx.tcx.sess.targ_cfg.uint_type, disr) ast::TyU => uint_in_range(ccx, ccx.tcx.sess.target.uint_type, disr)
} }
} }
fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool { fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
@ -4849,7 +4849,7 @@ pub fn check_enum_variants(ccx: &CrateCtxt,
ast::TyI16 => disr as i16 as Disr == disr, ast::TyI16 => disr as i16 as Disr == disr,
ast::TyI32 => disr as i32 as Disr == disr, ast::TyI32 => disr as i32 as Disr == disr,
ast::TyI64 => disr as i64 as Disr == disr, ast::TyI64 => disr as i64 as Disr == disr,
ast::TyI => int_in_range(ccx, ccx.tcx.sess.targ_cfg.int_type, disr) ast::TyI => int_in_range(ccx, ccx.tcx.sess.target.int_type, disr)
} }
} }
match ty { match ty {

View File

@ -16,7 +16,6 @@ use std::io::{fs, TempDir};
use std::io; use std::io;
use std::os; use std::os;
use std::str; use std::str;
use syntax::abi;
use syntax::diagnostic::Handler as ErrorHandler; use syntax::diagnostic::Handler as ErrorHandler;
pub static METADATA_FILENAME: &'static str = "rust.metadata.bin"; pub static METADATA_FILENAME: &'static str = "rust.metadata.bin";
@ -25,7 +24,8 @@ pub struct ArchiveConfig<'a> {
pub handler: &'a ErrorHandler, pub handler: &'a ErrorHandler,
pub dst: Path, pub dst: Path,
pub lib_search_paths: Vec<Path>, pub lib_search_paths: Vec<Path>,
pub os: abi::Os, pub slib_prefix: String,
pub slib_suffix: String,
pub maybe_ar_prog: Option<String> pub maybe_ar_prog: Option<String>
} }
@ -33,7 +33,8 @@ pub struct Archive<'a> {
handler: &'a ErrorHandler, handler: &'a ErrorHandler,
dst: Path, dst: Path,
lib_search_paths: Vec<Path>, lib_search_paths: Vec<Path>,
os: abi::Os, slib_prefix: String,
slib_suffix: String,
maybe_ar_prog: Option<String> maybe_ar_prog: Option<String>
} }
@ -96,14 +97,11 @@ fn run_ar(handler: &ErrorHandler, maybe_ar_prog: &Option<String>,
} }
} }
pub fn find_library(name: &str, os: abi::Os, search_paths: &[Path], pub fn find_library(name: &str, osprefix: &str, ossuffix: &str,
handler: &ErrorHandler) -> Path { search_paths: &[Path], handler: &ErrorHandler) -> Path {
let (osprefix, osext) = match os {
abi::OsWindows => ("", "lib"), _ => ("lib", "a"),
};
// On Windows, static libraries sometimes show up as libfoo.a and other // On Windows, static libraries sometimes show up as libfoo.a and other
// times show up as foo.lib // times show up as foo.lib
let oslibname = format!("{}{}.{}", osprefix, name, osext); let oslibname = format!("{}{}{}", osprefix, name, ossuffix);
let unixlibname = format!("lib{}.a", name); let unixlibname = format!("lib{}.a", name);
for path in search_paths.iter() { for path in search_paths.iter() {
@ -122,12 +120,14 @@ pub fn find_library(name: &str, os: abi::Os, search_paths: &[Path],
impl<'a> Archive<'a> { impl<'a> Archive<'a> {
fn new(config: ArchiveConfig<'a>) -> Archive<'a> { fn new(config: ArchiveConfig<'a>) -> Archive<'a> {
let ArchiveConfig { handler, dst, lib_search_paths, os, maybe_ar_prog } = config; let ArchiveConfig { handler, dst, lib_search_paths, slib_prefix, slib_suffix,
maybe_ar_prog } = config;
Archive { Archive {
handler: handler, handler: handler,
dst: dst, dst: dst,
lib_search_paths: lib_search_paths, lib_search_paths: lib_search_paths,
os: os, slib_prefix: slib_prefix,
slib_suffix: slib_suffix,
maybe_ar_prog: maybe_ar_prog maybe_ar_prog: maybe_ar_prog
} }
} }
@ -178,7 +178,9 @@ impl<'a> ArchiveBuilder<'a> {
/// Adds all of the contents of a native library to this archive. This will /// Adds all of the contents of a native library to this archive. This will
/// search in the relevant locations for a library named `name`. /// search in the relevant locations for a library named `name`.
pub fn add_native_library(&mut self, name: &str) -> io::IoResult<()> { pub fn add_native_library(&mut self, name: &str) -> io::IoResult<()> {
let location = find_library(name, self.archive.os, let location = find_library(name,
self.archive.slib_prefix.as_slice(),
self.archive.slib_suffix.as_slice(),
self.archive.lib_search_paths.as_slice(), self.archive.lib_search_paths.as_slice(),
self.archive.handler); self.archive.handler);
self.add_archive(&location, name, []) self.add_archive(&location, name, [])

View File

@ -51,3 +51,4 @@ pub mod svh;
pub mod target_strs; pub mod target_strs;
pub mod x86; pub mod x86;
pub mod x86_64; pub mod x86_64;
pub mod target;

View File

@ -12,13 +12,13 @@
use std::collections::HashSet; use std::collections::HashSet;
use std::os; use std::os;
use std::io::IoError; use std::io::IoError;
use syntax::abi;
use syntax::ast; use syntax::ast;
pub struct RPathConfig<'a> { pub struct RPathConfig<'a> {
pub os: abi::Os,
pub used_crates: Vec<(ast::CrateNum, Option<Path>)>, pub used_crates: Vec<(ast::CrateNum, Option<Path>)>,
pub out_filename: Path, pub out_filename: Path,
pub is_like_osx: bool,
pub has_rpath: bool,
pub get_install_prefix_lib_path: ||:'a -> Path, pub get_install_prefix_lib_path: ||:'a -> Path,
pub realpath: |&Path|:'a -> Result<Path, IoError> pub realpath: |&Path|:'a -> Result<Path, IoError>
} }
@ -26,24 +26,12 @@ pub struct RPathConfig<'a> {
pub fn get_rpath_flags(config: RPathConfig) -> Vec<String> { pub fn get_rpath_flags(config: RPathConfig) -> Vec<String> {
// No rpath on windows // No rpath on windows
if config.os == abi::OsWindows { if !config.has_rpath {
return Vec::new(); return Vec::new();
} }
let mut flags = Vec::new(); let mut flags = Vec::new();
if config.os == abi::OsFreebsd {
flags.push_all(["-Wl,-rpath,/usr/local/lib/gcc46".to_string(),
"-Wl,-rpath,/usr/local/lib/gcc44".to_string(),
"-Wl,-z,origin".to_string()]);
}
else if config.os == abi::OsDragonfly {
flags.push_all(["-Wl,-rpath,/usr/lib/gcc47".to_string(),
"-Wl,-rpath,/usr/lib/gcc44".to_string(),
"-Wl,-z,origin".to_string()]);
}
debug!("preparing the RPATH!"); debug!("preparing the RPATH!");
let libs = config.used_crates.clone(); let libs = config.used_crates.clone();
@ -107,14 +95,11 @@ fn get_rpath_relative_to_output(config: &mut RPathConfig,
lib: &Path) -> String { lib: &Path) -> String {
use std::os; use std::os;
assert!(config.os != abi::OsWindows);
// Mac doesn't appear to support $ORIGIN // Mac doesn't appear to support $ORIGIN
let prefix = match config.os { let prefix = if config.is_like_osx {
abi::OsAndroid | abi::OsLinux | abi::OsFreebsd | abi::OsDragonfly "@loader_path"
=> "$ORIGIN", } else {
abi::OsMacos => "@loader_path", "$ORIGIN"
abi::OsWindows | abi::OsiOS => unreachable!()
}; };
let mut lib = (config.realpath)(&os::make_absolute(lib)).unwrap(); let mut lib = (config.realpath)(&os::make_absolute(lib)).unwrap();
@ -203,10 +188,11 @@ mod test {
#[cfg(any(target_os = "linux", target_os = "android"))] #[cfg(any(target_os = "linux", target_os = "android"))]
fn test_rpath_relative() { fn test_rpath_relative() {
let config = &mut RPathConfig { let config = &mut RPathConfig {
os: abi::OsLinux,
used_crates: Vec::new(), used_crates: Vec::new(),
out_filename: Path::new("bin/rustc"), out_filename: Path::new("bin/rustc"),
get_install_prefix_lib_path: || panic!(), get_install_prefix_lib_path: || panic!(),
has_rpath: true,
is_like_osx: false,
realpath: |p| Ok(p.clone()) realpath: |p| Ok(p.clone())
}; };
let res = get_rpath_relative_to_output(config, &Path::new("lib/libstd.so")); let res = get_rpath_relative_to_output(config, &Path::new("lib/libstd.so"));
@ -217,8 +203,9 @@ mod test {
#[cfg(target_os = "freebsd")] #[cfg(target_os = "freebsd")]
fn test_rpath_relative() { fn test_rpath_relative() {
let config = &mut RPathConfig { let config = &mut RPathConfig {
os: abi::OsFreebsd,
used_crates: Vec::new(), used_crates: Vec::new(),
has_rpath: true,
is_like_osx: false,
out_filename: Path::new("bin/rustc"), out_filename: Path::new("bin/rustc"),
get_install_prefix_lib_path: || panic!(), get_install_prefix_lib_path: || panic!(),
realpath: |p| Ok(p.clone()) realpath: |p| Ok(p.clone())
@ -231,8 +218,9 @@ mod test {
#[cfg(target_os = "dragonfly")] #[cfg(target_os = "dragonfly")]
fn test_rpath_relative() { fn test_rpath_relative() {
let config = &mut RPathConfig { let config = &mut RPathConfig {
os: abi::OsDragonfly,
used_crates: Vec::new(), used_crates: Vec::new(),
has_rpath: true,
is_like_osx: false,
out_filename: Path::new("bin/rustc"), out_filename: Path::new("bin/rustc"),
get_install_prefix_lib_path: || panic!(), get_install_prefix_lib_path: || panic!(),
realpath: |p| Ok(p.clone()) realpath: |p| Ok(p.clone())
@ -245,8 +233,9 @@ mod test {
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
fn test_rpath_relative() { fn test_rpath_relative() {
let config = &mut RPathConfig { let config = &mut RPathConfig {
os: abi::OsMacos,
used_crates: Vec::new(), used_crates: Vec::new(),
has_rpath: true,
is_like_osx: true,
out_filename: Path::new("bin/rustc"), out_filename: Path::new("bin/rustc"),
get_install_prefix_lib_path: || panic!(), get_install_prefix_lib_path: || panic!(),
realpath: |p| Ok(p.clone()) realpath: |p| Ok(p.clone())

View File

@ -0,0 +1,29 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use target::TargetOptions;
use std::default::Default;
pub fn opts() -> TargetOptions {
TargetOptions {
// OSX has -dead_strip, which doesn't rely on ffunction_sections
function_sections: false,
linker: "cc".to_string(),
dynamic_linking: true,
executables: true,
is_like_osx: true,
morestack: true,
has_rpath: true,
dll_prefix: "lib".to_string(),
dll_suffix: ".dylib".to_string(),
pre_link_args: Vec::new(),
.. Default::default()
}
}

View File

@ -0,0 +1,37 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use target::{Target, TargetOptions};
pub fn target() -> Target {
Target {
data_layout: "e-p:32:32:32\
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string(),
llvm_target: "arm-apple-ios".to_string(),
target_endian: "little".to_string(),
target_word_size: "32".to_string(),
arch: "arm".to_string(),
target_os: "ios".to_string(),
options: TargetOptions {
features: "+v7,+thumb2,+vfp3,+neon".to_string(),
executables: false,
dynamic_linking: false,
// Although there is an experimental implementation of LLVM which
// supports SS on armv7 it wasn't approved by Apple, see:
// http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20140505/216350.html
// It looks like it might be never accepted to upstream LLVM.
morestack: false,
.. super::apple_base::opts()
}
}
}

View File

@ -0,0 +1,33 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use target::Target;
pub fn target() -> Target {
let mut base = super::linux_base::opts();
base.features = "+v7".to_string();
// Many of the symbols defined in compiler-rt are also defined in libgcc. Android
// linker doesn't like that by default.
base.pre_link_args.push("-Wl,--allow-multiple-definition".to_string());
Target {
data_layout: "e-p:32:32:32\
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string(),
llvm_target: "arm-linux-androideabi".to_string(),
target_endian: "little".to_string(),
target_word_size: "32".to_string(),
arch: "arm".to_string(),
target_os: "android".to_string(),
options: base,
}
}

View File

@ -0,0 +1,32 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use target::{Target, TargetOptions};
pub fn target() -> Target {
let base = super::linux_base::opts();
Target {
data_layout: "e-p:32:32:32\
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string(),
llvm_target: "arm-unknown-linux-gnueabi".to_string(),
target_endian: "little".to_string(),
target_word_size: "32".to_string(),
arch: "arm".to_string(),
target_os: "linux".to_string(),
options: TargetOptions {
features: "+v6".to_string(),
.. base
},
}
}

View File

@ -0,0 +1,32 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use target::{Target, TargetOptions};
pub fn target() -> Target {
let base = super::linux_base::opts();
Target {
data_layout: "e-p:32:32:32\
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string(),
llvm_target: "arm-unknown-linux-gnueabi".to_string(),
target_endian: "little".to_string(),
target_word_size: "32".to_string(),
arch: "arm".to_string(),
target_os: "linux".to_string(),
options: TargetOptions {
features: "+v6,+vfp2".to_string(),
.. base
}
}
}

View File

@ -0,0 +1,30 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use target::TargetOptions;
use std::default::Default;
pub fn opts() -> TargetOptions {
TargetOptions {
linker: "cc".to_string(),
dynamic_linking: true,
executables: true,
morestack: true,
has_rpath: true,
pre_link_args: vec!(
"-L/usr/local/lib".to_string(),
"-L/usr/local/lib/gcc47".to_string(),
"-L/usr/local/lib/gcc44".to_string(),
),
.. Default::default()
}
}

View File

@ -0,0 +1,30 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use target::TargetOptions;
use std::default::Default;
pub fn opts() -> TargetOptions {
TargetOptions {
linker: "cc".to_string(),
dynamic_linking: true,
executables: true,
morestack: true,
has_rpath: true,
pre_link_args: vec!(
"-L/usr/local/lib".to_string(),
"-L/usr/local/lib/gcc46".to_string(),
"-L/usr/local/lib/gcc44".to_string(),
),
.. Default::default()
}
}

View File

@ -0,0 +1,28 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use target::Target;
pub fn target() -> Target {
Target {
data_layout: "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16\
-i32:32:32-i64:32:64\
-f32:32:32-f64:32:64-v64:64:64\
-v128:128:128-a0:0:64-f80:128:128\
-n8:16:32".to_string(),
llvm_target: "i386-apple-ios".to_string(),
target_endian: "little".to_string(),
target_word_size: "32".to_string(),
arch: "x86".to_string(),
target_os: "ios".to_string(),
options: super::apple_base::opts()
}
}

View File

@ -0,0 +1,28 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use target::Target;
pub fn target() -> Target {
Target {
data_layout: "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16\
-i32:32:32-i64:32:64\
-f32:32:32-f64:32:64-v64:64:64\
-v128:128:128-a0:0:64-f80:128:128\
-n8:16:32".to_string(),
llvm_target: "i686-apple-darwin".to_string(),
target_endian: "little".to_string(),
target_word_size: "32".to_string(),
arch: "x86".to_string(),
target_os: "macos".to_string(),
options: super::apple_base::opts()
}
}

View File

@ -0,0 +1,34 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use target::Target;
pub fn target() -> Target {
let mut options = super::windows_base::opts();
// Mark all dynamic libraries and executables as compatible with the larger 4GiB address
// space available to x86 Windows binaries on x86_64.
options.pre_link_args.push("-Wl,--large-address-aware".to_string());
// Make sure that we link to the dynamic libgcc, otherwise cross-module
// DWARF stack unwinding will not work.
// This behavior may be overridden by -Clink-args="-static-libgcc"
options.pre_link_args.push("-shared-libgcc".to_string());
Target {
data_layout: "e-p:32:32-f64:64:64-i64:64:64-f80:32:32-n8:16:32".to_string(),
llvm_target: "i686-pc-windows-gnu".to_string(),
target_endian: "little".to_string(),
target_word_size: "32".to_string(),
arch: "x86".to_string(),
target_os: "windows".to_string(),
options: options,
}
}

View File

@ -0,0 +1,23 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use target::Target;
pub fn target() -> Target {
Target {
data_layout: "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32".to_string(),
llvm_target: "i686-unknown-dragonfly".to_string(),
target_endian: "little".to_string(),
target_word_size: "32".to_string(),
arch: "x86".to_string(),
target_os: "dragonfly".to_string(),
options: super::dragonfly_base::opts()
}
}

View File

@ -0,0 +1,23 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use target::Target;
pub fn target() -> Target {
Target {
data_layout: "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32".to_string(),
llvm_target: "i686-unknown-linux-gnu".to_string(),
target_endian: "little".to_string(),
target_word_size: "32".to_string(),
arch: "x86".to_string(),
target_os: "linux".to_string(),
options: super::linux_base::opts()
}
}

View File

@ -0,0 +1,31 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use target::TargetOptions;
use std::default::Default;
pub fn opts() -> TargetOptions {
TargetOptions {
linker: "cc".to_string(),
dynamic_linking: true,
executables: true,
morestack: true,
linker_is_gnu: true,
has_rpath: true,
pre_link_args: vec!(
// GNU-style linkers will use this to omit linking to libraries which
// don't actually fulfill any relocations, but only for libraries which
// follow this flag. Thus, use it before specifying libraries to link to.
"-Wl,--as-needed".to_string(),
),
position_independant_executables: true,
.. Default::default()
}
}

View File

@ -0,0 +1,27 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use target::Target;
pub fn target() -> Target {
Target {
data_layout: "E-p:32:32:32\
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string(),
llvm_target: "mips-unknown-linux-gnu".to_string(),
target_endian: "big".to_string(),
target_word_size: "32".to_string(),
arch: "mips".to_string(),
target_os: "linux".to_string(),
options: super::linux_base::opts()
}
}

View File

@ -0,0 +1,28 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use target::Target;
pub fn target() -> Target {
Target {
data_layout: "e-p:32:32:32\
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string(),
llvm_target: "mipsel-unknown-linux-gnu".to_string(),
target_endian: "little".to_string(),
target_word_size: "32".to_string(),
arch: "mips".to_string(),
target_os: "linux".to_string(),
options: super::linux_base::opts()
}
}

View File

@ -0,0 +1,379 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! [Flexible target specification.](https://github.com/rust-lang/rfcs/pull/131)
//!
//! Rust targets a wide variety of usecases, and in the interest of flexibility,
//! allows new target triples to be defined in configuration files. Most users
//! will not need to care about these, but this is invaluable when porting Rust
//! to a new platform, and allows for an unprecedented level of control over how
//! the compiler works.
//!
//! # Using custom targets
//!
//! A target triple, as passed via `rustc --target=TRIPLE`, will first be
//! compared against the list of built-in targets. This is to ease distributing
//! rustc (no need for configuration files) and also to hold these built-in
//! targets as immutable and sacred. If `TRIPLE` is not one of the built-in
//! targets, rustc will check if a file named `TRIPLE` exists. If it does, it
//! will be loaded as the target configuration. If the file does not exist,
//! rustc will search each directory in the environment variable
//! `RUST_TARGET_PATH` for a file named `TRIPLE.json`. The first one found will
//! be loaded. If no file is found in any of those directories, a fatal error
//! will be given. `RUST_TARGET_PATH` includes `/etc/rustc` as its last entry,
//! to be searched by default.
//!
//! Projects defining their own targets should use
//! `--target=path/to/my-awesome-platform.json` instead of adding to
//! `RUST_TARGET_PATH`.
//!
//! # Defining a new target
//!
//! Targets are defined using [JSON](http://json.org/). The `Target` struct in
//! this module defines the format the JSON file should take, though each
//! underscore in the field names should be replaced with a hyphen (`-`) in the
//! JSON file. Some fields are required in every target specification, such as
//! `data-layout`, `llvm-target`, `target-endian`, `target-word-size`, and
//! `arch`. In general, options passed to rustc with `-C` override the target's
//! settings, though `target-feature` and `link-args` will *add* to the list
//! specified by the target, rather than replace.
use serialize::json::Json;
use syntax::{diagnostic, abi};
use std::default::Default;
use std::io::fs::PathExtensions;
mod windows_base;
mod linux_base;
mod apple_base;
mod freebsd_base;
mod dragonfly_base;
mod arm_apple_ios;
mod arm_linux_androideabi;
mod arm_unknown_linux_gnueabi;
mod arm_unknown_linux_gnueabihf;
mod i686_apple_darwin;
mod i386_apple_ios;
mod i686_pc_windows_gnu;
mod i686_unknown_linux_gnu;
mod mips_unknown_linux_gnu;
mod mipsel_unknown_linux_gnu;
mod x86_64_apple_darwin;
mod x86_64_pc_windows_gnu;
mod x86_64_unknown_freebsd;
mod x86_64_unknown_dragonfly;
mod x86_64_unknown_linux_gnu;
/// Everything `rustc` knows about how to compile for a specific target.
///
/// Every field here must be specified, and has no default value.
#[deriving(Clone, Show)]
pub struct Target {
/// [Data layout](http://llvm.org/docs/LangRef.html#data-layout) to pass to LLVM.
pub data_layout: String,
/// Target triple to pass to LLVM.
pub llvm_target: String,
/// String to use as the `target_endian` `cfg` variable.
pub target_endian: String,
/// String to use as the `target_word_size` `cfg` variable.
pub target_word_size: String,
/// OS name to use for conditional compilation.
pub target_os: String,
/// Architecture to use for ABI considerations. Valid options: "x86", "x86_64", "arm", and
/// "mips". "mips" includes "mipsel".
pub arch: String,
/// Optional settings with defaults.
pub options: TargetOptions,
}
/// Optional aspects of a target specification.
///
/// This has an implementation of `Default`, see each field for what the default is. In general,
/// these try to take "minimal defaults" that don't assume anything about the runtime they run in.
#[deriving(Clone, Show)]
pub struct TargetOptions {
/// Linker to invoke. Defaults to "cc".
pub linker: String,
/// Linker arguments that are unconditionally passed *before* any user-defined libraries.
pub pre_link_args: Vec<String>,
/// Linker arguments that are unconditionally passed *after* any user-defined libraries.
pub post_link_args: Vec<String>,
/// Default CPU to pass to LLVM. Corresponds to `llc -mcpu=$cpu`. Defaults to "default".
pub cpu: String,
/// Default target features to pass to LLVM. These features will *always* be passed, and cannot
/// be disabled even via `-C`. Corresponds to `llc -mattr=$features`.
pub features: String,
/// Whether dynamic linking is available on this target. Defaults to false.
pub dynamic_linking: bool,
/// Whether executables are available on this target. iOS, for example, only allows static
/// libraries. Defaults to false.
pub executables: bool,
/// Whether LLVM's segmented stack prelude is supported by whatever runtime is available.
/// Will emit stack checks and calls to __morestack. Defaults to false.
pub morestack: bool,
/// Relocation model to use in object file. Corresponds to `llc
/// -relocation-model=$relocation_model`. Defaults to "pic".
pub relocation_model: String,
/// Code model to use. Corresponds to `llc -code-model=$code_model`. Defaults to "default".
pub code_model: String,
/// Do not emit code that uses the "red zone", if the ABI has one. Defaults to false.
pub disable_redzone: bool,
/// Eliminate frame pointers from stack frames if possible. Defaults to true.
pub eliminate_frame_pointer: bool,
/// Emit each function in its own section. Defaults to true.
pub function_sections: bool,
/// String to prepend to the name of every dynamic library. Defaults to "lib".
pub dll_prefix: String,
/// String to append to the name of every dynamic library. Defaults to ".so".
pub dll_suffix: String,
/// String to append to the name of every executable.
pub exe_suffix: String,
/// String to prepend to the name of every static library. Defaults to "lib".
pub staticlib_prefix: String,
/// String to append to the name of every static library. Defaults to ".a".
pub staticlib_suffix: String,
/// Whether the target toolchain is like OSX's. Only useful for compiling against iOS/OS X, in
/// particular running dsymutil and some other stuff like `-dead_strip`. Defaults to false.
pub is_like_osx: bool,
/// Whether the target toolchain is like Windows'. Only useful for compiling against Windows,
/// only realy used for figuring out how to find libraries, since Windows uses its own
/// library naming convention. Defaults to false.
pub is_like_windows: bool,
/// Whether the linker support GNU-like arguments such as -O. Defaults to false.
pub linker_is_gnu: bool,
/// Whether the linker support rpaths or not. Defaults to false.
pub has_rpath: bool,
/// Whether to disable linking to compiler-rt. Defaults to false, as LLVM will emit references
/// to the functions that compiler-rt provides.
pub no_compiler_rt: bool,
/// Dynamically linked executables can be compiled as position independent if the default
/// relocation model of position independent code is not changed. This is a requirement to take
/// advantage of ASLR, as otherwise the functions in the executable are not randomized and can
/// be used during an exploit of a vulnerability in any code.
pub position_independant_executables: bool,
}
impl Default for TargetOptions {
/// Create a set of "sane defaults" for any target. This is still incomplete, and if used for
/// compilation, will certainly not work.
fn default() -> TargetOptions {
TargetOptions {
linker: "cc".to_string(),
pre_link_args: Vec::new(),
post_link_args: Vec::new(),
cpu: "generic".to_string(),
features: "".to_string(),
dynamic_linking: false,
executables: false,
morestack: false,
relocation_model: "pic".to_string(),
code_model: "default".to_string(),
disable_redzone: false,
eliminate_frame_pointer: true,
function_sections: true,
dll_prefix: "lib".to_string(),
dll_suffix: ".so".to_string(),
exe_suffix: "".to_string(),
staticlib_prefix: "lib".to_string(),
staticlib_suffix: ".a".to_string(),
is_like_osx: false,
is_like_windows: false,
linker_is_gnu: false,
has_rpath: false,
no_compiler_rt: false,
position_independant_executables: false,
}
}
}
impl Target {
/// Given a function ABI, turn "System" into the correct ABI for this target.
pub fn adjust_abi(&self, abi: abi::Abi) -> abi::Abi {
match abi {
abi::System => {
if self.options.is_like_windows && self.arch.as_slice() == "x86" {
abi::Stdcall
} else {
abi::C
}
},
abi => abi
}
}
/// Load a target descriptor from a JSON object.
pub fn from_json(obj: Json) -> Target {
// this is 1. ugly, 2. error prone.
let handler = diagnostic::default_handler(diagnostic::Auto, None);
let get_req_field = |name: &str| {
match obj.find(&name.to_string())
.map(|s| s.as_string())
.and_then(|os| os.map(|s| s.to_string())) {
Some(val) => val,
None =>
handler.fatal((format!("Field {} in target specification is required", name))
.as_slice())
}
};
let mut base = Target {
data_layout: get_req_field("data-layout"),
llvm_target: get_req_field("llvm-target"),
target_endian: get_req_field("target-endian"),
target_word_size: get_req_field("target-word-size"),
arch: get_req_field("arch"),
target_os: get_req_field("os"),
options: Default::default(),
};
macro_rules! key (
($key_name:ident) => ( {
let name = (stringify!($key_name)).replace("_", "-");
obj.find(&name).map(|o| o.as_string()
.map(|s| base.options.$key_name = s.to_string()));
} );
($key_name:ident, bool) => ( {
let name = (stringify!($key_name)).replace("_", "-");
obj.find(&name).map(|o| o.as_boolean().map(|s| base.options.$key_name = s));
} );
($key_name:ident, list) => ( {
let name = (stringify!($key_name)).replace("_", "-");
obj.find(&name).map(|o| o.as_list()
.map(|v| base.options.$key_name = v.iter()
.map(|a| a.as_string().unwrap().to_string()).collect()
)
);
} );
)
key!(cpu);
key!(linker);
key!(relocation_model);
key!(code_model);
key!(dll_prefix);
key!(dll_suffix);
key!(exe_suffix);
key!(staticlib_prefix);
key!(staticlib_suffix);
key!(features);
key!(dynamic_linking, bool);
key!(executables, bool);
key!(morestack, bool);
key!(disable_redzone, bool);
key!(eliminate_frame_pointer, bool);
key!(function_sections, bool);
key!(is_like_osx, bool);
key!(is_like_windows, bool);
key!(linker_is_gnu, bool);
key!(has_rpath, bool);
key!(no_compiler_rt, bool);
key!(pre_link_args, list);
key!(post_link_args, list);
base
}
/// Search RUST_TARGET_PATH for a JSON file specifying the given target triple. Note that it
/// could also just be a bare filename already, so also check for that. If one of the hardcoded
/// targets we know about, just return it directly.
///
/// The error string could come from any of the APIs called, including filesystem access and
/// JSON decoding.
pub fn search(target: &str) -> Result<Target, String> {
use std::os;
use std::io::File;
use std::path::Path;
use serialize::json;
fn load_file(path: &Path) -> Result<Target, String> {
let mut f = try!(File::open(path).map_err(|e| e.to_string()));
let obj = try!(json::from_reader(&mut f).map_err(|e| e.to_string()));
Ok(Target::from_json(obj))
}
// this would use a match if stringify! were allowed in pattern position
macro_rules! load_specific (
( $($name:ident),+ ) => (
{
let target = target.replace("-", "_");
let target = target.as_slice();
if false { }
$(
else if target == stringify!($name) {
let t = $name::target();
debug!("Got builtin target: {}", t);
return Ok(t);
}
)*
else if target == "x86_64-w64-mingw32" {
let t = x86_64_pc_windows_gnu::target();
return Ok(t);
} else if target == "i686-w64-mingw32" {
let t = i686_pc_windows_gnu::target();
return Ok(t);
}
}
)
)
load_specific!(
x86_64_unknown_linux_gnu,
i686_unknown_linux_gnu,
mips_unknown_linux_gnu,
mipsel_unknown_linux_gnu,
arm_linux_androideabi,
arm_unknown_linux_gnueabi,
arm_unknown_linux_gnueabihf,
x86_64_unknown_freebsd,
x86_64_unknown_dragonfly,
x86_64_apple_darwin,
i686_apple_darwin,
i386_apple_ios,
arm_apple_ios,
x86_64_pc_windows_gnu,
i686_pc_windows_gnu
)
let path = Path::new(target);
if path.is_file() {
return load_file(&path);
}
let path = {
let mut target = target.to_string();
target.push_str(".json");
Path::new(target)
};
let target_path = os::getenv("RUST_TARGET_PATH").unwrap_or(String::new());
let paths = os::split_paths(target_path.as_slice());
// FIXME 16351: add a sane default search path?
for dir in paths.iter() {
let p = dir.join(path.clone());
if p.is_file() {
return load_file(&p);
}
}
Err(format!("Could not find specification for target {}", target))
}
}

View File

@ -0,0 +1,66 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use target::TargetOptions;
use std::default::Default;
pub fn opts() -> TargetOptions {
TargetOptions {
// FIXME(#13846) this should be enabled for windows
function_sections: false,
linker: "gcc".to_string(),
dynamic_linking: true,
executables: true,
dll_prefix: "".to_string(),
dll_suffix: ".dll".to_string(),
exe_suffix: ".exe".to_string(),
staticlib_prefix: "".to_string(),
staticlib_suffix: ".lib".to_string(),
morestack: false,
is_like_windows: true,
pre_link_args: vec!(
// And here, we see obscure linker flags #45. On windows, it has been
// found to be necessary to have this flag to compile liblibc.
//
// First a bit of background. On Windows, the file format is not ELF,
// but COFF (at least according to LLVM). COFF doesn't officially allow
// for section names over 8 characters, apparently. Our metadata
// section, ".note.rustc", you'll note is over 8 characters.
//
// On more recent versions of gcc on mingw, apparently the section name
// is *not* truncated, but rather stored elsewhere in a separate lookup
// table. On older versions of gcc, they apparently always truncated th
// section names (at least in some cases). Truncating the section name
// actually creates "invalid" objects [1] [2], but only for some
// introspection tools, not in terms of whether it can be loaded.
//
// Long story short, passing this flag forces the linker to *not*
// truncate section names (so we can find the metadata section after
// it's compiled). The real kicker is that rust compiled just fine on
// windows for quite a long time *without* this flag, so I have no idea
// why it suddenly started failing for liblibc. Regardless, we
// definitely don't want section name truncation, so we're keeping this
// flag for windows.
//
// [1] - https://sourceware.org/bugzilla/show_bug.cgi?id=13130
// [2] - https://code.google.com/p/go/issues/detail?id=2139
"-Wl,--enable-long-section-names".to_string(),
// Tell GCC to avoid linker plugins, because we are not bundling
// them with Windows installer, and Rust does its own LTO anyways.
"-fno-use-linker-plugin".to_string(),
// Always enable DEP (NX bit) when it is available
"-Wl,--nxcompat".to_string(),
),
.. Default::default()
}
}

View File

@ -0,0 +1,29 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use target::Target;
pub fn target() -> Target {
let mut base = super::apple_base::opts();
base.eliminate_frame_pointer = false;
base.pre_link_args.push("-m64".to_string());
Target {
data_layout: "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
s0:64:64-f80:128:128-n8:16:32:64".to_string(),
llvm_target: "x86_64-apple-darwin".to_string(),
target_endian: "little".to_string(),
target_word_size: "64".to_string(),
arch: "x86_64".to_string(),
target_os: "macos".to_string(),
options: base,
}
}

View File

@ -0,0 +1,31 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use target::Target;
pub fn target() -> Target {
let mut base = super::windows_base::opts();
// On Win64 unwinding is handled by the OS, so we can link libgcc statically.
base.pre_link_args.push("-static-libgcc".to_string());
base.pre_link_args.push("-m64".to_string());
Target {
// FIXME: Test this. Copied from linux (#2398)
data_layout: "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
s0:64:64-f80:128:128-n8:16:32:64-S128".to_string(),
llvm_target: "x86_64-pc-windows-gnu".to_string(),
target_endian: "little".to_string(),
target_word_size: "64".to_string(),
arch: "x86_64".to_string(),
target_os: "windows".to_string(),
options: base,
}
}

View File

@ -0,0 +1,23 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use target::Target;
pub fn target() -> Target {
Target {
data_layout: "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32".to_string(),
llvm_target: "x86_64-unknown-dragonfly".to_string(),
target_endian: "little".to_string(),
target_word_size: "32".to_string(),
arch: "x86_64".to_string(),
target_os: "dragonfly".to_string(),
options: super::dragonfly_base::opts()
}
}

View File

@ -0,0 +1,28 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use target::Target;
pub fn target() -> Target {
let mut base = super::freebsd_base::opts();
base.pre_link_args.push("-m64".to_string());
Target {
data_layout: "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
s0:64:64-f80:128:128-n8:16:32:64-S128".to_string(),
llvm_target: "x86_64-unknown-freebsd".to_string(),
target_endian: "little".to_string(),
target_word_size: "64".to_string(),
arch: "x86_64".to_string(),
target_os: "freebsd".to_string(),
options: base,
}
}

View File

@ -0,0 +1,28 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use target::Target;
pub fn target() -> Target {
let mut base = super::linux_base::opts();
base.pre_link_args.push("-m64".to_string());
Target {
data_layout: "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
s0:64:64-f80:128:128-n8:16:32:64-S128".to_string(),
llvm_target: "x86_64-unknown-linux-gnu".to_string(),
target_endian: "little".to_string(),
target_word_size: "64".to_string(),
arch: "x86_64".to_string(),
target_os: "linux".to_string(),
options: base,
}
}

View File

@ -183,7 +183,7 @@ fn runtest(test: &str, cratename: &str, libs: Vec<Path>, externs: core::Externs,
// environment to ensure that the target loads the right libraries at // environment to ensure that the target loads the right libraries at
// runtime. It would be a sad day if the *host* libraries were loaded as a // runtime. It would be a sad day if the *host* libraries were loaded as a
// mistake. // mistake.
let mut cmd = Command::new(outdir.path().join("rust_out")); let mut cmd = Command::new(outdir.path().join("rust-out"));
let newpath = { let newpath = {
let mut path = DynamicLibrary::search_path(); let mut path = DynamicLibrary::search_path();
path.insert(0, libdir.clone()); path.insert(0, libdir.clone());

View File

@ -37,9 +37,6 @@ pub enum Abi {
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
#[deriving(PartialEq)] #[deriving(PartialEq)]
pub enum Architecture { pub enum Architecture {
// NB. You cannot change the ordering of these
// constants without adjusting IntelBits below.
// (This is ensured by the test indices_are_correct().)
X86, X86,
X86_64, X86_64,
Arm, Arm,
@ -47,20 +44,11 @@ pub enum Architecture {
Mipsel Mipsel
} }
#[allow(non_upper_case_globals)]
const IntelBits: u32 = (1 << (X86 as uint)) | (1 << (X86_64 as uint));
#[allow(non_upper_case_globals)]
const ArmBits: u32 = (1 << (Arm as uint));
pub struct AbiData { pub struct AbiData {
abi: Abi, abi: Abi,
// Name of this ABI as we like it called. // Name of this ABI as we like it called.
name: &'static str, name: &'static str,
// Is it specific to a platform? If so, which one? Also, what is
// the name that LLVM gives it (in case we disagree)
abi_arch: AbiArchitecture
} }
pub enum AbiArchitecture { pub enum AbiArchitecture {
@ -75,22 +63,21 @@ pub enum AbiArchitecture {
#[allow(non_upper_case_globals)] #[allow(non_upper_case_globals)]
static AbiDatas: &'static [AbiData] = &[ static AbiDatas: &'static [AbiData] = &[
// Platform-specific ABIs // Platform-specific ABIs
AbiData {abi: Cdecl, name: "cdecl", abi_arch: Archs(IntelBits)}, AbiData {abi: Cdecl, name: "cdecl" },
AbiData {abi: Stdcall, name: "stdcall", abi_arch: Archs(IntelBits)}, AbiData {abi: Stdcall, name: "stdcall" },
AbiData {abi: Fastcall, name:"fastcall", abi_arch: Archs(IntelBits)}, AbiData {abi: Fastcall, name:"fastcall" },
AbiData {abi: Aapcs, name: "aapcs", abi_arch: Archs(ArmBits)}, AbiData {abi: Aapcs, name: "aapcs" },
AbiData {abi: Win64, name: "win64", AbiData {abi: Win64, name: "win64" },
abi_arch: Archs(1 << (X86_64 as uint))},
// Cross-platform ABIs // Cross-platform ABIs
// //
// NB: Do not adjust this ordering without // NB: Do not adjust this ordering without
// adjusting the indices below. // adjusting the indices below.
AbiData {abi: Rust, name: "Rust", abi_arch: RustArch}, AbiData {abi: Rust, name: "Rust" },
AbiData {abi: C, name: "C", abi_arch: AllArch}, AbiData {abi: C, name: "C" },
AbiData {abi: System, name: "system", abi_arch: AllArch}, AbiData {abi: System, name: "system" },
AbiData {abi: RustIntrinsic, name: "rust-intrinsic", abi_arch: RustArch}, AbiData {abi: RustIntrinsic, name: "rust-intrinsic" },
AbiData {abi: RustCall, name: "rust-call", abi_arch: RustArch}, AbiData {abi: RustCall, name: "rust-call" },
]; ];
/// Returns the ABI with the given name (if any). /// Returns the ABI with the given name (if any).
@ -116,28 +103,6 @@ impl Abi {
pub fn name(&self) -> &'static str { pub fn name(&self) -> &'static str {
self.data().name self.data().name
} }
pub fn for_target(&self, os: Os, arch: Architecture) -> Option<Abi> {
// If this ABI isn't actually for the specified architecture, then we
// short circuit early
match self.data().abi_arch {
Archs(a) if a & arch.bit() == 0 => return None,
Archs(_) | RustArch | AllArch => {}
}
// Transform this ABI as appropriate for the requested os/arch
// combination.
Some(match (*self, os, arch) {
(System, OsWindows, X86) => Stdcall,
(System, _, _) => C,
(me, _, _) => me,
})
}
}
impl Architecture {
fn bit(&self) -> u32 {
1 << (*self as uint)
}
} }
impl fmt::Show for Abi { impl fmt::Show for Abi {
@ -184,23 +149,4 @@ fn indices_are_correct() {
for (i, abi_data) in AbiDatas.iter().enumerate() { for (i, abi_data) in AbiDatas.iter().enumerate() {
assert_eq!(i, abi_data.abi.index()); assert_eq!(i, abi_data.abi.index());
} }
let bits = 1 << (X86 as uint);
let bits = bits | 1 << (X86_64 as uint);
assert_eq!(IntelBits, bits);
let bits = 1 << (Arm as uint);
assert_eq!(ArmBits, bits);
}
#[test]
fn pick_uniplatform() {
assert_eq!(Stdcall.for_target(OsLinux, X86), Some(Stdcall));
assert_eq!(Stdcall.for_target(OsLinux, Arm), None);
assert_eq!(System.for_target(OsLinux, X86), Some(C));
assert_eq!(System.for_target(OsWindows, X86), Some(Stdcall));
assert_eq!(System.for_target(OsWindows, X86_64), Some(C));
assert_eq!(System.for_target(OsWindows, Arm), Some(C));
assert_eq!(Stdcall.for_target(OsWindows, X86), Some(Stdcall));
assert_eq!(Stdcall.for_target(OsWindows, X86_64), Some(Stdcall));
} }

View File

@ -4,6 +4,7 @@
ifndef IS_WINDOWS ifndef IS_WINDOWS
all: all:
@echo $(RUSTDOC)
$(HOST_RPATH_ENV) $(RUSTDOC) --test foo.rs $(HOST_RPATH_ENV) $(RUSTDOC) --test foo.rs
$(HOST_RPATH_ENV) $(RUSTDOC) -w html -o $(TMPDIR)/doc foo.rs $(HOST_RPATH_ENV) $(RUSTDOC) -w html -o $(TMPDIR)/doc foo.rs
cp verify.sh $(TMPDIR) cp verify.sh $(TMPDIR)

View File

@ -0,0 +1,11 @@
-include ../tools.mk
all:
$(RUSTC) foo.rs --target=my-awesome-platform.json --crate-type=lib --emit=asm
grep --quiet --invert-match morestack < $(TMPDIR)/foo.s
$(RUSTC) foo.rs --target=my-invalid-platform.json 2>&1 | grep --quiet --invert-match "Error loading taget specification"
$(RUSTC) foo.rs --target=my-incomplete-platform.json 2>&1 | grep 'Field llvm-target'
RUST_TARGET_PATH=. $(RUSTC) foo.rs --target=my-awesome-platform --crate-type=lib --emit=asm
RUST_TARGET_PATH=. $(RUSTC) foo.rs --target=x86_64-unknown-linux-gnu --crate-type=lib --emit=asm
# The built-in target *should* override the one we have here, and thus we
# should have morestack
grep --quiet morestack < $(TMPDIR)/foo.s

View File

@ -0,0 +1,26 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(lang_items)]
#![no_std]
#[lang="sized"]
trait Sized { }
#[lang="start"]
fn start(_main: *const u8, _argc: int, _argv: *const *const u8) -> int { 0 }
extern {
fn _foo() -> [u8, ..16];
}
fn _main() {
let _a = unsafe { _foo() };
}

View File

@ -0,0 +1,9 @@
{
"data-layout": "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32",
"llvm-target": "i686-unknown-linux-gnu",
"target-endian": "little",
"target-word-size": "32",
"arch": "x86",
"os": "linux",
"morestack": false
}

View File

@ -0,0 +1,8 @@
{
"data-layout": "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32",
"target-endian": "little",
"target-word-size": "32",
"arch": "x86",
"os": "foo",
"morestack": false
}

View File

@ -0,0 +1 @@
wow this json is really broke!

View File

@ -0,0 +1,9 @@
{
"data-layout": "e-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32",
"llvm-target": "i686-unknown-linux-gnu",
"target-endian": "little",
"target-word-size": "32",
"arch": "x86",
"os": "linux",
"morestack": false
}