@@ -1255,6 +1255,87 @@ fn add_post_link_args(cmd: &mut dyn Linker, sess: &'a Session, flavor: LinkerFla
1255
1255
}
1256
1256
}
1257
1257
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
+
1258
1339
/// Add sysroot and other globally set directories to the directory search list.
1259
1340
fn add_library_search_dirs ( cmd : & mut dyn Linker , sess : & ' a Session ) {
1260
1341
// 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) {
1271
1352
cmd. include_path ( & fix_windows_verbatim_for_gcc ( & lib_path) ) ;
1272
1353
}
1273
1354
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
+
1274
1444
/// Produce the linker command line containing linker path and arguments.
1275
1445
/// `NO-OPT-OUT` marks the arguments that cannot be removed from the command line
1276
1446
/// by the user without creating a custom target specification.
@@ -1332,9 +1502,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
1332
1502
add_library_search_dirs ( cmd, sess) ;
1333
1503
1334
1504
// 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) ;
1338
1506
1339
1507
// NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
1340
1508
cmd. output_filename ( out_filename) ;
@@ -1353,21 +1521,10 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
1353
1521
cmd. export_symbols ( tmpdir, crate_type) ;
1354
1522
1355
1523
// 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) ;
1365
1525
1366
1526
// 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) ;
1371
1528
1372
1529
// OBJECT-FILES-NO, AUDIT-ORDER
1373
1530
// 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>>(
1379
1536
}
1380
1537
1381
1538
// 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) ;
1411
1540
1412
1541
// 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) ;
1429
1543
1430
1544
// OBJECT-FILES-NO, AUDIT-ORDER
1431
1545
// Pass optimization flags down to the linker.
@@ -1450,43 +1564,13 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
1450
1564
}
1451
1565
1452
1566
// 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
+ ) ;
1490
1574
1491
1575
// NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
1492
1576
// Tell the linker what we're doing.
@@ -1508,29 +1592,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
1508
1592
}
1509
1593
1510
1594
// 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) ;
1534
1596
1535
1597
// OBJECT-FILES-MAYBE, CUSTOMIZATION-POINT
1536
1598
add_user_defined_link_args ( cmd, sess, codegen_results) ;
0 commit comments