@@ -11,7 +11,9 @@ use rustc_session::search_paths::PathKind;
1111/// need out of the shared crate context before we get rid of it. 
1212use  rustc_session:: { filesearch,  Session } ; 
1313use  rustc_span:: symbol:: Symbol ; 
14- use  rustc_target:: spec:: { LinkerFlavor ,  LldFlavor ,  PanicStrategy ,  RelocModel ,  RelroLevel } ; 
14+ use  rustc_target:: spec:: crt_objects:: CrtObjectsFallback ; 
15+ use  rustc_target:: spec:: { LinkOutputKind ,  LinkerFlavor ,  LldFlavor } ; 
16+ use  rustc_target:: spec:: { PanicStrategy ,  RelocModel ,  RelroLevel } ; 
1517
1618use  super :: archive:: ArchiveBuilder ; 
1719use  super :: command:: Command ; 
@@ -1130,33 +1132,70 @@ fn exec_linker(
11301132    } 
11311133} 
11321134
1133- /// Add begin object files defined by the target spec. 
1134- fn  add_pre_link_objects ( cmd :  & mut  dyn  Linker ,  sess :  & Session ,  crate_type :  CrateType )  { 
1135-     let  pre_link_objects = if  crate_type == CrateType :: Executable  { 
1136-         & sess. target . target . options . pre_link_objects_exe 
1137-     }  else  { 
1138-         & sess. target . target . options . pre_link_objects_dll 
1135+ fn  link_output_kind ( sess :  & Session ,  crate_type :  CrateType )  -> LinkOutputKind  { 
1136+     let  kind = match  ( crate_type,  sess. crt_static ( Some ( crate_type) ) ,  sess. relocation_model ( ) )  { 
1137+         ( CrateType :: Executable ,  false ,  RelocModel :: Pic )  => LinkOutputKind :: DynamicPicExe , 
1138+         ( CrateType :: Executable ,  false ,  _)  => LinkOutputKind :: DynamicNoPicExe , 
1139+         ( CrateType :: Executable ,  true ,  RelocModel :: Pic )  => LinkOutputKind :: StaticPicExe , 
1140+         ( CrateType :: Executable ,  true ,  _)  => LinkOutputKind :: StaticNoPicExe , 
1141+         ( _,  true ,  _)  => LinkOutputKind :: StaticDylib , 
1142+         ( _,  false ,  _)  => LinkOutputKind :: DynamicDylib , 
11391143    } ; 
1140-     for  obj in  pre_link_objects { 
1141-         cmd. add_object ( & get_object_file_path ( sess,  obj) ) ; 
1144+ 
1145+     // Adjust the output kind to target capabilities. 
1146+     let  pic_exe_supported = sess. target . target . options . position_independent_executables ; 
1147+     let  static_pic_exe_supported = false ;  // FIXME: Add this option to target specs. 
1148+     let  static_dylib_supported = sess. target . target . options . crt_static_allows_dylibs ; 
1149+     match  kind { 
1150+         LinkOutputKind :: DynamicPicExe  if  !pic_exe_supported => LinkOutputKind :: DynamicNoPicExe , 
1151+         LinkOutputKind :: StaticPicExe  if  !static_pic_exe_supported => LinkOutputKind :: StaticNoPicExe , 
1152+         LinkOutputKind :: StaticDylib  if  !static_dylib_supported => LinkOutputKind :: DynamicDylib , 
1153+         _ => kind, 
11421154    } 
1155+ } 
11431156
1144-     if  crate_type == CrateType :: Executable  && sess. crt_static ( Some ( crate_type) )  { 
1145-         for  obj in  & sess. target . target . options . pre_link_objects_exe_crt  { 
1146-             cmd. add_object ( & get_object_file_path ( sess,  obj) ) ; 
1147-         } 
1157+ /// Whether we link to our own CRT objects instead of relying on gcc to pull them. 
1158+ /// We only provide such support for a very limited number of targets. 
1159+ fn  crt_objects_fallback ( sess :  & Session ,  crate_type :  CrateType )  -> bool  { 
1160+     match  sess. target . target . options . crt_objects_fallback  { 
1161+         // FIXME: Find a better heuristic for "native musl toolchain is available", 
1162+         // based on host and linker path, for example. 
1163+         // (https://github.com/rust-lang/rust/pull/71769#issuecomment-626330237). 
1164+         Some ( CrtObjectsFallback :: Musl )  => sess. crt_static ( Some ( crate_type) ) , 
1165+         // FIXME: Find some heuristic for "native mingw toolchain is available", 
1166+         // likely based on `get_crt_libs_path` (https://github.com/rust-lang/rust/pull/67429). 
1167+         Some ( CrtObjectsFallback :: Mingw )  => sess. target . target . target_vendor  != "uwp" , 
1168+         // FIXME: Figure out cases in which WASM needs to link with a native toolchain. 
1169+         Some ( CrtObjectsFallback :: Wasm )  => true , 
1170+         None  => false , 
11481171    } 
11491172} 
11501173
1151- /// Add end object files defined by the target spec. 
1152- fn  add_post_link_objects ( cmd :  & mut  dyn  Linker ,  sess :  & Session ,  crate_type :  CrateType )  { 
1153-     for  obj in  & sess. target . target . options . post_link_objects  { 
1174+ /// Add pre-link object files defined by the target spec. 
1175+ fn  add_pre_link_objects ( 
1176+     cmd :  & mut  dyn  Linker , 
1177+     sess :  & Session , 
1178+     link_output_kind :  LinkOutputKind , 
1179+     fallback :  bool , 
1180+ )  { 
1181+     let  opts = & sess. target . target . options ; 
1182+     let  objects = if  fallback {  & opts. pre_link_objects_fallback  }  else  {  & opts. pre_link_objects  } ; 
1183+     for  obj in  objects. get ( & link_output_kind) . iter ( ) . copied ( ) . flatten ( )  { 
11541184        cmd. add_object ( & get_object_file_path ( sess,  obj) ) ; 
11551185    } 
1156-     if  sess. crt_static ( Some ( crate_type) )  { 
1157-         for  obj in  & sess. target . target . options . post_link_objects_crt  { 
1158-             cmd. add_object ( & get_object_file_path ( sess,  obj) ) ; 
1159-         } 
1186+ } 
1187+ 
1188+ /// Add post-link object files defined by the target spec. 
1189+ fn  add_post_link_objects ( 
1190+     cmd :  & mut  dyn  Linker , 
1191+     sess :  & Session , 
1192+     link_output_kind :  LinkOutputKind , 
1193+     fallback :  bool , 
1194+ )  { 
1195+     let  opts = & sess. target . target . options ; 
1196+     let  objects = if  fallback {  & opts. post_link_objects_fallback  }  else  {  & opts. post_link_objects  } ; 
1197+     for  obj in  objects. get ( & link_output_kind) . iter ( ) . copied ( ) . flatten ( )  { 
1198+         cmd. add_object ( & get_object_file_path ( sess,  obj) ) ; 
11601199    } 
11611200} 
11621201
@@ -1342,38 +1381,6 @@ fn add_library_search_dirs(cmd: &mut dyn Linker, sess: &Session) {
13421381    cmd. include_path ( & fix_windows_verbatim_for_gcc ( & lib_path) ) ; 
13431382} 
13441383
1345- /// Add options requesting executables to be position-independent or not position-independent. 
1346- fn  add_position_independent_executable_args ( 
1347-     cmd :  & mut  dyn  Linker , 
1348-     sess :  & Session , 
1349-     flavor :  LinkerFlavor , 
1350-     crate_type :  CrateType , 
1351-     codegen_results :  & CodegenResults , 
1352- )  { 
1353-     if  crate_type != CrateType :: Executable  { 
1354-         return ; 
1355-     } 
1356- 
1357-     if  sess. target . target . options . position_independent_executables  { 
1358-         let  attr_link_args = & * codegen_results. crate_info . link_args ; 
1359-         let  mut  user_defined_link_args = sess. opts . cg . link_args . iter ( ) . chain ( attr_link_args) ; 
1360-         if  sess. relocation_model ( )  == RelocModel :: Pic 
1361-             && !sess. crt_static ( Some ( crate_type) ) 
1362-             && !user_defined_link_args. any ( |x| x == "-static" ) 
1363-         { 
1364-             cmd. position_independent_executable ( ) ; 
1365-             return ; 
1366-         } 
1367-     } 
1368- 
1369-     // Recent versions of gcc can be configured to generate position 
1370-     // independent executables by default. We have to pass -no-pie to 
1371-     // explicitly turn that off. Not applicable to ld. 
1372-     if  sess. target . target . options . linker_is_gnu  && flavor != LinkerFlavor :: Ld  { 
1373-         cmd. no_position_independent_executable ( ) ; 
1374-     } 
1375- } 
1376- 
13771384/// Add options making relocation sections in the produced ELF files read-only 
13781385/// and suppressing lazy binding. 
13791386fn  add_relro_args ( cmd :  & mut  dyn  Linker ,  sess :  & Session )  { 
@@ -1439,6 +1446,8 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
14391446    // to the linker args construction. 
14401447    assert ! ( base_cmd. get_args( ) . is_empty( )  || sess. target. target. target_vendor == "uwp" ) ; 
14411448    let  cmd = & mut  * codegen_results. linker_info . to_linker ( base_cmd,  & sess,  flavor,  target_cpu) ; 
1449+     let  link_output_kind = link_output_kind ( sess,  crate_type) ; 
1450+     let  crt_objects_fallback = crt_objects_fallback ( sess,  crate_type) ; 
14421451
14431452    // NO-OPT-OUT, OBJECT-FILES-MAYBE, CUSTOMIZATION-POINT 
14441453    add_pre_link_args ( cmd,  sess,  flavor,  crate_type) ; 
@@ -1455,8 +1464,13 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
14551464        cmd. arg ( format ! ( "--dynamic-linker={}ld.so.1" ,  prefix) ) ; 
14561465    } 
14571466
1467+     // NO-OPT-OUT, OBJECT-FILES-NO 
1468+     if  crt_objects_fallback { 
1469+         cmd. no_crt_objects ( ) ; 
1470+     } 
1471+ 
14581472    // NO-OPT-OUT, OBJECT-FILES-YES 
1459-     add_pre_link_objects ( cmd,  sess,  crate_type ) ; 
1473+     add_pre_link_objects ( cmd,  sess,  link_output_kind ,  crt_objects_fallback ) ; 
14601474
14611475    // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER 
14621476    if  sess. target . target . options . is_like_emscripten  { 
@@ -1515,7 +1529,16 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
15151529    } 
15161530
15171531    // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER 
1518-     add_position_independent_executable_args ( cmd,  sess,  flavor,  crate_type,  codegen_results) ; 
1532+     // FIXME: Support `StaticPicExe` correctly. 
1533+     match  link_output_kind { 
1534+         LinkOutputKind :: DynamicPicExe  | LinkOutputKind :: StaticPicExe  => { 
1535+             cmd. position_independent_executable ( ) 
1536+         } 
1537+         LinkOutputKind :: DynamicNoPicExe  | LinkOutputKind :: StaticNoPicExe  => { 
1538+             cmd. no_position_independent_executable ( ) 
1539+         } 
1540+         _ => { } 
1541+     } 
15191542
15201543    // OBJECT-FILES-NO, AUDIT-ORDER 
15211544    add_relro_args ( cmd,  sess) ; 
@@ -1545,12 +1568,14 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
15451568    ) ; 
15461569
15471570    // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER 
1548-     // Tell the linker what we're doing. 
1549-     if  crate_type != CrateType :: Executable  { 
1550-         cmd. build_dylib ( out_filename) ; 
1551-     } 
1552-     if  crate_type == CrateType :: Executable  && sess. crt_static ( Some ( crate_type) )  { 
1553-         cmd. build_static_executable ( ) ; 
1571+     // FIXME: Merge with the previous `link_output_kind` match, 
1572+     // and support `StaticPicExe` and `StaticDylib` correctly. 
1573+     match  link_output_kind { 
1574+         LinkOutputKind :: StaticNoPicExe  | LinkOutputKind :: StaticPicExe  => { 
1575+             cmd. build_static_executable ( ) 
1576+         } 
1577+         LinkOutputKind :: DynamicDylib  | LinkOutputKind :: StaticDylib  => cmd. build_dylib ( out_filename) , 
1578+         _ => { } 
15541579    } 
15551580
15561581    // OBJECT-FILES-NO, AUDIT-ORDER 
@@ -1576,7 +1601,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
15761601    add_late_link_args ( cmd,  sess,  flavor,  crate_type,  codegen_results) ; 
15771602
15781603    // NO-OPT-OUT, OBJECT-FILES-YES 
1579-     add_post_link_objects ( cmd,  sess,  crate_type ) ; 
1604+     add_post_link_objects ( cmd,  sess,  link_output_kind ,  crt_objects_fallback ) ; 
15801605
15811606    // NO-OPT-OUT, OBJECT-FILES-MAYBE, CUSTOMIZATION-POINT 
15821607    add_post_link_args ( cmd,  sess,  flavor) ; 
0 commit comments