6 use std::path::{Path, PathBuf};
9 use tempfile::Builder as TempFileBuilder;
11 use rustc::session::config::{self, CrateType, DebugInfo, RUST_CGU_EXT};
12 use rustc::session::search_paths::PathKind;
13 use rustc::session::Session;
14 use rustc_codegen_ssa::back::command::Command;
15 use rustc_codegen_ssa::back::link::*;
16 use rustc_codegen_ssa::back::linker::*;
17 use rustc_fs_util::fix_windows_verbatim_for_gcc;
18 use rustc_target::spec::{LinkerFlavor, PanicStrategy, RelroLevel};
20 use crate::prelude::*;
22 use crate::link_copied::*;
24 pub(crate) fn link_rlib(sess: &Session, res: &CodegenResults, output_name: PathBuf) {
25 let file = File::create(&output_name).unwrap();
26 let mut builder = ar::Builder::new(file);
28 // Add main object file
29 for module in &res.modules {
30 if let Some(ref object_path) = module.object {
31 let object = File::open(object_path).expect("Someone deleted our object file");
32 let object_len = object.metadata().unwrap().len();
36 (module.name.to_string() + RUST_CGU_EXT).into_bytes(),
45 // Non object files need to be added after object files, because ranlib will
46 // try to read the native architecture from the first file, even if it isn't
51 crate::metadata::METADATA_FILENAME.as_bytes().to_vec(),
52 res.metadata.raw_data.len() as u64,
54 ::std::io::Cursor::new(res.metadata.raw_data.clone()),
59 std::mem::drop(builder);
61 // Run ranlib to be able to link the archive
62 let status = std::process::Command::new("ranlib")
65 .expect("Couldn't run ranlib");
66 if !status.success() {
67 sess.fatal(&format!("Ranlib exited with code {:?}", status.code()));
71 pub(crate) fn link_natively(
73 crate_type: CrateType,
74 codegen_results: &CodegenResults,
77 let tmpdir = match TempFileBuilder::new().prefix("rustc").tempdir() {
79 Err(err) => sess.fatal(&format!("couldn't create a temp dir: {}", err)),
82 let (linker, flavor) = linker_and_flavor(sess);
84 // The invocations of cc share some flags across platforms
85 let (pname, mut cmd) = get_linker(sess, &linker, flavor);
87 let root = sess.target_filesearch(PathKind::Native).get_lib_path();
88 if let Some(args) = sess.target.target.options.pre_link_args.get(&flavor) {
91 if let Some(args) = sess.target.target.options.pre_link_args_crt.get(&flavor) {
92 if sess.crt_static() {
96 if let Some(ref args) = sess.opts.debugging_opts.pre_link_args {
99 cmd.args(&sess.opts.debugging_opts.pre_link_arg);
101 let pre_link_objects = if crate_type == config::CrateType::Executable {
102 &sess.target.target.options.pre_link_objects_exe
104 &sess.target.target.options.pre_link_objects_dll
106 for obj in pre_link_objects {
107 cmd.arg(root.join(obj));
110 if crate_type == config::CrateType::Executable && sess.crt_static() {
111 for obj in &sess.target.target.options.pre_link_objects_exe_crt {
112 cmd.arg(root.join(obj));
116 if sess.target.target.options.is_like_emscripten {
118 cmd.arg(if sess.panic_strategy() == PanicStrategy::Abort {
119 "DISABLE_EXCEPTION_CATCHING=1"
121 "DISABLE_EXCEPTION_CATCHING=0"
126 let target_cpu = ::target_lexicon::HOST.to_string();
127 let mut linker = codegen_results.linker_info.to_linker(cmd, &sess, flavor, &target_cpu);
128 link_args(&mut *linker, flavor, sess, crate_type, tmpdir.path(),
129 out_filename, codegen_results);
130 cmd = linker.finalize();
132 if let Some(args) = sess.target.target.options.late_link_args.get(&flavor) {
135 for obj in &sess.target.target.options.post_link_objects {
136 cmd.arg(root.join(obj));
138 if sess.crt_static() {
139 for obj in &sess.target.target.options.post_link_objects_crt {
140 cmd.arg(root.join(obj));
143 if let Some(args) = sess.target.target.options.post_link_args.get(&flavor) {
146 for &(ref k, ref v) in &sess.target.target.options.link_env {
150 if sess.opts.debugging_opts.print_link_args {
151 println!("{:?}", &cmd);
154 // May have not found libraries in the right formats.
155 sess.abort_if_errors();
157 // Invoke the system linker
159 // Note that there's a terribly awful hack that really shouldn't be present
160 // in any compiler. Here an environment variable is supported to
161 // automatically retry the linker invocation if the linker looks like it
164 // Gee that seems odd, normally segfaults are things we want to know about!
165 // Unfortunately though in rust-lang/rust#38878 we're experiencing the
166 // linker segfaulting on Travis quite a bit which is causing quite a bit of
167 // pain to land PRs when they spuriously fail due to a segfault.
169 // The issue #38878 has some more debugging information on it as well, but
170 // this unfortunately looks like it's just a race condition in macOS's linker
171 // with some thread pool working in the background. It seems that no one
172 // currently knows a fix for this so in the meantime we're left with this...
173 let retry_on_segfault = env::var("RUSTC_RETRY_LINKER_ON_SEGFAULT").is_ok();
178 prog = exec_linker(sess, &mut cmd, out_filename, tmpdir.path());
179 let output = match prog {
180 Ok(ref output) => output,
183 if output.status.success() {
186 let mut out = output.stderr.clone();
187 out.extend(&output.stdout);
188 let out = String::from_utf8_lossy(&out);
190 // Check to see if the link failed with "unrecognized command line option:
191 // '-no-pie'" for gcc or "unknown argument: '-no-pie'" for clang. If so,
192 // reperform the link step without the -no-pie option. This is safe because
193 // if the linker doesn't support -no-pie then it should not default to
194 // linking executables as pie. Different versions of gcc seem to use
195 // different quotes in the error message so don't check for them.
196 if sess.target.target.options.linker_is_gnu &&
197 flavor != LinkerFlavor::Ld &&
198 (out.contains("unrecognized command line option") ||
199 out.contains("unknown argument")) &&
200 out.contains("-no-pie") &&
201 cmd.get_args().iter().any(|e| e.to_string_lossy() == "-no-pie") {
202 for arg in cmd.take_args() {
203 if arg.to_string_lossy() != "-no-pie" {
209 if !retry_on_segfault || i > 3 {
212 let msg_segv = "clang: error: unable to execute command: Segmentation fault: 11";
213 let msg_bus = "clang: error: unable to execute command: Bus error: 10";
214 if !(out.contains(msg_segv) || out.contains(msg_bus)) {
221 fn escape_string(s: &[u8]) -> String {
222 str::from_utf8(s).map(|s| s.to_owned())
223 .unwrap_or_else(|_| {
224 let mut x = "Non-UTF-8 output: ".to_string();
226 .flat_map(|&b| ascii::escape_default(b))
231 if !prog.status.success() {
232 let mut output = prog.stderr.clone();
233 output.extend_from_slice(&prog.stdout);
234 sess.struct_err(&format!("linking with `{}` failed: {}",
237 .note(&format!("{:?}", &cmd))
238 .note(&escape_string(&output))
240 sess.abort_if_errors();
244 let linker_not_found = e.kind() == io::ErrorKind::NotFound;
246 let mut linker_error = {
247 if linker_not_found {
248 sess.struct_err(&format!("linker `{}` not found", pname.display()))
250 sess.struct_err(&format!("could not exec the linker `{}`", pname.display()))
254 linker_error.note(&e.to_string());
256 if !linker_not_found {
257 linker_error.note(&format!("{:?}", &cmd));
262 if sess.target.target.options.is_like_msvc && linker_not_found {
263 sess.note_without_error("the msvc targets depend on the msvc linker \
264 but `link.exe` was not found");
265 sess.note_without_error("please ensure that VS 2013, VS 2015 or VS 2017 \
266 was installed with the Visual C++ option");
268 sess.abort_if_errors();
273 // On macOS, debuggers need this utility to get run to do some munging of
274 // the symbols. Note, though, that if the object files are being preserved
275 // for their debug information there's no need for us to run dsymutil.
276 if sess.target.target.options.is_like_osx &&
277 sess.opts.debuginfo != DebugInfo::None
279 if let Err(e) = Command::new("dsymutil").arg(out_filename).output() {
280 sess.fatal(&format!("failed to run dsymutil: {}", e))
285 fn link_args(cmd: &mut dyn Linker,
286 flavor: LinkerFlavor,
288 crate_type: config::CrateType,
291 codegen_results: &CodegenResults) {
293 // Linker plugins should be specified early in the list of arguments
294 cmd.cross_lang_lto();
296 // The default library location, we need this to find the runtime.
297 // The location of crates will be determined as needed.
298 let lib_path = sess.target_filesearch(PathKind::All).get_lib_path();
301 let t = &sess.target.target;
303 cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path));
304 for obj in codegen_results.modules.iter().filter_map(|m| m.object.as_ref()) {
307 cmd.output_filename(out_filename);
309 // If we're building a dynamic library then some platforms need to make sure
310 // that all symbols are exported correctly from the dynamic library.
311 if crate_type != config::CrateType::Executable ||
312 sess.target.target.options.is_like_emscripten {
313 cmd.export_symbols(tmpdir, crate_type);
316 let obj = codegen_results.allocator_module
318 .and_then(|m| m.object.as_ref());
319 if let Some(obj) = obj {
323 // Try to strip as much out of the generated object by removing unused
324 // sections if possible. See more comments in linker.rs
325 if !sess.opts.cg.link_dead_code {
326 let keep_metadata = crate_type == config::CrateType::Dylib;
327 cmd.gc_sections(keep_metadata);
330 let used_link_args = &codegen_results.crate_info.link_args;
332 if crate_type == config::CrateType::Executable {
333 let mut position_independent_executable = false;
335 if t.options.position_independent_executables {
336 let empty_vec = Vec::new();
337 let args = sess.opts.cg.link_args.as_ref().unwrap_or(&empty_vec);
338 let more_args = &sess.opts.cg.link_arg;
339 let mut args = args.iter().chain(more_args.iter()).chain(used_link_args.iter());
341 if !sess.crt_static() && !args.any(|x| *x == "-static") {
342 position_independent_executable = true;
346 if position_independent_executable {
347 cmd.position_independent_executable();
349 // recent versions of gcc can be configured to generate position
350 // independent executables by default. We have to pass -no-pie to
351 // explicitly turn that off. Not applicable to ld.
352 if sess.target.target.options.linker_is_gnu
353 && flavor != LinkerFlavor::Ld {
354 cmd.no_position_independent_executable();
359 let relro_level = match sess.opts.debugging_opts.relro_level {
360 Some(level) => level,
361 None => t.options.relro_level,
364 RelroLevel::Full => {
367 RelroLevel::Partial => {
373 RelroLevel::None => {
377 // Pass optimization flags down to the linker.
380 // Pass debuginfo flags down to the linker.
383 // We want to, by default, prevent the compiler from accidentally leaking in
384 // any system libraries, so we may explicitly ask linkers to not link to any
385 // libraries by default. Note that this does not happen for windows because
386 // windows pulls in some large number of libraries and I couldn't quite
387 // figure out which subset we wanted.
389 // This is all naturally configurable via the standard methods as well.
390 if !sess.opts.cg.default_linker_libraries.unwrap_or(false) &&
391 t.options.no_default_libraries
393 cmd.no_default_libraries();
396 // Take careful note of the ordering of the arguments we pass to the linker
397 // here. Linkers will assume that things on the left depend on things to the
398 // right. Things on the right cannot depend on things on the left. This is
399 // all formally implemented in terms of resolving symbols (libs on the right
400 // resolve unknown symbols of libs on the left, but not vice versa).
402 // For this reason, we have organized the arguments we pass to the linker as
405 // 1. The local object that LLVM just generated
406 // 2. Local native libraries
407 // 3. Upstream rust libraries
408 // 4. Upstream native libraries
410 // The rationale behind this ordering is that those items lower down in the
411 // list can't depend on items higher up in the list. For example nothing can
412 // depend on what we just generated (e.g. that'd be a circular dependency).
413 // Upstream rust libraries are not allowed to depend on our local native
414 // libraries as that would violate the structure of the DAG, in that
415 // scenario they are required to link to them as well in a shared fashion.
417 // Note that upstream rust libraries may contain native dependencies as
418 // well, but they also can't depend on what we just started to add to the
419 // link line. And finally upstream native libraries can't depend on anything
420 // in this DAG so far because they're only dylibs and dylibs can only depend
421 // on other dylibs (e.g. other native deps).
422 add_local_native_libraries(cmd, sess, codegen_results);
423 add_upstream_rust_crates(cmd, sess, codegen_results, crate_type, tmpdir);
424 add_upstream_native_libraries(cmd, sess, codegen_results, crate_type);
426 // Tell the linker what we're doing.
427 if crate_type != config::CrateType::Executable {
428 cmd.build_dylib(out_filename);
430 if crate_type == config::CrateType::Executable && sess.crt_static() {
431 cmd.build_static_executable();
434 if sess.opts.debugging_opts.pgo_gen.is_some() {
438 // Finally add all the linker arguments provided on the command line along
439 // with any #[link_args] attributes found inside the crate
440 if let Some(ref args) = sess.opts.cg.link_args {
443 cmd.args(&sess.opts.cg.link_arg);
444 cmd.args(&used_link_args);