9
9
// except according to those terms.
10
10
11
11
use super :: archive:: { Archive , ArchiveBuilder , ArchiveConfig , METADATA_FILENAME } ;
12
- use super :: archive;
13
- use super :: rpath;
12
+ use super :: linker:: { Linker , GnuLinker } ;
14
13
use super :: rpath:: RPathConfig ;
14
+ use super :: rpath;
15
15
use super :: svh:: Svh ;
16
16
use session:: config;
17
17
use session:: config:: NoDebugInfo ;
@@ -29,7 +29,6 @@ use util::sha2::{Digest, Sha256};
29
29
use util:: fs:: fix_windows_verbatim_for_gcc;
30
30
use rustc_back:: tempdir:: TempDir ;
31
31
32
- use std:: ffi:: OsString ;
33
32
use std:: fs:: { self , PathExt } ;
34
33
use std:: io:: { self , Read , Write } ;
35
34
use std:: mem;
@@ -801,10 +800,13 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
801
800
cmd. arg ( root. join ( obj) ) ;
802
801
}
803
802
804
- link_args ( & mut cmd, sess, dylib, tmpdir. path ( ) ,
805
- trans, obj_filename, out_filename) ;
806
- if !sess. target . target . options . no_compiler_rt {
807
- cmd. arg ( "-lcompiler-rt" ) ;
803
+ {
804
+ let mut linker = GnuLinker { cmd : & mut cmd, sess : & sess } ;
805
+ link_args ( & mut linker, sess, dylib, tmpdir. path ( ) ,
806
+ trans, obj_filename, out_filename) ;
807
+ if !sess. target . target . options . no_compiler_rt {
808
+ linker. link_staticlib ( "compiler-rt" ) ;
809
+ }
808
810
}
809
811
for obj in & sess. target . target . options . post_link_objects {
810
812
cmd. arg ( root. join ( obj) ) ;
@@ -858,7 +860,7 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
858
860
}
859
861
}
860
862
861
- fn link_args ( cmd : & mut Command ,
863
+ fn link_args ( cmd : & mut Linker ,
862
864
sess : & Session ,
863
865
dylib : bool ,
864
866
tmpdir : & Path ,
@@ -873,10 +875,10 @@ fn link_args(cmd: &mut Command,
873
875
// target descriptor
874
876
let t = & sess. target . target ;
875
877
876
- cmd. arg ( "-L" ) . arg ( & fix_windows_verbatim_for_gcc ( & lib_path) ) ;
877
-
878
- cmd. arg ( "-o" ) . arg ( out_filename) . arg ( obj_filename) ;
878
+ cmd. include_path ( & fix_windows_verbatim_for_gcc ( & lib_path) ) ;
879
879
880
+ cmd. output_filename ( out_filename) ;
881
+ cmd. add_object ( obj_filename) ;
880
882
881
883
// Stack growth requires statically linking a __morestack function. Note
882
884
// that this is listed *before* all other libraries. Due to the usage of the
@@ -895,89 +897,44 @@ fn link_args(cmd: &mut Command,
895
897
// will include the __morestack symbol 100% of the time, always resolving
896
898
// references to it even if the object above didn't use it.
897
899
if t. options . morestack {
898
- if t. options . is_like_osx {
899
- let morestack = lib_path. join ( "libmorestack.a" ) ;
900
-
901
- let mut v = OsString :: from ( "-Wl,-force_load," ) ;
902
- v. push ( & morestack) ;
903
- cmd. arg ( & v) ;
904
- } else {
905
- cmd. args ( & [ "-Wl,--whole-archive" , "-lmorestack" , "-Wl,--no-whole-archive" ] ) ;
906
- }
900
+ cmd. link_whole_staticlib ( "morestack" , & [ lib_path] ) ;
907
901
}
908
902
909
903
// When linking a dynamic library, we put the metadata into a section of the
910
904
// executable. This metadata is in a separate object file from the main
911
905
// object file, so we link that in here.
912
906
if dylib {
913
- cmd. arg ( & obj_filename. with_extension ( "metadata.o" ) ) ;
907
+ cmd. add_object ( & obj_filename. with_extension ( "metadata.o" ) ) ;
914
908
}
915
909
916
- if t. options . is_like_osx {
917
- // The dead_strip option to the linker specifies that functions and data
918
- // unreachable by the entry point will be removed. This is quite useful
919
- // with Rust's compilation model of compiling libraries at a time into
920
- // one object file. For example, this brings hello world from 1.7MB to
921
- // 458K.
922
- //
923
- // Note that this is done for both executables and dynamic libraries. We
924
- // won't get much benefit from dylibs because LLVM will have already
925
- // stripped away as much as it could. This has not been seen to impact
926
- // link times negatively.
927
- //
928
- // -dead_strip can't be part of the pre_link_args because it's also used
929
- // for partial linking when using multiple codegen units (-r). So we
930
- // insert it here.
931
- cmd. arg ( "-Wl,-dead_strip" ) ;
932
- }
933
-
934
- // If we're building a dylib, we don't use --gc-sections because LLVM has
935
- // already done the best it can do, and we also don't want to eliminate the
936
- // metadata. If we're building an executable, however, --gc-sections drops
937
- // the size of hello world from 1.8MB to 597K, a 67% reduction.
938
- if !dylib && !t. options . is_like_osx {
939
- cmd. arg ( "-Wl,--gc-sections" ) ;
940
- }
910
+ // Try to strip as much out of the generated object by removing unused
911
+ // sections if possible. See more comments in linker.rs
912
+ cmd. gc_sections ( dylib) ;
941
913
942
914
let used_link_args = sess. cstore . get_used_link_args ( ) . borrow ( ) ;
943
915
944
- if t. options . position_independent_executables {
916
+ if !dylib && t. options . position_independent_executables {
945
917
let empty_vec = Vec :: new ( ) ;
946
918
let empty_str = String :: new ( ) ;
947
919
let args = sess. opts . cg . link_args . as_ref ( ) . unwrap_or ( & empty_vec) ;
948
920
let mut args = args. iter ( ) . chain ( used_link_args. iter ( ) ) ;
949
- if !dylib
950
- && ( t. options . relocation_model == "pic"
951
- || * sess. opts . cg . relocation_model . as_ref ( )
952
- . unwrap_or ( & empty_str) == "pic" )
921
+ let relocation_model = sess. opts . cg . relocation_model . as_ref ( )
922
+ . unwrap_or ( & empty_str) ;
923
+ if ( t. options . relocation_model == "pic" || * relocation_model == "pic" )
953
924
&& !args. any ( |x| * x == "-static" ) {
954
- cmd. arg ( "-pie" ) ;
925
+ cmd. position_independent_executable ( ) ;
955
926
}
956
927
}
957
928
958
- if t. options . linker_is_gnu {
959
- // GNU-style linkers support optimization with -O. GNU ld doesn't need a
960
- // numeric argument, but other linkers do.
961
- if sess. opts . optimize == config:: Default ||
962
- sess. opts . optimize == config:: Aggressive {
963
- cmd. arg ( "-Wl,-O1" ) ;
964
- }
965
- }
929
+ // Pass optimization flags down to the linker.
930
+ cmd. optimize ( ) ;
966
931
967
932
// We want to prevent the compiler from accidentally leaking in any system
968
933
// libraries, so we explicitly ask gcc to not link to any libraries by
969
934
// default. Note that this does not happen for windows because windows pulls
970
935
// in some large number of libraries and I couldn't quite figure out which
971
936
// subset we wanted.
972
- if !t. options . is_like_windows {
973
- cmd. arg ( "-nodefaultlibs" ) ;
974
- }
975
-
976
- // Mark all dynamic libraries and executables as compatible with ASLR
977
- // FIXME #17098: ASLR breaks gdb
978
- if t. options . is_like_windows && sess. opts . debuginfo == NoDebugInfo {
979
- // cmd.arg("-Wl,--dynamicbase");
980
- }
937
+ cmd. no_default_libraries ( ) ;
981
938
982
939
// Take careful note of the ordering of the arguments we pass to the linker
983
940
// here. Linkers will assume that things on the left depend on things to the
@@ -1019,18 +976,7 @@ fn link_args(cmd: &mut Command,
1019
976
// # Telling the linker what we're doing
1020
977
1021
978
if dylib {
1022
- // On mac we need to tell the linker to let this library be rpathed
1023
- if sess. target . target . options . is_like_osx {
1024
- cmd. args ( & [ "-dynamiclib" , "-Wl,-dylib" ] ) ;
1025
-
1026
- if sess. opts . cg . rpath {
1027
- let mut v = OsString :: from ( "-Wl,-install_name,@rpath/" ) ;
1028
- v. push ( out_filename. file_name ( ) . unwrap ( ) ) ;
1029
- cmd. arg ( & v) ;
1030
- }
1031
- } else {
1032
- cmd. arg ( "-shared" ) ;
1033
- }
979
+ cmd. build_dylib ( out_filename) ;
1034
980
}
1035
981
1036
982
// FIXME (#2397): At some point we want to rpath our guesses as to
@@ -1059,9 +1005,10 @@ fn link_args(cmd: &mut Command,
1059
1005
1060
1006
// Finally add all the linker arguments provided on the command line along
1061
1007
// with any #[link_args] attributes found inside the crate
1062
- let empty = Vec :: new ( ) ;
1063
- cmd. args ( & sess. opts . cg . link_args . as_ref ( ) . unwrap_or ( & empty) ) ;
1064
- cmd. args ( & used_link_args[ ..] ) ;
1008
+ if let Some ( ref args) = sess. opts . cg . link_args {
1009
+ cmd. args ( args) ;
1010
+ }
1011
+ cmd. args ( & used_link_args) ;
1065
1012
}
1066
1013
1067
1014
// # Native library linking
@@ -1075,21 +1022,15 @@ fn link_args(cmd: &mut Command,
1075
1022
// Also note that the native libraries linked here are only the ones located
1076
1023
// in the current crate. Upstream crates with native library dependencies
1077
1024
// may have their native library pulled in above.
1078
- fn add_local_native_libraries ( cmd : & mut Command , sess : & Session ) {
1025
+ fn add_local_native_libraries ( cmd : & mut Linker , sess : & Session ) {
1079
1026
sess. target_filesearch ( PathKind :: All ) . for_each_lib_search_path ( |path, k| {
1080
1027
match k {
1081
- PathKind :: Framework => { cmd. arg ( "-F" ) . arg ( path) ; }
1082
- _ => { cmd. arg ( "-L" ) . arg ( & fix_windows_verbatim_for_gcc ( path) ) ; }
1028
+ PathKind :: Framework => { cmd. framework_path ( path) ; }
1029
+ _ => { cmd. include_path ( & fix_windows_verbatim_for_gcc ( path) ) ; }
1083
1030
}
1084
1031
FileDoesntMatch
1085
1032
} ) ;
1086
1033
1087
- // Some platforms take hints about whether a library is static or dynamic.
1088
- // For those that support this, we ensure we pass the option if the library
1089
- // was flagged "static" (most defaults are dynamic) to ensure that if
1090
- // libfoo.a and libfoo.so both exist that the right one is chosen.
1091
- let takes_hints = !sess. target . target . options . is_like_osx ;
1092
-
1093
1034
let libs = sess. cstore . get_used_libraries ( ) ;
1094
1035
let libs = libs. borrow ( ) ;
1095
1036
@@ -1100,46 +1041,29 @@ fn add_local_native_libraries(cmd: &mut Command, sess: &Session) {
1100
1041
kind != cstore:: NativeStatic
1101
1042
} ) ;
1102
1043
1103
- // Platforms that take hints generally also support the --whole-archive
1104
- // flag. We need to pass this flag when linking static native libraries to
1105
- // ensure the entire library is included.
1106
- //
1107
- // For more details see #15460, but the gist is that the linker will strip
1108
- // away any unused objects in the archive if we don't otherwise explicitly
1109
- // reference them. This can occur for libraries which are just providing
1110
- // bindings, libraries with generic functions, etc.
1111
- if takes_hints {
1112
- cmd. arg ( "-Wl,--whole-archive" ) . arg ( "-Wl,-Bstatic" ) ;
1113
- }
1044
+ // Some platforms take hints about whether a library is static or dynamic.
1045
+ // For those that support this, we ensure we pass the option if the library
1046
+ // was flagged "static" (most defaults are dynamic) to ensure that if
1047
+ // libfoo.a and libfoo.so both exist that the right one is chosen.
1048
+ cmd. hint_static ( ) ;
1049
+
1114
1050
let search_path = archive_search_paths ( sess) ;
1115
1051
for l in staticlibs {
1116
- if takes_hints {
1117
- cmd. arg ( & format ! ( "-l{}" , l) ) ;
1118
- } else {
1119
- // -force_load is the OSX equivalent of --whole-archive, but it
1120
- // involves passing the full path to the library to link.
1121
- let lib = archive:: find_library ( & l[ ..] ,
1122
- & sess. target . target . options . staticlib_prefix ,
1123
- & sess. target . target . options . staticlib_suffix ,
1124
- & search_path[ ..] ,
1125
- & sess. diagnostic ( ) . handler ) ;
1126
- let mut v = OsString :: from ( "-Wl,-force_load," ) ;
1127
- v. push ( & lib) ;
1128
- cmd. arg ( & v) ;
1129
- }
1130
- }
1131
- if takes_hints {
1132
- cmd. arg ( "-Wl,--no-whole-archive" ) . arg ( "-Wl,-Bdynamic" ) ;
1052
+ // Here we explicitly ask that the entire archive is included into the
1053
+ // result artifact. For more details see #15460, but the gist is that
1054
+ // the linker will strip away any unused objects in the archive if we
1055
+ // don't otherwise explicitly reference them. This can occur for
1056
+ // libraries which are just providing bindings, libraries with generic
1057
+ // functions, etc.
1058
+ cmd. link_whole_staticlib ( l, & search_path) ;
1133
1059
}
1134
1060
1061
+ cmd. hint_dynamic ( ) ;
1062
+
1135
1063
for & ( ref l, kind) in others {
1136
1064
match kind {
1137
- cstore:: NativeUnknown => {
1138
- cmd. arg ( & format ! ( "-l{}" , l) ) ;
1139
- }
1140
- cstore:: NativeFramework => {
1141
- cmd. arg ( "-framework" ) . arg ( & l[ ..] ) ;
1142
- }
1065
+ cstore:: NativeUnknown => cmd. link_dylib ( l) ,
1066
+ cstore:: NativeFramework => cmd. link_framework ( l) ,
1143
1067
cstore:: NativeStatic => unreachable ! ( ) ,
1144
1068
}
1145
1069
}
@@ -1150,7 +1074,7 @@ fn add_local_native_libraries(cmd: &mut Command, sess: &Session) {
1150
1074
// Rust crates are not considered at all when creating an rlib output. All
1151
1075
// dependencies will be linked when producing the final output (instead of
1152
1076
// the intermediate rlib version)
1153
- fn add_upstream_rust_crates ( cmd : & mut Command , sess : & Session ,
1077
+ fn add_upstream_rust_crates ( cmd : & mut Linker , sess : & Session ,
1154
1078
dylib : bool , tmpdir : & Path ,
1155
1079
trans : & CrateTranslation ) {
1156
1080
// All of the heavy lifting has previously been accomplished by the
@@ -1201,7 +1125,7 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session,
1201
1125
}
1202
1126
1203
1127
// Adds the static "rlib" versions of all crates to the command line.
1204
- fn add_static_crate ( cmd : & mut Command , sess : & Session , tmpdir : & Path ,
1128
+ fn add_static_crate ( cmd : & mut Linker , sess : & Session , tmpdir : & Path ,
1205
1129
cratepath : & Path ) {
1206
1130
// When performing LTO on an executable output, all of the
1207
1131
// bytecode from the upstream libraries has already been
@@ -1263,27 +1187,27 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session,
1263
1187
archive. remove_file ( & format ! ( "{}.o" , name) ) ;
1264
1188
let files = archive. files ( ) ;
1265
1189
if files. iter ( ) . any ( |s| s. ends_with ( ".o" ) ) {
1266
- cmd. arg ( & dst) ;
1190
+ cmd. link_rlib ( & dst) ;
1267
1191
}
1268
1192
} ) ;
1269
1193
} else {
1270
- cmd. arg ( & fix_windows_verbatim_for_gcc ( cratepath) ) ;
1194
+ cmd. link_rlib ( & fix_windows_verbatim_for_gcc ( cratepath) ) ;
1271
1195
}
1272
1196
}
1273
1197
1274
1198
// Same thing as above, but for dynamic crates instead of static crates.
1275
- fn add_dynamic_crate ( cmd : & mut Command , sess : & Session , cratepath : & Path ) {
1199
+ fn add_dynamic_crate ( cmd : & mut Linker , sess : & Session , cratepath : & Path ) {
1276
1200
// If we're performing LTO, then it should have been previously required
1277
1201
// that all upstream rust dependencies were available in an rlib format.
1278
1202
assert ! ( !sess. lto( ) ) ;
1279
1203
1280
1204
// Just need to tell the linker about where the library lives and
1281
1205
// what its name is
1282
1206
if let Some ( dir) = cratepath. parent ( ) {
1283
- cmd. arg ( "-L" ) . arg ( & fix_windows_verbatim_for_gcc ( dir) ) ;
1207
+ cmd. include_path ( & fix_windows_verbatim_for_gcc ( dir) ) ;
1284
1208
}
1285
1209
let filestem = cratepath. file_stem ( ) . unwrap ( ) . to_str ( ) . unwrap ( ) ;
1286
- cmd. arg ( & format ! ( "-l{}" , unlib( & sess. target, filestem) ) ) ;
1210
+ cmd. link_dylib ( & unlib ( & sess. target , filestem) ) ;
1287
1211
}
1288
1212
}
1289
1213
@@ -1305,7 +1229,7 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session,
1305
1229
// generic function calls a native function, then the generic function must
1306
1230
// be instantiated in the target crate, meaning that the native symbol must
1307
1231
// also be resolved in the target crate.
1308
- fn add_upstream_native_libraries ( cmd : & mut Command , sess : & Session ) {
1232
+ fn add_upstream_native_libraries ( cmd : & mut Linker , sess : & Session ) {
1309
1233
// Be sure to use a topological sorting of crates because there may be
1310
1234
// interdependencies between native libraries. When passing -nodefaultlibs,
1311
1235
// for example, almost all native libraries depend on libc, so we have to
@@ -1320,13 +1244,8 @@ fn add_upstream_native_libraries(cmd: &mut Command, sess: &Session) {
1320
1244
let libs = csearch:: get_native_libraries ( & sess. cstore , cnum) ;
1321
1245
for & ( kind, ref lib) in & libs {
1322
1246
match kind {
1323
- cstore:: NativeUnknown => {
1324
- cmd. arg ( & format ! ( "-l{}" , * lib) ) ;
1325
- }
1326
- cstore:: NativeFramework => {
1327
- cmd. arg ( "-framework" ) ;
1328
- cmd. arg ( & lib[ ..] ) ;
1329
- }
1247
+ cstore:: NativeUnknown => cmd. link_dylib ( lib) ,
1248
+ cstore:: NativeFramework => cmd. link_framework ( lib) ,
1330
1249
cstore:: NativeStatic => {
1331
1250
sess. bug ( "statics shouldn't be propagated" ) ;
1332
1251
}
0 commit comments