Rollup merge of #72738 - mati865:self-contained-option, r=petrochenkov

Self contained linking option

With objects moved to self-contained directory by https://github.com/rust-lang/rust/pull/72999 we can now add option to control whether to use self-contained on native linkage mode.
This commit is contained in:
Manish Goregaokar 2020-06-25 18:00:03 -07:00 committed by GitHub
commit 9275ff7b21
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 60 additions and 29 deletions

View file

@ -140,7 +140,12 @@ pub fn link_binary<'a, B: ArchiveBuilder<'a>>(
// The third parameter is for env vars, used on windows to set up the
// path for MSVC to find its DLLs, and gcc to find its bundled
// toolchain
fn get_linker(sess: &Session, linker: &Path, flavor: LinkerFlavor) -> Command {
fn get_linker(
sess: &Session,
linker: &Path,
flavor: LinkerFlavor,
self_contained: bool,
) -> Command {
let msvc_tool = windows_registry::find_tool(&sess.opts.target_triple.triple(), "link.exe");
// If our linker looks like a batch script on Windows then to execute this
@ -199,7 +204,7 @@ fn get_linker(sess: &Session, linker: &Path, flavor: LinkerFlavor) -> Command {
// The compiler's sysroot often has some bundled tools, so add it to the
// PATH for the child.
let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths();
let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths(self_contained);
let mut msvc_changed_path = false;
if sess.target.target.options.is_like_msvc {
if let Some(ref tool) = msvc_tool {
@ -551,19 +556,25 @@ fn link_natively<'a, B: ArchiveBuilder<'a>>(
"Linker does not support -static-pie command line option. Retrying with -static instead."
);
// Mirror `add_(pre,post)_link_objects` to replace CRT objects.
let fallback = crt_objects_fallback(sess, crate_type);
let self_contained = crt_objects_fallback(sess, crate_type);
let opts = &sess.target.target.options;
let pre_objects =
if fallback { &opts.pre_link_objects_fallback } else { &opts.pre_link_objects };
let post_objects =
if fallback { &opts.post_link_objects_fallback } else { &opts.post_link_objects };
let pre_objects = if self_contained {
&opts.pre_link_objects_fallback
} else {
&opts.pre_link_objects
};
let post_objects = if self_contained {
&opts.post_link_objects_fallback
} else {
&opts.post_link_objects
};
let get_objects = |objects: &CrtObjects, kind| {
objects
.get(&kind)
.iter()
.copied()
.flatten()
.map(|obj| get_object_file_path(sess, obj).into_os_string())
.map(|obj| get_object_file_path(sess, obj, self_contained).into_os_string())
.collect::<Vec<_>>()
};
let pre_objects_static_pie = get_objects(pre_objects, LinkOutputKind::StaticPicExe);
@ -1066,9 +1077,11 @@ fn get_crt_libs_path(sess: &Session) -> Option<PathBuf> {
}
}
fn get_object_file_path(sess: &Session, name: &str) -> PathBuf {
fn get_object_file_path(sess: &Session, name: &str, self_contained: bool) -> PathBuf {
// prefer system {,dll}crt2.o libs, see get_crt_libs_path comment for more details
if sess.target.target.llvm_target.contains("windows-gnu") {
if sess.opts.debugging_opts.link_self_contained.is_none()
&& sess.target.target.llvm_target.contains("windows-gnu")
{
if let Some(compiler_libs_path) = get_crt_libs_path(sess) {
let file_path = compiler_libs_path.join(name);
if file_path.exists() {
@ -1081,9 +1094,12 @@ fn get_object_file_path(sess: &Session, name: &str) -> PathBuf {
if file_path.exists() {
return file_path;
}
let file_path = fs.get_selfcontained_lib_path().join(name);
if file_path.exists() {
return file_path;
// Special directory with objects used only in self-contained linkage mode
if self_contained {
let file_path = fs.get_self_contained_lib_path().join(name);
if file_path.exists() {
return file_path;
}
}
for search_path in fs.search_paths() {
let file_path = search_path.dir.join(name);
@ -1268,6 +1284,10 @@ fn link_output_kind(sess: &Session, crate_type: CrateType) -> LinkOutputKind {
/// Whether we link to our own CRT objects instead of relying on gcc to pull them.
/// We only provide such support for a very limited number of targets.
fn crt_objects_fallback(sess: &Session, crate_type: CrateType) -> bool {
if let Some(self_contained) = sess.opts.debugging_opts.link_self_contained {
return self_contained;
}
match sess.target.target.options.crt_objects_fallback {
// FIXME: Find a better heuristic for "native musl toolchain is available",
// based on host and linker path, for example.
@ -1287,12 +1307,13 @@ fn add_pre_link_objects(
cmd: &mut dyn Linker,
sess: &Session,
link_output_kind: LinkOutputKind,
fallback: bool,
self_contained: bool,
) {
let opts = &sess.target.target.options;
let objects = if fallback { &opts.pre_link_objects_fallback } else { &opts.pre_link_objects };
let objects =
if self_contained { &opts.pre_link_objects_fallback } else { &opts.pre_link_objects };
for obj in objects.get(&link_output_kind).iter().copied().flatten() {
cmd.add_object(&get_object_file_path(sess, obj));
cmd.add_object(&get_object_file_path(sess, obj, self_contained));
}
}
@ -1301,12 +1322,13 @@ fn add_post_link_objects(
cmd: &mut dyn Linker,
sess: &Session,
link_output_kind: LinkOutputKind,
fallback: bool,
self_contained: bool,
) {
let opts = &sess.target.target.options;
let objects = if fallback { &opts.post_link_objects_fallback } else { &opts.post_link_objects };
let objects =
if self_contained { &opts.post_link_objects_fallback } else { &opts.post_link_objects };
for obj in objects.get(&link_output_kind).iter().copied().flatten() {
cmd.add_object(&get_object_file_path(sess, obj));
cmd.add_object(&get_object_file_path(sess, obj, self_contained));
}
}
@ -1468,9 +1490,12 @@ fn link_local_crate_native_libs_and_dependent_crate_libs<'a, B: ArchiveBuilder<'
}
/// Add sysroot and other globally set directories to the directory search list.
fn add_library_search_dirs(cmd: &mut dyn Linker, sess: &Session) {
fn add_library_search_dirs(cmd: &mut dyn Linker, sess: &Session, self_contained: bool) {
// Prefer system mingw-w64 libs, see get_crt_libs_path comment for more details.
if cfg!(windows) && sess.target.target.llvm_target.contains("windows-gnu") {
if sess.opts.debugging_opts.link_self_contained.is_none()
&& cfg!(windows)
&& sess.target.target.llvm_target.contains("windows-gnu")
{
if let Some(compiler_libs_path) = get_crt_libs_path(sess) {
cmd.include_path(&compiler_libs_path);
}
@ -1481,8 +1506,11 @@ fn add_library_search_dirs(cmd: &mut dyn Linker, sess: &Session) {
let lib_path = sess.target_filesearch(PathKind::All).get_lib_path();
cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path));
let lib_path = sess.target_filesearch(PathKind::All).get_selfcontained_lib_path();
cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path));
// Special directory with libraries used only in self-contained linkage mode
if self_contained {
let lib_path = sess.target_filesearch(PathKind::All).get_self_contained_lib_path();
cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path));
}
}
/// Add options making relocation sections in the produced ELF files read-only
@ -1545,13 +1573,13 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
codegen_results: &CodegenResults,
target_cpu: &str,
) -> Command {
let base_cmd = get_linker(sess, path, flavor);
let crt_objects_fallback = crt_objects_fallback(sess, crate_type);
let base_cmd = get_linker(sess, path, flavor, crt_objects_fallback);
// FIXME: Move `/LIBPATH` addition for uwp targets from the linker construction
// to the linker args construction.
assert!(base_cmd.get_args().is_empty() || sess.target.target.target_vendor == "uwp");
let cmd = &mut *codegen_results.linker_info.to_linker(base_cmd, &sess, flavor, target_cpu);
let link_output_kind = link_output_kind(sess, crate_type);
let crt_objects_fallback = crt_objects_fallback(sess, crate_type);
// NO-OPT-OUT, OBJECT-FILES-MAYBE, CUSTOMIZATION-POINT
add_pre_link_args(cmd, sess, flavor);
@ -1597,7 +1625,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
// NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
// FIXME: Order-dependent, at least relatively to other args adding searh directories.
add_library_search_dirs(cmd, sess);
add_library_search_dirs(cmd, sess, crt_objects_fallback);
// OBJECT-FILES-YES
add_local_crate_regular_objects(cmd, codegen_results);

View file

@ -41,7 +41,7 @@ impl<'a> FileSearch<'a> {
make_target_lib_path(self.sysroot, self.triple)
}
pub fn get_selfcontained_lib_path(&self) -> PathBuf {
pub fn get_self_contained_lib_path(&self) -> PathBuf {
self.get_lib_path().join("self-contained")
}
@ -92,13 +92,13 @@ impl<'a> FileSearch<'a> {
}
// Returns a list of directories where target-specific tool binaries are located.
pub fn get_tools_search_paths(&self) -> Vec<PathBuf> {
pub fn get_tools_search_paths(&self, self_contained: bool) -> Vec<PathBuf> {
let mut p = PathBuf::from(self.sysroot);
p.push(find_libdir(self.sysroot).as_ref());
p.push(RUST_LIB_DIR);
p.push(&self.triple);
p.push("bin");
vec![p.clone(), p.join("self-contained")]
if self_contained { vec![p.clone(), p.join("self-contained")] } else { vec![p.clone()] }
}
}

View file

@ -889,6 +889,9 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"keep hygiene data after analysis (default: no)"),
link_native_libraries: bool = (true, parse_bool, [UNTRACKED],
"link native libraries in the linker invocation (default: yes)"),
link_self_contained: Option<bool> = (None, parse_opt_bool, [TRACKED],
"control whether to link Rust provided C objects/libraries or rely
on C toolchain installed in the system"),
link_only: bool = (false, parse_bool, [TRACKED],
"link the `.rlink` file generated by `-Z no-link` (default: no)"),
llvm_time_trace: bool = (false, parse_bool, [UNTRACKED],