@@ -1255,6 +1255,87 @@ fn add_post_link_args(cmd: &mut dyn Linker, sess: &'a Session, flavor: LinkerFla
12551255 }
12561256}
12571257
1258+ /// Add object files containing code from the current crate.
1259+ fn add_local_crate_regular_objects ( cmd : & mut dyn Linker , codegen_results : & CodegenResults ) {
1260+ for obj in codegen_results. modules . iter ( ) . filter_map ( |m| m. object . as_ref ( ) ) {
1261+ cmd. add_object ( obj) ;
1262+ }
1263+ }
1264+
1265+ /// Add object files for allocator code linked once for the whole crate tree.
1266+ fn add_local_crate_allocator_objects ( cmd : & mut dyn Linker , codegen_results : & CodegenResults ) {
1267+ let obj = codegen_results. allocator_module . as_ref ( ) . and_then ( |m| m. object . as_ref ( ) ) ;
1268+ if let Some ( obj) = obj {
1269+ cmd. add_object ( obj) ;
1270+ }
1271+ }
1272+
1273+ /// Add object files containing metadata for the current crate.
1274+ fn add_local_crate_metadata_objects (
1275+ cmd : & mut dyn Linker ,
1276+ crate_type : config:: CrateType ,
1277+ codegen_results : & CodegenResults ,
1278+ ) {
1279+ // When linking a dynamic library, we put the metadata into a section of the
1280+ // executable. This metadata is in a separate object file from the main
1281+ // object file, so we link that in here.
1282+ if crate_type == config:: CrateType :: Dylib || crate_type == config:: CrateType :: ProcMacro {
1283+ let obj = codegen_results. metadata_module . as_ref ( ) . and_then ( |m| m. object . as_ref ( ) ) ;
1284+ if let Some ( obj) = obj {
1285+ cmd. add_object ( obj) ;
1286+ }
1287+ }
1288+ }
1289+
1290+ /// Link native libraries corresponding to the current crate and all libraries corresponding to
1291+ /// all its dependency crates.
1292+ /// FIXME: Consider combining this with the functions above adding object files for the local crate.
1293+ fn link_local_crate_native_libs_and_dependent_crate_libs < ' a , B : ArchiveBuilder < ' a > > (
1294+ cmd : & mut dyn Linker ,
1295+ sess : & ' a Session ,
1296+ crate_type : config:: CrateType ,
1297+ codegen_results : & CodegenResults ,
1298+ tmpdir : & Path ,
1299+ ) {
1300+ // Take careful note of the ordering of the arguments we pass to the linker
1301+ // here. Linkers will assume that things on the left depend on things to the
1302+ // right. Things on the right cannot depend on things on the left. This is
1303+ // all formally implemented in terms of resolving symbols (libs on the right
1304+ // resolve unknown symbols of libs on the left, but not vice versa).
1305+ //
1306+ // For this reason, we have organized the arguments we pass to the linker as
1307+ // such:
1308+ //
1309+ // 1. The local object that LLVM just generated
1310+ // 2. Local native libraries
1311+ // 3. Upstream rust libraries
1312+ // 4. Upstream native libraries
1313+ //
1314+ // The rationale behind this ordering is that those items lower down in the
1315+ // list can't depend on items higher up in the list. For example nothing can
1316+ // depend on what we just generated (e.g., that'd be a circular dependency).
1317+ // Upstream rust libraries are not allowed to depend on our local native
1318+ // libraries as that would violate the structure of the DAG, in that
1319+ // scenario they are required to link to them as well in a shared fashion.
1320+ //
1321+ // Note that upstream rust libraries may contain native dependencies as
1322+ // well, but they also can't depend on what we just started to add to the
1323+ // link line. And finally upstream native libraries can't depend on anything
1324+ // in this DAG so far because they're only dylibs and dylibs can only depend
1325+ // on other dylibs (e.g., other native deps).
1326+ //
1327+ // If -Zlink-native-libraries=false is set, then the assumption is that an
1328+ // external build system already has the native dependencies defined, and it
1329+ // will provide them to the linker itself.
1330+ if sess. opts . debugging_opts . link_native_libraries . unwrap_or ( true ) {
1331+ add_local_native_libraries ( cmd, sess, codegen_results) ;
1332+ }
1333+ add_upstream_rust_crates :: < B > ( cmd, sess, codegen_results, crate_type, tmpdir) ;
1334+ if sess. opts . debugging_opts . link_native_libraries . unwrap_or ( true ) {
1335+ add_upstream_native_libraries ( cmd, sess, codegen_results, crate_type) ;
1336+ }
1337+ }
1338+
12581339/// Add sysroot and other globally set directories to the directory search list.
12591340fn add_library_search_dirs ( cmd : & mut dyn Linker , sess : & ' a Session ) {
12601341 // The default library location, we need this to find the runtime.
@@ -1271,6 +1352,95 @@ fn add_library_search_dirs(cmd: &mut dyn Linker, sess: &'a Session) {
12711352 cmd. include_path ( & fix_windows_verbatim_for_gcc ( & lib_path) ) ;
12721353}
12731354
1355+ /// Add options requesting executables to be position-independent or not position-independent.
1356+ fn add_position_independent_executable_args (
1357+ cmd : & mut dyn Linker ,
1358+ sess : & ' a Session ,
1359+ flavor : LinkerFlavor ,
1360+ crate_type : config:: CrateType ,
1361+ codegen_results : & CodegenResults ,
1362+ ) {
1363+ if crate_type != config:: CrateType :: Executable {
1364+ return ;
1365+ }
1366+
1367+ let mut position_independent_executable = false ;
1368+ if sess. target . target . options . position_independent_executables {
1369+ let attr_link_args = & * codegen_results. crate_info . link_args ;
1370+ let mut user_defined_link_args = sess. opts . cg . link_args . iter ( ) . chain ( attr_link_args) ;
1371+ if is_pic ( sess)
1372+ && !sess. crt_static ( Some ( crate_type) )
1373+ && !user_defined_link_args. any ( |x| x == "-static" )
1374+ {
1375+ position_independent_executable = true ;
1376+ }
1377+ }
1378+
1379+ if position_independent_executable {
1380+ cmd. position_independent_executable ( ) ;
1381+ } else {
1382+ // recent versions of gcc can be configured to generate position
1383+ // independent executables by default. We have to pass -no-pie to
1384+ // explicitly turn that off. Not applicable to ld.
1385+ if sess. target . target . options . linker_is_gnu && flavor != LinkerFlavor :: Ld {
1386+ cmd. no_position_independent_executable ( ) ;
1387+ }
1388+ }
1389+ }
1390+
1391+ /// Add options making relocation sections in the produced ELF files read-only
1392+ /// and suppressing lazy binding.
1393+ fn add_relro_args ( cmd : & mut dyn Linker , sess : & ' a Session ) {
1394+ let relro_level = match sess. opts . debugging_opts . relro_level {
1395+ Some ( level) => level,
1396+ None => sess. target . target . options . relro_level ,
1397+ } ;
1398+ match relro_level {
1399+ RelroLevel :: Full => {
1400+ cmd. full_relro ( ) ;
1401+ }
1402+ RelroLevel :: Partial => {
1403+ cmd. partial_relro ( ) ;
1404+ }
1405+ RelroLevel :: Off => {
1406+ cmd. no_relro ( ) ;
1407+ }
1408+ RelroLevel :: None => { }
1409+ }
1410+ }
1411+
1412+ /// Add library search paths used at runtime by dynamic linkers.
1413+ fn add_rpath_args (
1414+ cmd : & mut dyn Linker ,
1415+ sess : & ' a Session ,
1416+ codegen_results : & CodegenResults ,
1417+ out_filename : & Path ,
1418+ ) {
1419+ // FIXME (#2397): At some point we want to rpath our guesses as to
1420+ // where extern libraries might live, based on the
1421+ // addl_lib_search_paths
1422+ if sess. opts . cg . rpath {
1423+ let target_triple = sess. opts . target_triple . triple ( ) ;
1424+ let mut get_install_prefix_lib_path = || {
1425+ let install_prefix = option_env ! ( "CFG_PREFIX" ) . expect ( "CFG_PREFIX" ) ;
1426+ let tlib = filesearch:: relative_target_lib_path ( & sess. sysroot , target_triple) ;
1427+ let mut path = PathBuf :: from ( install_prefix) ;
1428+ path. push ( & tlib) ;
1429+
1430+ path
1431+ } ;
1432+ let mut rpath_config = RPathConfig {
1433+ used_crates : & codegen_results. crate_info . used_crates_dynamic ,
1434+ out_filename : out_filename. to_path_buf ( ) ,
1435+ has_rpath : sess. target . target . options . has_rpath ,
1436+ is_like_osx : sess. target . target . options . is_like_osx ,
1437+ linker_is_gnu : sess. target . target . options . linker_is_gnu ,
1438+ get_install_prefix_lib_path : & mut get_install_prefix_lib_path,
1439+ } ;
1440+ cmd. args ( & rpath:: get_rpath_flags ( & mut rpath_config) ) ;
1441+ }
1442+ }
1443+
12741444/// Produce the linker command line containing linker path and arguments.
12751445/// `NO-OPT-OUT` marks the arguments that cannot be removed from the command line
12761446/// by the user without creating a custom target specification.
@@ -1332,9 +1502,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
13321502 add_library_search_dirs ( cmd, sess) ;
13331503
13341504 // OBJECT-FILES-YES
1335- for obj in codegen_results. modules . iter ( ) . filter_map ( |m| m. object . as_ref ( ) ) {
1336- cmd. add_object ( obj) ;
1337- }
1505+ add_local_crate_regular_objects ( cmd, codegen_results) ;
13381506
13391507 // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
13401508 cmd. output_filename ( out_filename) ;
@@ -1353,21 +1521,10 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
13531521 cmd. export_symbols ( tmpdir, crate_type) ;
13541522
13551523 // OBJECT-FILES-YES
1356- // When linking a dynamic library, we put the metadata into a section of the
1357- // executable. This metadata is in a separate object file from the main
1358- // object file, so we link that in here.
1359- if crate_type == config:: CrateType :: Dylib || crate_type == config:: CrateType :: ProcMacro {
1360- let obj = codegen_results. metadata_module . as_ref ( ) . and_then ( |m| m. object . as_ref ( ) ) ;
1361- if let Some ( obj) = obj {
1362- cmd. add_object ( obj) ;
1363- }
1364- }
1524+ add_local_crate_metadata_objects ( cmd, crate_type, codegen_results) ;
13651525
13661526 // OBJECT-FILES-YES
1367- let obj = codegen_results. allocator_module . as_ref ( ) . and_then ( |m| m. object . as_ref ( ) ) ;
1368- if let Some ( obj) = obj {
1369- cmd. add_object ( obj) ;
1370- }
1527+ add_local_crate_allocator_objects ( cmd, codegen_results) ;
13711528
13721529 // OBJECT-FILES-NO, AUDIT-ORDER
13731530 // FIXME: Order dependent, applies to the following objects. Where should it be placed?
@@ -1379,53 +1536,10 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
13791536 }
13801537
13811538 // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
1382- if crate_type == config:: CrateType :: Executable {
1383- let mut position_independent_executable = false ;
1384-
1385- if sess. target . target . options . position_independent_executables {
1386- if is_pic ( sess)
1387- && !sess. crt_static ( Some ( crate_type) )
1388- && !sess
1389- . opts
1390- . cg
1391- . link_args
1392- . iter ( )
1393- . chain ( & * codegen_results. crate_info . link_args )
1394- . any ( |x| x == "-static" )
1395- {
1396- position_independent_executable = true ;
1397- }
1398- }
1399-
1400- if position_independent_executable {
1401- cmd. position_independent_executable ( ) ;
1402- } else {
1403- // recent versions of gcc can be configured to generate position
1404- // independent executables by default. We have to pass -no-pie to
1405- // explicitly turn that off. Not applicable to ld.
1406- if sess. target . target . options . linker_is_gnu && flavor != LinkerFlavor :: Ld {
1407- cmd. no_position_independent_executable ( ) ;
1408- }
1409- }
1410- }
1539+ add_position_independent_executable_args ( cmd, sess, flavor, crate_type, codegen_results) ;
14111540
14121541 // OBJECT-FILES-NO, AUDIT-ORDER
1413- let relro_level = match sess. opts . debugging_opts . relro_level {
1414- Some ( level) => level,
1415- None => sess. target . target . options . relro_level ,
1416- } ;
1417- match relro_level {
1418- RelroLevel :: Full => {
1419- cmd. full_relro ( ) ;
1420- }
1421- RelroLevel :: Partial => {
1422- cmd. partial_relro ( ) ;
1423- }
1424- RelroLevel :: Off => {
1425- cmd. no_relro ( ) ;
1426- }
1427- RelroLevel :: None => { }
1428- }
1542+ add_relro_args ( cmd, sess) ;
14291543
14301544 // OBJECT-FILES-NO, AUDIT-ORDER
14311545 // Pass optimization flags down to the linker.
@@ -1450,43 +1564,13 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
14501564 }
14511565
14521566 // OBJECT-FILES-YES
1453- // Take careful note of the ordering of the arguments we pass to the linker
1454- // here. Linkers will assume that things on the left depend on things to the
1455- // right. Things on the right cannot depend on things on the left. This is
1456- // all formally implemented in terms of resolving symbols (libs on the right
1457- // resolve unknown symbols of libs on the left, but not vice versa).
1458- //
1459- // For this reason, we have organized the arguments we pass to the linker as
1460- // such:
1461- //
1462- // 1. The local object that LLVM just generated
1463- // 2. Local native libraries
1464- // 3. Upstream rust libraries
1465- // 4. Upstream native libraries
1466- //
1467- // The rationale behind this ordering is that those items lower down in the
1468- // list can't depend on items higher up in the list. For example nothing can
1469- // depend on what we just generated (e.g., that'd be a circular dependency).
1470- // Upstream rust libraries are not allowed to depend on our local native
1471- // libraries as that would violate the structure of the DAG, in that
1472- // scenario they are required to link to them as well in a shared fashion.
1473- //
1474- // Note that upstream rust libraries may contain native dependencies as
1475- // well, but they also can't depend on what we just started to add to the
1476- // link line. And finally upstream native libraries can't depend on anything
1477- // in this DAG so far because they're only dylibs and dylibs can only depend
1478- // on other dylibs (e.g., other native deps).
1479- //
1480- // If -Zlink-native-libraries=false is set, then the assumption is that an
1481- // external build system already has the native dependencies defined, and it
1482- // will provide them to the linker itself.
1483- if sess. opts . debugging_opts . link_native_libraries . unwrap_or ( true ) {
1484- add_local_native_libraries ( cmd, sess, codegen_results) ;
1485- }
1486- add_upstream_rust_crates :: < B > ( cmd, sess, codegen_results, crate_type, tmpdir) ;
1487- if sess. opts . debugging_opts . link_native_libraries . unwrap_or ( true ) {
1488- add_upstream_native_libraries ( cmd, sess, codegen_results, crate_type) ;
1489- }
1567+ link_local_crate_native_libs_and_dependent_crate_libs :: < B > (
1568+ cmd,
1569+ sess,
1570+ crate_type,
1571+ codegen_results,
1572+ tmpdir,
1573+ ) ;
14901574
14911575 // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
14921576 // Tell the linker what we're doing.
@@ -1508,29 +1592,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
15081592 }
15091593
15101594 // OBJECT-FILES-NO, AUDIT-ORDER
1511- // FIXME (#2397): At some point we want to rpath our guesses as to
1512- // where extern libraries might live, based on the
1513- // addl_lib_search_paths
1514- if sess. opts . cg . rpath {
1515- let target_triple = sess. opts . target_triple . triple ( ) ;
1516- let mut get_install_prefix_lib_path = || {
1517- let install_prefix = option_env ! ( "CFG_PREFIX" ) . expect ( "CFG_PREFIX" ) ;
1518- let tlib = filesearch:: relative_target_lib_path ( & sess. sysroot , target_triple) ;
1519- let mut path = PathBuf :: from ( install_prefix) ;
1520- path. push ( & tlib) ;
1521-
1522- path
1523- } ;
1524- let mut rpath_config = RPathConfig {
1525- used_crates : & codegen_results. crate_info . used_crates_dynamic ,
1526- out_filename : out_filename. to_path_buf ( ) ,
1527- has_rpath : sess. target . target . options . has_rpath ,
1528- is_like_osx : sess. target . target . options . is_like_osx ,
1529- linker_is_gnu : sess. target . target . options . linker_is_gnu ,
1530- get_install_prefix_lib_path : & mut get_install_prefix_lib_path,
1531- } ;
1532- cmd. args ( & rpath:: get_rpath_flags ( & mut rpath_config) ) ;
1533- }
1595+ add_rpath_args ( cmd, sess, codegen_results, out_filename) ;
15341596
15351597 // OBJECT-FILES-MAYBE, CUSTOMIZATION-POINT
15361598 add_user_defined_link_args ( cmd, sess, codegen_results) ;
0 commit comments