]> git.proxmox.com Git - rustc.git/blame - src/librustc_codegen_ssa/back/linker.rs
New upstream version 1.41.1+dfsg1
[rustc.git] / src / librustc_codegen_ssa / back / linker.rs
CommitLineData
a1dfa0c6
XL
1use super::symbol_export;
2use super::command::Command;
3use super::archive;
4
b7449926 5use rustc_data_structures::fx::FxHashMap;
cc61c64b 6use std::ffi::{OsStr, OsString};
e9174d1e 7use std::fs::{self, File};
e9174d1e 8use std::io::prelude::*;
9e0c209e 9use std::io::{self, BufWriter};
62682a34 10use std::path::{Path, PathBuf};
3157f602 11
476ff2be 12use rustc::hir::def_id::{LOCAL_CRATE, CrateNum};
ea8adc8c 13use rustc::middle::dependency_format::Linkage;
7cac9316 14use rustc::session::Session;
b7449926 15use rustc::session::config::{self, CrateType, OptLevel, DebugInfo,
9fa01778 16 LinkerPluginLto, Lto};
ea8adc8c 17use rustc::ty::TyCtxt;
83c7162d 18use rustc_target::spec::{LinkerFlavor, LldFlavor};
416331ca 19use rustc_serialize::{json, Encoder};
e1599b0c 20use syntax::symbol::Symbol;
3157f602
XL
21
22/// For all the linkers we support, and information they might
23/// need out of the shared crate context before we get rid of it.
24pub struct LinkerInfo {
b7449926 25 exports: FxHashMap<CrateType, Vec<String>>,
3157f602
XL
26}
27
ea8adc8c 28impl LinkerInfo {
dc9dc135 29 pub fn new(tcx: TyCtxt<'_>) -> LinkerInfo {
3157f602 30 LinkerInfo {
ea8adc8c
XL
31 exports: tcx.sess.crate_types.borrow().iter().map(|&c| {
32 (c, exported_symbols(tcx, c))
9e0c209e 33 }).collect(),
3157f602
XL
34 }
35 }
36
a1dfa0c6
XL
37 pub fn to_linker<'a>(
38 &'a self,
39 cmd: Command,
40 sess: &'a Session,
41 flavor: LinkerFlavor,
42 target_cpu: &'a str,
43 ) -> Box<dyn Linker+'a> {
b7449926 44 match flavor {
0531ce1d 45 LinkerFlavor::Lld(LldFlavor::Link) |
cc61c64b
XL
46 LinkerFlavor::Msvc => {
47 Box::new(MsvcLinker {
3b2f2976
XL
48 cmd,
49 sess,
cc61c64b 50 info: self
8faf50e0 51 }) as Box<dyn Linker>
cc61c64b
XL
52 }
53 LinkerFlavor::Em => {
54 Box::new(EmLinker {
3b2f2976
XL
55 cmd,
56 sess,
cc61c64b 57 info: self
8faf50e0 58 }) as Box<dyn Linker>
cc61c64b
XL
59 }
60 LinkerFlavor::Gcc => {
61 Box::new(GccLinker {
3b2f2976
XL
62 cmd,
63 sess,
cc61c64b
XL
64 info: self,
65 hinted_static: false,
66 is_ld: false,
a1dfa0c6 67 target_cpu,
8faf50e0 68 }) as Box<dyn Linker>
cc61c64b 69 }
0531ce1d
XL
70
71 LinkerFlavor::Lld(LldFlavor::Ld) |
72 LinkerFlavor::Lld(LldFlavor::Ld64) |
cc61c64b
XL
73 LinkerFlavor::Ld => {
74 Box::new(GccLinker {
3b2f2976
XL
75 cmd,
76 sess,
cc61c64b
XL
77 info: self,
78 hinted_static: false,
79 is_ld: true,
a1dfa0c6 80 target_cpu,
8faf50e0 81 }) as Box<dyn Linker>
cc61c64b 82 }
0531ce1d
XL
83
84 LinkerFlavor::Lld(LldFlavor::Wasm) => {
0731742a 85 Box::new(WasmLd::new(cmd, sess, self)) as Box<dyn Linker>
abe05a73 86 }
9fa01778
XL
87
88 LinkerFlavor::PtxLinker => {
89 Box::new(PtxLinker { cmd, sess }) as Box<dyn Linker>
90 }
3157f602
XL
91 }
92 }
93}
62682a34 94
9fa01778 95/// Linker abstraction used by `back::link` to build up the command to invoke a
62682a34
SL
96/// linker.
97///
98/// This trait is the total list of requirements needed by `back::link` and
99/// represents the meaning of each option being passed down. This trait is then
100/// used to dispatch on whether a GNU-like linker (generally `ld.exe`) or an
0731742a 101/// MSVC linker (e.g., `link.exe`) is being used.
62682a34 102pub trait Linker {
e1599b0c
XL
103 fn link_dylib(&mut self, lib: Symbol);
104 fn link_rust_dylib(&mut self, lib: Symbol, path: &Path);
105 fn link_framework(&mut self, framework: Symbol);
106 fn link_staticlib(&mut self, lib: Symbol);
62682a34 107 fn link_rlib(&mut self, lib: &Path);
c1a9b12d 108 fn link_whole_rlib(&mut self, lib: &Path);
e1599b0c 109 fn link_whole_staticlib(&mut self, lib: Symbol, search_path: &[PathBuf]);
62682a34
SL
110 fn include_path(&mut self, path: &Path);
111 fn framework_path(&mut self, path: &Path);
112 fn output_filename(&mut self, path: &Path);
113 fn add_object(&mut self, path: &Path);
a7813a04 114 fn gc_sections(&mut self, keep_metadata: bool);
62682a34 115 fn position_independent_executable(&mut self);
0531ce1d 116 fn no_position_independent_executable(&mut self);
3b2f2976 117 fn full_relro(&mut self);
0531ce1d
XL
118 fn partial_relro(&mut self);
119 fn no_relro(&mut self);
62682a34 120 fn optimize(&mut self);
0531ce1d 121 fn pgo_gen(&mut self);
c1a9b12d 122 fn debuginfo(&mut self);
62682a34
SL
123 fn no_default_libraries(&mut self);
124 fn build_dylib(&mut self, out_filename: &Path);
3b2f2976 125 fn build_static_executable(&mut self);
62682a34 126 fn args(&mut self, args: &[String]);
3157f602 127 fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType);
c30ab7b3 128 fn subsystem(&mut self, subsystem: &str);
0531ce1d
XL
129 fn group_start(&mut self);
130 fn group_end(&mut self);
9fa01778 131 fn linker_plugin_lto(&mut self);
cc61c64b
XL
132 // Should have been finalize(self), but we don't support self-by-value on trait objects (yet?).
133 fn finalize(&mut self) -> Command;
62682a34
SL
134}
135
cc61c64b
XL
136pub struct GccLinker<'a> {
137 cmd: Command,
3157f602 138 sess: &'a Session,
cc61c64b
XL
139 info: &'a LinkerInfo,
140 hinted_static: bool, // Keeps track of the current hinting mode.
141 // Link as ld
142 is_ld: bool,
a1dfa0c6 143 target_cpu: &'a str,
62682a34
SL
144}
145
cc61c64b
XL
146impl<'a> GccLinker<'a> {
147 /// Argument that must be passed *directly* to the linker
148 ///
9fa01778 149 /// These arguments need to be prepended with `-Wl`, when a GCC-style linker is used.
cc61c64b
XL
150 fn linker_arg<S>(&mut self, arg: S) -> &mut Self
151 where S: AsRef<OsStr>
152 {
153 if !self.is_ld {
154 let mut os = OsString::from("-Wl,");
155 os.push(arg.as_ref());
156 self.cmd.arg(os);
157 } else {
158 self.cmd.arg(arg);
159 }
160 self
161 }
162
62682a34 163 fn takes_hints(&self) -> bool {
532ac7d7
XL
164 // Really this function only returns true if the underlying linker
165 // configured for a compiler is binutils `ld.bfd` and `ld.gold`. We
166 // don't really have a foolproof way to detect that, so rule out some
167 // platforms where currently this is guaranteed to *not* be the case:
168 //
169 // * On OSX they have their own linker, not binutils'
170 // * For WebAssembly the only functional linker is LLD, which doesn't
171 // support hint flags
172 !self.sess.target.target.options.is_like_osx &&
173 self.sess.target.target.arch != "wasm32"
62682a34 174 }
cc61c64b
XL
175
176 // Some platforms take hints about whether a library is static or dynamic.
177 // For those that support this, we ensure we pass the option if the library
178 // was flagged "static" (most defaults are dynamic) to ensure that if
179 // libfoo.a and libfoo.so both exist that the right one is chosen.
180 fn hint_static(&mut self) {
181 if !self.takes_hints() { return }
182 if !self.hinted_static {
183 self.linker_arg("-Bstatic");
184 self.hinted_static = true;
185 }
186 }
187
188 fn hint_dynamic(&mut self) {
189 if !self.takes_hints() { return }
190 if self.hinted_static {
191 self.linker_arg("-Bdynamic");
192 self.hinted_static = false;
193 }
194 }
8faf50e0 195
9fa01778 196 fn push_linker_plugin_lto_args(&mut self, plugin_path: Option<&OsStr>) {
8faf50e0
XL
197 if let Some(plugin_path) = plugin_path {
198 let mut arg = OsString::from("-plugin=");
199 arg.push(plugin_path);
200 self.linker_arg(&arg);
201 }
202
203 let opt_level = match self.sess.opts.optimize {
204 config::OptLevel::No => "O0",
205 config::OptLevel::Less => "O1",
206 config::OptLevel::Default => "O2",
207 config::OptLevel::Aggressive => "O3",
208 config::OptLevel::Size => "Os",
209 config::OptLevel::SizeMin => "Oz",
210 };
211
212 self.linker_arg(&format!("-plugin-opt={}", opt_level));
a1dfa0c6
XL
213 let target_cpu = self.target_cpu;
214 self.linker_arg(&format!("-plugin-opt=mcpu={}", target_cpu));
8faf50e0 215 }
62682a34
SL
216}
217
cc61c64b 218impl<'a> Linker for GccLinker<'a> {
e1599b0c
XL
219 fn link_dylib(&mut self, lib: Symbol) {
220 self.hint_dynamic();
221 self.cmd.arg(format!("-l{}", lib));
222 }
223 fn link_staticlib(&mut self, lib: Symbol) {
224 self.hint_static();
225 self.cmd.arg(format!("-l{}", lib));
8faf50e0 226 }
cc61c64b 227 fn link_rlib(&mut self, lib: &Path) { self.hint_static(); self.cmd.arg(lib); }
62682a34
SL
228 fn include_path(&mut self, path: &Path) { self.cmd.arg("-L").arg(path); }
229 fn framework_path(&mut self, path: &Path) { self.cmd.arg("-F").arg(path); }
230 fn output_filename(&mut self, path: &Path) { self.cmd.arg("-o").arg(path); }
231 fn add_object(&mut self, path: &Path) { self.cmd.arg(path); }
232 fn position_independent_executable(&mut self) { self.cmd.arg("-pie"); }
0531ce1d 233 fn no_position_independent_executable(&mut self) { self.cmd.arg("-no-pie"); }
8faf50e0
XL
234 fn full_relro(&mut self) { self.linker_arg("-zrelro"); self.linker_arg("-znow"); }
235 fn partial_relro(&mut self) { self.linker_arg("-zrelro"); }
236 fn no_relro(&mut self) { self.linker_arg("-znorelro"); }
3b2f2976 237 fn build_static_executable(&mut self) { self.cmd.arg("-static"); }
62682a34
SL
238 fn args(&mut self, args: &[String]) { self.cmd.args(args); }
239
e1599b0c 240 fn link_rust_dylib(&mut self, lib: Symbol, _path: &Path) {
cc61c64b 241 self.hint_dynamic();
a1dfa0c6 242 self.cmd.arg(format!("-l{}", lib));
c1a9b12d
SL
243 }
244
e1599b0c 245 fn link_framework(&mut self, framework: Symbol) {
cc61c64b 246 self.hint_dynamic();
e1599b0c 247 self.cmd.arg("-framework").sym_arg(framework);
62682a34
SL
248 }
249
cc61c64b
XL
250 // Here we explicitly ask that the entire archive is included into the
251 // result artifact. For more details see #15460, but the gist is that
252 // the linker will strip away any unused objects in the archive if we
253 // don't otherwise explicitly reference them. This can occur for
254 // libraries which are just providing bindings, libraries with generic
255 // functions, etc.
e1599b0c 256 fn link_whole_staticlib(&mut self, lib: Symbol, search_path: &[PathBuf]) {
cc61c64b 257 self.hint_static();
62682a34
SL
258 let target = &self.sess.target.target;
259 if !target.options.is_like_osx {
a1dfa0c6 260 self.linker_arg("--whole-archive").cmd.arg(format!("-l{}", lib));
cc61c64b 261 self.linker_arg("--no-whole-archive");
62682a34 262 } else {
cc61c64b 263 // -force_load is the macOS equivalent of --whole-archive, but it
62682a34 264 // involves passing the full path to the library to link.
8faf50e0
XL
265 self.linker_arg("-force_load");
266 let lib = archive::find_library(lib, search_path, &self.sess);
267 self.linker_arg(&lib);
c1a9b12d
SL
268 }
269 }
270
271 fn link_whole_rlib(&mut self, lib: &Path) {
cc61c64b 272 self.hint_static();
c1a9b12d 273 if self.sess.target.target.options.is_like_osx {
8faf50e0
XL
274 self.linker_arg("-force_load");
275 self.linker_arg(&lib);
c1a9b12d 276 } else {
cc61c64b
XL
277 self.linker_arg("--whole-archive").cmd.arg(lib);
278 self.linker_arg("--no-whole-archive");
62682a34
SL
279 }
280 }
281
a7813a04 282 fn gc_sections(&mut self, keep_metadata: bool) {
62682a34
SL
283 // The dead_strip option to the linker specifies that functions and data
284 // unreachable by the entry point will be removed. This is quite useful
285 // with Rust's compilation model of compiling libraries at a time into
286 // one object file. For example, this brings hello world from 1.7MB to
287 // 458K.
288 //
289 // Note that this is done for both executables and dynamic libraries. We
290 // won't get much benefit from dylibs because LLVM will have already
291 // stripped away as much as it could. This has not been seen to impact
292 // link times negatively.
293 //
294 // -dead_strip can't be part of the pre_link_args because it's also used
295 // for partial linking when using multiple codegen units (-r). So we
296 // insert it here.
297 if self.sess.target.target.options.is_like_osx {
cc61c64b 298 self.linker_arg("-dead_strip");
7453a54e 299 } else if self.sess.target.target.options.is_like_solaris {
8faf50e0 300 self.linker_arg("-zignore");
62682a34
SL
301
302 // If we're building a dylib, we don't use --gc-sections because LLVM
303 // has already done the best it can do, and we also don't want to
304 // eliminate the metadata. If we're building an executable, however,
305 // --gc-sections drops the size of hello world from 1.8MB to 597K, a 67%
306 // reduction.
a7813a04 307 } else if !keep_metadata {
cc61c64b 308 self.linker_arg("--gc-sections");
62682a34
SL
309 }
310 }
311
312 fn optimize(&mut self) {
313 if !self.sess.target.target.options.linker_is_gnu { return }
314
315 // GNU-style linkers support optimization with -O. GNU ld doesn't
316 // need a numeric argument, but other linkers do.
9cc50fc6
SL
317 if self.sess.opts.optimize == config::OptLevel::Default ||
318 self.sess.opts.optimize == config::OptLevel::Aggressive {
cc61c64b 319 self.linker_arg("-O1");
62682a34
SL
320 }
321 }
322
0531ce1d
XL
323 fn pgo_gen(&mut self) {
324 if !self.sess.target.target.options.linker_is_gnu { return }
325
326 // If we're doing PGO generation stuff and on a GNU-like linker, use the
327 // "-u" flag to properly pull in the profiler runtime bits.
328 //
329 // This is because LLVM otherwise won't add the needed initialization
330 // for us on Linux (though the extra flag should be harmless if it
331 // does).
332 //
333 // See https://reviews.llvm.org/D14033 and https://reviews.llvm.org/D14030.
334 //
335 // Though it may be worth to try to revert those changes upstream, since
336 // the overhead of the initialization should be minor.
337 self.cmd.arg("-u");
338 self.cmd.arg("__llvm_profile_runtime");
339 }
340
c1a9b12d 341 fn debuginfo(&mut self) {
a1dfa0c6
XL
342 if let DebugInfo::None = self.sess.opts.debuginfo {
343 // If we are building without debuginfo enabled and we were called with
344 // `-Zstrip-debuginfo-if-disabled=yes`, tell the linker to strip any debuginfo
345 // found when linking to get rid of symbols from libstd.
346 if let Some(true) = self.sess.opts.debugging_opts.strip_debuginfo_if_disabled {
347 self.linker_arg("-S");
348 }
0531ce1d 349 };
c1a9b12d
SL
350 }
351
62682a34 352 fn no_default_libraries(&mut self) {
cc61c64b
XL
353 if !self.is_ld {
354 self.cmd.arg("-nodefaultlibs");
355 }
62682a34
SL
356 }
357
358 fn build_dylib(&mut self, out_filename: &Path) {
359 // On mac we need to tell the linker to let this library be rpathed
360 if self.sess.target.target.options.is_like_osx {
cc61c64b
XL
361 self.cmd.arg("-dynamiclib");
362 self.linker_arg("-dylib");
62682a34 363
476ff2be
SL
364 // Note that the `osx_rpath_install_name` option here is a hack
365 // purely to support rustbuild right now, we should get a more
366 // principled solution at some point to force the compiler to pass
367 // the right `-Wl,-install_name` with an `@rpath` in it.
a1dfa0c6 368 if self.sess.opts.cg.rpath || self.sess.opts.debugging_opts.osx_rpath_install_name {
8faf50e0
XL
369 self.linker_arg("-install_name");
370 let mut v = OsString::from("@rpath/");
62682a34 371 v.push(out_filename.file_name().unwrap());
cc61c64b 372 self.linker_arg(&v);
62682a34
SL
373 }
374 } else {
375 self.cmd.arg("-shared");
416331ca
XL
376 if self.sess.target.target.options.is_like_windows {
377 // The output filename already contains `dll_suffix` so
378 // the resulting import library will have a name in the
379 // form of libfoo.dll.a
380 let implib_name = out_filename
381 .file_name()
382 .and_then(|file| file.to_str())
383 .map(|file| format!("{}{}{}",
384 self.sess.target.target.options.staticlib_prefix,
385 file,
386 self.sess.target.target.options.staticlib_suffix));
387 if let Some(implib_name) = implib_name {
388 let implib = out_filename
389 .parent()
390 .map(|dir| dir.join(&implib_name));
391 if let Some(implib) = implib {
392 self.linker_arg(&format!("--out-implib,{}", (*implib).to_str().unwrap()));
393 }
394 }
395 }
62682a34
SL
396 }
397 }
398
3157f602 399 fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
48663c56 400 // Symbol visibility in object files typically takes care of this.
60c5eb7d
XL
401 if crate_type == CrateType::Executable &&
402 self.sess.target.target.options.override_export_symbols.is_none() {
48663c56
XL
403 return;
404 }
405
dc9dc135
XL
406 // We manually create a list of exported symbols to ensure we don't expose any more.
407 // The object files have far more public symbols than we actually want to export,
408 // so we hide them all here.
a7813a04 409
dc9dc135 410 if !self.sess.target.target.options.limit_rdylib_exports {
532ac7d7
XL
411 return;
412 }
413
dc9dc135
XL
414 if crate_type == CrateType::ProcMacro {
415 return
416 }
417
9e0c209e 418 let mut arg = OsString::new();
a7813a04 419 let path = tmpdir.join("list");
9e0c209e 420
476ff2be
SL
421 debug!("EXPORTED SYMBOLS:");
422
423 if self.sess.target.target.options.is_like_osx {
424 // Write a plain, newline-separated list of symbols
532ac7d7 425 let res: io::Result<()> = try {
9e0c209e 426 let mut f = BufWriter::new(File::create(&path)?);
9e0c209e 427 for sym in self.info.exports[&crate_type].iter() {
476ff2be
SL
428 debug!(" _{}", sym);
429 writeln!(f, "_{}", sym)?;
9e0c209e 430 }
532ac7d7 431 };
9e0c209e 432 if let Err(e) = res {
476ff2be 433 self.sess.fatal(&format!("failed to write lib.def file: {}", e));
a7813a04 434 }
a7813a04 435 } else {
476ff2be 436 // Write an LD version script
532ac7d7 437 let res: io::Result<()> = try {
9e0c209e 438 let mut f = BufWriter::new(File::create(&path)?);
e1599b0c
XL
439 writeln!(f, "{{")?;
440 if !self.info.exports[&crate_type].is_empty() {
441 writeln!(f, " global:")?;
442 for sym in self.info.exports[&crate_type].iter() {
443 debug!(" {};", sym);
444 writeln!(f, " {};", sym)?;
445 }
9e0c209e 446 }
476ff2be 447 writeln!(f, "\n local:\n *;\n}};")?;
532ac7d7 448 };
9e0c209e 449 if let Err(e) = res {
476ff2be 450 self.sess.fatal(&format!("failed to write version script: {}", e));
9e0c209e 451 }
a7813a04 452 }
9e0c209e 453
476ff2be 454 if self.sess.target.target.options.is_like_osx {
cc61c64b
XL
455 if !self.is_ld {
456 arg.push("-Wl,")
457 }
458 arg.push("-exported_symbols_list,");
476ff2be 459 } else if self.sess.target.target.options.is_like_solaris {
cc61c64b
XL
460 if !self.is_ld {
461 arg.push("-Wl,")
462 }
463 arg.push("-M,");
476ff2be 464 } else {
cc61c64b
XL
465 if !self.is_ld {
466 arg.push("-Wl,")
467 }
468 arg.push("--version-script=");
476ff2be
SL
469 }
470
471 arg.push(&path);
a7813a04 472 self.cmd.arg(arg);
e9174d1e 473 }
c30ab7b3
SL
474
475 fn subsystem(&mut self, subsystem: &str) {
8faf50e0
XL
476 self.linker_arg("--subsystem");
477 self.linker_arg(&subsystem);
cc61c64b
XL
478 }
479
480 fn finalize(&mut self) -> Command {
481 self.hint_dynamic(); // Reset to default before returning the composed command line.
a1dfa0c6
XL
482
483 ::std::mem::replace(&mut self.cmd, Command::new(""))
c30ab7b3 484 }
0531ce1d
XL
485
486 fn group_start(&mut self) {
532ac7d7 487 if self.takes_hints() {
0531ce1d
XL
488 self.linker_arg("--start-group");
489 }
490 }
491
492 fn group_end(&mut self) {
532ac7d7 493 if self.takes_hints() {
0531ce1d
XL
494 self.linker_arg("--end-group");
495 }
496 }
94b46f34 497
9fa01778
XL
498 fn linker_plugin_lto(&mut self) {
499 match self.sess.opts.cg.linker_plugin_lto {
500 LinkerPluginLto::Disabled => {
94b46f34
XL
501 // Nothing to do
502 }
9fa01778
XL
503 LinkerPluginLto::LinkerPluginAuto => {
504 self.push_linker_plugin_lto_args(None);
8faf50e0 505 }
9fa01778
XL
506 LinkerPluginLto::LinkerPlugin(ref path) => {
507 self.push_linker_plugin_lto_args(Some(path.as_os_str()));
94b46f34
XL
508 }
509 }
510 }
62682a34
SL
511}
512
513pub struct MsvcLinker<'a> {
cc61c64b 514 cmd: Command,
3157f602
XL
515 sess: &'a Session,
516 info: &'a LinkerInfo
62682a34
SL
517}
518
519impl<'a> Linker for MsvcLinker<'a> {
520 fn link_rlib(&mut self, lib: &Path) { self.cmd.arg(lib); }
521 fn add_object(&mut self, path: &Path) { self.cmd.arg(path); }
522 fn args(&mut self, args: &[String]) { self.cmd.args(args); }
7453a54e
SL
523
524 fn build_dylib(&mut self, out_filename: &Path) {
525 self.cmd.arg("/DLL");
526 let mut arg: OsString = "/IMPLIB:".into();
527 arg.push(out_filename.with_extension("dll.lib"));
528 self.cmd.arg(arg);
529 }
530
3b2f2976
XL
531 fn build_static_executable(&mut self) {
532 // noop
533 }
534
a7813a04 535 fn gc_sections(&mut self, _keep_metadata: bool) {
476ff2be
SL
536 // MSVC's ICF (Identical COMDAT Folding) link optimization is
537 // slow for Rust and thus we disable it by default when not in
538 // optimization build.
539 if self.sess.opts.optimize != config::OptLevel::No {
540 self.cmd.arg("/OPT:REF,ICF");
541 } else {
542 // It is necessary to specify NOICF here, because /OPT:REF
543 // implies ICF by default.
544 self.cmd.arg("/OPT:REF,NOICF");
545 }
a7813a04 546 }
62682a34 547
e1599b0c 548 fn link_dylib(&mut self, lib: Symbol) {
62682a34
SL
549 self.cmd.arg(&format!("{}.lib", lib));
550 }
c1a9b12d 551
e1599b0c 552 fn link_rust_dylib(&mut self, lib: Symbol, path: &Path) {
c1a9b12d
SL
553 // When producing a dll, the MSVC linker may not actually emit a
554 // `foo.lib` file if the dll doesn't actually export any symbols, so we
555 // check to see if the file is there and just omit linking to it if it's
556 // not present.
7453a54e 557 let name = format!("{}.dll.lib", lib);
c1a9b12d
SL
558 if fs::metadata(&path.join(&name)).is_ok() {
559 self.cmd.arg(name);
560 }
561 }
562
e1599b0c 563 fn link_staticlib(&mut self, lib: Symbol) {
62682a34
SL
564 self.cmd.arg(&format!("{}.lib", lib));
565 }
566
567 fn position_independent_executable(&mut self) {
568 // noop
569 }
570
0531ce1d 571 fn no_position_independent_executable(&mut self) {
3b2f2976
XL
572 // noop
573 }
574
575 fn full_relro(&mut self) {
576 // noop
577 }
578
0531ce1d
XL
579 fn partial_relro(&mut self) {
580 // noop
581 }
582
583 fn no_relro(&mut self) {
584 // noop
585 }
586
62682a34
SL
587 fn no_default_libraries(&mut self) {
588 // Currently we don't pass the /NODEFAULTLIB flag to the linker on MSVC
589 // as there's been trouble in the past of linking the C++ standard
590 // library required by LLVM. This likely needs to happen one day, but
591 // in general Windows is also a more controlled environment than
592 // Unix, so it's not necessarily as critical that this be implemented.
593 //
594 // Note that there are also some licensing worries about statically
595 // linking some libraries which require a specific agreement, so it may
596 // not ever be possible for us to pass this flag.
597 }
598
599 fn include_path(&mut self, path: &Path) {
600 let mut arg = OsString::from("/LIBPATH:");
601 arg.push(path);
602 self.cmd.arg(&arg);
603 }
604
605 fn output_filename(&mut self, path: &Path) {
606 let mut arg = OsString::from("/OUT:");
607 arg.push(path);
608 self.cmd.arg(&arg);
609 }
610
611 fn framework_path(&mut self, _path: &Path) {
54a0048b 612 bug!("frameworks are not supported on windows")
62682a34 613 }
e1599b0c 614 fn link_framework(&mut self, _framework: Symbol) {
54a0048b 615 bug!("frameworks are not supported on windows")
62682a34
SL
616 }
617
e1599b0c 618 fn link_whole_staticlib(&mut self, lib: Symbol, _search_path: &[PathBuf]) {
62682a34
SL
619 // not supported?
620 self.link_staticlib(lib);
621 }
c1a9b12d
SL
622 fn link_whole_rlib(&mut self, path: &Path) {
623 // not supported?
624 self.link_rlib(path);
625 }
62682a34
SL
626 fn optimize(&mut self) {
627 // Needs more investigation of `/OPT` arguments
628 }
c1a9b12d 629
0531ce1d
XL
630 fn pgo_gen(&mut self) {
631 // Nothing needed here.
632 }
633
c1a9b12d 634 fn debuginfo(&mut self) {
b039eaaf
SL
635 // This will cause the Microsoft linker to generate a PDB file
636 // from the CodeView line tables in the object files.
637 self.cmd.arg("/DEBUG");
3b2f2976 638
a1dfa0c6 639 // This will cause the Microsoft linker to embed .natvis info into the PDB file
0731742a 640 let natvis_dir_path = self.sess.sysroot.join("lib\\rustlib\\etc");
3b2f2976
XL
641 if let Ok(natvis_dir) = fs::read_dir(&natvis_dir_path) {
642 for entry in natvis_dir {
643 match entry {
644 Ok(entry) => {
645 let path = entry.path();
646 if path.extension() == Some("natvis".as_ref()) {
647 let mut arg = OsString::from("/NATVIS:");
648 arg.push(path);
649 self.cmd.arg(arg);
650 }
651 },
652 Err(err) => {
653 self.sess.warn(&format!("error enumerating natvis directory: {}", err));
654 },
655 }
656 }
657 }
c1a9b12d
SL
658 }
659
e9174d1e
SL
660 // Currently the compiler doesn't use `dllexport` (an LLVM attribute) to
661 // export symbols from a dynamic library. When building a dynamic library,
662 // however, we're going to want some symbols exported, so this function
663 // generates a DEF file which lists all the symbols.
664 //
665 // The linker will read this `*.def` file and export all the symbols from
666 // the dynamic library. Note that this is not as simple as just exporting
94b46f34 667 // all the symbols in the current crate (as specified by `codegen.reachable`)
e9174d1e
SL
668 // but rather we also need to possibly export the symbols of upstream
669 // crates. Upstream rlibs may be linked statically to this dynamic library,
670 // in which case they may continue to transitively be used and hence need
671 // their symbols exported.
a7813a04 672 fn export_symbols(&mut self,
a7813a04
XL
673 tmpdir: &Path,
674 crate_type: CrateType) {
48663c56
XL
675 // Symbol visibility takes care of this typically
676 if crate_type == CrateType::Executable {
677 return;
678 }
679
e9174d1e 680 let path = tmpdir.join("lib.def");
532ac7d7 681 let res: io::Result<()> = try {
54a0048b 682 let mut f = BufWriter::new(File::create(&path)?);
e9174d1e
SL
683
684 // Start off with the standard module name header and then go
685 // straight to exports.
54a0048b
SL
686 writeln!(f, "LIBRARY")?;
687 writeln!(f, "EXPORTS")?;
9e0c209e 688 for symbol in self.info.exports[&crate_type].iter() {
8bb4bdeb 689 debug!(" _{}", symbol);
3157f602 690 writeln!(f, " {}", symbol)?;
e9174d1e 691 }
532ac7d7 692 };
e9174d1e 693 if let Err(e) = res {
3157f602 694 self.sess.fatal(&format!("failed to write lib.def file: {}", e));
e9174d1e
SL
695 }
696 let mut arg = OsString::from("/DEF:");
697 arg.push(path);
698 self.cmd.arg(&arg);
699 }
c30ab7b3
SL
700
701 fn subsystem(&mut self, subsystem: &str) {
702 // Note that previous passes of the compiler validated this subsystem,
703 // so we just blindly pass it to the linker.
704 self.cmd.arg(&format!("/SUBSYSTEM:{}", subsystem));
705
706 // Windows has two subsystems we're interested in right now, the console
707 // and windows subsystems. These both implicitly have different entry
708 // points (starting symbols). The console entry point starts with
709 // `mainCRTStartup` and the windows entry point starts with
710 // `WinMainCRTStartup`. These entry points, defined in system libraries,
711 // will then later probe for either `main` or `WinMain`, respectively to
712 // start the application.
713 //
714 // In Rust we just always generate a `main` function so we want control
715 // to always start there, so we force the entry point on the windows
716 // subsystem to be `mainCRTStartup` to get everything booted up
717 // correctly.
718 //
719 // For more information see RFC #1665
720 if subsystem == "windows" {
721 self.cmd.arg("/ENTRY:mainCRTStartup");
722 }
723 }
cc61c64b
XL
724
725 fn finalize(&mut self) -> Command {
a1dfa0c6 726 ::std::mem::replace(&mut self.cmd, Command::new(""))
cc61c64b 727 }
0531ce1d
XL
728
729 // MSVC doesn't need group indicators
730 fn group_start(&mut self) {}
731 fn group_end(&mut self) {}
94b46f34 732
9fa01778 733 fn linker_plugin_lto(&mut self) {
94b46f34
XL
734 // Do nothing
735 }
62682a34 736}
a7813a04 737
8bb4bdeb 738pub struct EmLinker<'a> {
cc61c64b 739 cmd: Command,
8bb4bdeb
XL
740 sess: &'a Session,
741 info: &'a LinkerInfo
742}
743
744impl<'a> Linker for EmLinker<'a> {
745 fn include_path(&mut self, path: &Path) {
746 self.cmd.arg("-L").arg(path);
747 }
748
e1599b0c
XL
749 fn link_staticlib(&mut self, lib: Symbol) {
750 self.cmd.arg("-l").sym_arg(lib);
8bb4bdeb
XL
751 }
752
753 fn output_filename(&mut self, path: &Path) {
754 self.cmd.arg("-o").arg(path);
755 }
756
757 fn add_object(&mut self, path: &Path) {
758 self.cmd.arg(path);
759 }
760
e1599b0c 761 fn link_dylib(&mut self, lib: Symbol) {
8bb4bdeb
XL
762 // Emscripten always links statically
763 self.link_staticlib(lib);
764 }
765
e1599b0c 766 fn link_whole_staticlib(&mut self, lib: Symbol, _search_path: &[PathBuf]) {
8bb4bdeb
XL
767 // not supported?
768 self.link_staticlib(lib);
769 }
770
771 fn link_whole_rlib(&mut self, lib: &Path) {
772 // not supported?
773 self.link_rlib(lib);
774 }
775
e1599b0c 776 fn link_rust_dylib(&mut self, lib: Symbol, _path: &Path) {
8bb4bdeb
XL
777 self.link_dylib(lib);
778 }
779
780 fn link_rlib(&mut self, lib: &Path) {
781 self.add_object(lib);
782 }
783
784 fn position_independent_executable(&mut self) {
785 // noop
786 }
787
0531ce1d 788 fn no_position_independent_executable(&mut self) {
3b2f2976
XL
789 // noop
790 }
791
792 fn full_relro(&mut self) {
793 // noop
794 }
795
0531ce1d
XL
796 fn partial_relro(&mut self) {
797 // noop
798 }
799
800 fn no_relro(&mut self) {
801 // noop
802 }
803
8bb4bdeb
XL
804 fn args(&mut self, args: &[String]) {
805 self.cmd.args(args);
806 }
807
808 fn framework_path(&mut self, _path: &Path) {
809 bug!("frameworks are not supported on Emscripten")
810 }
811
e1599b0c 812 fn link_framework(&mut self, _framework: Symbol) {
8bb4bdeb
XL
813 bug!("frameworks are not supported on Emscripten")
814 }
815
816 fn gc_sections(&mut self, _keep_metadata: bool) {
817 // noop
818 }
819
820 fn optimize(&mut self) {
821 // Emscripten performs own optimizations
822 self.cmd.arg(match self.sess.opts.optimize {
823 OptLevel::No => "-O0",
824 OptLevel::Less => "-O1",
825 OptLevel::Default => "-O2",
826 OptLevel::Aggressive => "-O3",
827 OptLevel::Size => "-Os",
828 OptLevel::SizeMin => "-Oz"
829 });
830 // Unusable until https://github.com/rust-lang/rust/issues/38454 is resolved
831 self.cmd.args(&["--memory-init-file", "0"]);
832 }
833
0531ce1d
XL
834 fn pgo_gen(&mut self) {
835 // noop, but maybe we need something like the gnu linker?
836 }
837
8bb4bdeb
XL
838 fn debuginfo(&mut self) {
839 // Preserve names or generate source maps depending on debug info
840 self.cmd.arg(match self.sess.opts.debuginfo {
b7449926
XL
841 DebugInfo::None => "-g0",
842 DebugInfo::Limited => "-g3",
843 DebugInfo::Full => "-g4"
8bb4bdeb
XL
844 });
845 }
846
847 fn no_default_libraries(&mut self) {
848 self.cmd.args(&["-s", "DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=[]"]);
849 }
850
851 fn build_dylib(&mut self, _out_filename: &Path) {
852 bug!("building dynamic library is unsupported on Emscripten")
853 }
854
3b2f2976
XL
855 fn build_static_executable(&mut self) {
856 // noop
857 }
858
8bb4bdeb
XL
859 fn export_symbols(&mut self, _tmpdir: &Path, crate_type: CrateType) {
860 let symbols = &self.info.exports[&crate_type];
861
862 debug!("EXPORTED SYMBOLS:");
863
864 self.cmd.arg("-s");
865
866 let mut arg = OsString::from("EXPORTED_FUNCTIONS=");
867 let mut encoded = String::new();
868
869 {
870 let mut encoder = json::Encoder::new(&mut encoded);
871 let res = encoder.emit_seq(symbols.len(), |encoder| {
872 for (i, sym) in symbols.iter().enumerate() {
873 encoder.emit_seq_elt(i, |encoder| {
a1dfa0c6 874 encoder.emit_str(&("_".to_owned() + sym))
8bb4bdeb
XL
875 })?;
876 }
877 Ok(())
878 });
879 if let Err(e) = res {
880 self.sess.fatal(&format!("failed to encode exported symbols: {}", e));
881 }
882 }
883 debug!("{}", encoded);
884 arg.push(encoded);
885
886 self.cmd.arg(arg);
887 }
888
889 fn subsystem(&mut self, _subsystem: &str) {
890 // noop
891 }
cc61c64b
XL
892
893 fn finalize(&mut self) -> Command {
a1dfa0c6 894 ::std::mem::replace(&mut self.cmd, Command::new(""))
cc61c64b 895 }
0531ce1d
XL
896
897 // Appears not necessary on Emscripten
898 fn group_start(&mut self) {}
899 fn group_end(&mut self) {}
94b46f34 900
9fa01778 901 fn linker_plugin_lto(&mut self) {
94b46f34
XL
902 // Do nothing
903 }
8bb4bdeb
XL
904}
905
8faf50e0 906pub struct WasmLd<'a> {
0531ce1d 907 cmd: Command,
8faf50e0 908 sess: &'a Session,
0bf4aa26 909 info: &'a LinkerInfo,
0531ce1d
XL
910}
911
0731742a 912impl<'a> WasmLd<'a> {
416331ca
XL
913 fn new(mut cmd: Command, sess: &'a Session, info: &'a LinkerInfo) -> WasmLd<'a> {
914 // If the atomics feature is enabled for wasm then we need a whole bunch
915 // of flags:
916 //
917 // * `--shared-memory` - the link won't even succeed without this, flags
918 // the one linear memory as `shared`
919 //
920 // * `--max-memory=1G` - when specifying a shared memory this must also
921 // be specified. We conservatively choose 1GB but users should be able
922 // to override this with `-C link-arg`.
923 //
924 // * `--import-memory` - it doesn't make much sense for memory to be
925 // exported in a threaded module because typically you're
926 // sharing memory and instantiating the module multiple times. As a
927 // result if it were exported then we'd just have no sharing.
928 //
929 // * `--passive-segments` - all memory segments should be passive to
930 // prevent each module instantiation from reinitializing memory.
931 //
932 // * `--export=__wasm_init_memory` - when using `--passive-segments` the
933 // linker will synthesize this function, and so we need to make sure
934 // that our usage of `--export` below won't accidentally cause this
935 // function to get deleted.
936 //
937 // * `--export=*tls*` - when `#[thread_local]` symbols are used these
938 // symbols are how the TLS segments are initialized and configured.
939 let atomics = sess.opts.cg.target_feature.contains("+atomics") ||
940 sess.target.target.options.features.contains("+atomics");
941 if atomics {
942 cmd.arg("--shared-memory");
943 cmd.arg("--max-memory=1073741824");
944 cmd.arg("--import-memory");
945 cmd.arg("--passive-segments");
946 cmd.arg("--export=__wasm_init_memory");
947 cmd.arg("--export=__wasm_init_tls");
948 cmd.arg("--export=__tls_size");
949 cmd.arg("--export=__tls_align");
950 cmd.arg("--export=__tls_base");
951 }
0731742a
XL
952 WasmLd { cmd, sess, info }
953 }
954}
955
8faf50e0 956impl<'a> Linker for WasmLd<'a> {
e1599b0c
XL
957 fn link_dylib(&mut self, lib: Symbol) {
958 self.cmd.arg("-l").sym_arg(lib);
0531ce1d
XL
959 }
960
e1599b0c
XL
961 fn link_staticlib(&mut self, lib: Symbol) {
962 self.cmd.arg("-l").sym_arg(lib);
0531ce1d
XL
963 }
964
965 fn link_rlib(&mut self, lib: &Path) {
966 self.cmd.arg(lib);
967 }
968
969 fn include_path(&mut self, path: &Path) {
970 self.cmd.arg("-L").arg(path);
971 }
972
973 fn framework_path(&mut self, _path: &Path) {
974 panic!("frameworks not supported")
975 }
976
977 fn output_filename(&mut self, path: &Path) {
978 self.cmd.arg("-o").arg(path);
979 }
980
981 fn add_object(&mut self, path: &Path) {
982 self.cmd.arg(path);
983 }
984
985 fn position_independent_executable(&mut self) {
986 }
987
988 fn full_relro(&mut self) {
989 }
990
991 fn partial_relro(&mut self) {
992 }
993
994 fn no_relro(&mut self) {
995 }
996
997 fn build_static_executable(&mut self) {
998 }
999
1000 fn args(&mut self, args: &[String]) {
1001 self.cmd.args(args);
1002 }
1003
e1599b0c
XL
1004 fn link_rust_dylib(&mut self, lib: Symbol, _path: &Path) {
1005 self.cmd.arg("-l").sym_arg(lib);
0531ce1d
XL
1006 }
1007
e1599b0c 1008 fn link_framework(&mut self, _framework: Symbol) {
0531ce1d
XL
1009 panic!("frameworks not supported")
1010 }
1011
e1599b0c
XL
1012 fn link_whole_staticlib(&mut self, lib: Symbol, _search_path: &[PathBuf]) {
1013 self.cmd.arg("-l").sym_arg(lib);
0531ce1d
XL
1014 }
1015
1016 fn link_whole_rlib(&mut self, lib: &Path) {
1017 self.cmd.arg(lib);
1018 }
1019
1020 fn gc_sections(&mut self, _keep_metadata: bool) {
8faf50e0 1021 self.cmd.arg("--gc-sections");
0531ce1d
XL
1022 }
1023
1024 fn optimize(&mut self) {
8faf50e0
XL
1025 self.cmd.arg(match self.sess.opts.optimize {
1026 OptLevel::No => "-O0",
1027 OptLevel::Less => "-O1",
1028 OptLevel::Default => "-O2",
1029 OptLevel::Aggressive => "-O3",
1030 // Currently LLD doesn't support `Os` and `Oz`, so pass through `O2`
1031 // instead.
1032 OptLevel::Size => "-O2",
1033 OptLevel::SizeMin => "-O2"
1034 });
0531ce1d
XL
1035 }
1036
1037 fn pgo_gen(&mut self) {
1038 }
1039
1040 fn debuginfo(&mut self) {
1041 }
1042
1043 fn no_default_libraries(&mut self) {
1044 }
1045
1046 fn build_dylib(&mut self, _out_filename: &Path) {
532ac7d7 1047 self.cmd.arg("--no-entry");
0531ce1d
XL
1048 }
1049
0bf4aa26
XL
1050 fn export_symbols(&mut self, _tmpdir: &Path, crate_type: CrateType) {
1051 for sym in self.info.exports[&crate_type].iter() {
1052 self.cmd.arg("--export").arg(&sym);
1053 }
416331ca
XL
1054
1055 // LLD will hide these otherwise-internal symbols since our `--export`
1056 // list above is a whitelist of what to export. Various bits and pieces
1057 // of tooling use this, so be sure these symbols make their way out of
1058 // the linker as well.
1059 self.cmd.arg("--export=__heap_base");
1060 self.cmd.arg("--export=__data_end");
0531ce1d
XL
1061 }
1062
1063 fn subsystem(&mut self, _subsystem: &str) {
1064 }
1065
1066 fn no_position_independent_executable(&mut self) {
1067 }
1068
1069 fn finalize(&mut self) -> Command {
a1dfa0c6 1070 ::std::mem::replace(&mut self.cmd, Command::new(""))
0531ce1d
XL
1071 }
1072
1073 // Not needed for now with LLD
1074 fn group_start(&mut self) {}
1075 fn group_end(&mut self) {}
94b46f34 1076
9fa01778 1077 fn linker_plugin_lto(&mut self) {
94b46f34
XL
1078 // Do nothing for now
1079 }
0531ce1d 1080}
a1dfa0c6 1081
dc9dc135 1082fn exported_symbols(tcx: TyCtxt<'_>, crate_type: CrateType) -> Vec<String> {
a1dfa0c6
XL
1083 if let Some(ref exports) = tcx.sess.target.target.options.override_export_symbols {
1084 return exports.clone()
1085 }
1086
1087 let mut symbols = Vec::new();
1088
1089 let export_threshold = symbol_export::crates_export_threshold(&[crate_type]);
1090 for &(symbol, level) in tcx.exported_symbols(LOCAL_CRATE).iter() {
1091 if level.is_below_threshold(export_threshold) {
1092 symbols.push(symbol.symbol_name(tcx).to_string());
1093 }
1094 }
1095
e74abb32
XL
1096 let formats = tcx.dependency_formats(LOCAL_CRATE);
1097 let deps = formats.iter().filter_map(|(t, list)| {
1098 if *t == crate_type {
1099 Some(list)
1100 } else {
1101 None
1102 }
1103 }).next().unwrap();
a1dfa0c6 1104
e74abb32 1105 for (index, dep_format) in deps.iter().enumerate() {
a1dfa0c6
XL
1106 let cnum = CrateNum::new(index + 1);
1107 // For each dependency that we are linking to statically ...
1108 if *dep_format == Linkage::Static {
1109 // ... we add its symbol list to our export list.
1110 for &(symbol, level) in tcx.exported_symbols(cnum).iter() {
e74abb32
XL
1111 if !level.is_below_threshold(export_threshold) {
1112 continue;
a1dfa0c6 1113 }
e74abb32
XL
1114
1115 // FIXME rust-lang/rust#64319, rust-lang/rust#64872:
1116 // We want to block export of generics from dylibs,
1117 // but we must fix rust-lang/rust#65890 before we can
1118 // do that robustly.
1119
1120 symbols.push(symbol.symbol_name(tcx).to_string());
a1dfa0c6
XL
1121 }
1122 }
1123 }
1124
1125 symbols
1126}
9fa01778
XL
1127
1128/// Much simplified and explicit CLI for the NVPTX linker. The linker operates
1129/// with bitcode and uses LLVM backend to generate a PTX assembly.
1130pub struct PtxLinker<'a> {
1131 cmd: Command,
1132 sess: &'a Session,
1133}
1134
1135impl<'a> Linker for PtxLinker<'a> {
1136 fn link_rlib(&mut self, path: &Path) {
1137 self.cmd.arg("--rlib").arg(path);
1138 }
1139
1140 fn link_whole_rlib(&mut self, path: &Path) {
1141 self.cmd.arg("--rlib").arg(path);
1142 }
1143
1144 fn include_path(&mut self, path: &Path) {
1145 self.cmd.arg("-L").arg(path);
1146 }
1147
1148 fn debuginfo(&mut self) {
1149 self.cmd.arg("--debug");
1150 }
1151
1152 fn add_object(&mut self, path: &Path) {
1153 self.cmd.arg("--bitcode").arg(path);
1154 }
1155
1156 fn args(&mut self, args: &[String]) {
1157 self.cmd.args(args);
1158 }
1159
1160 fn optimize(&mut self) {
1161 match self.sess.lto() {
1162 Lto::Thin | Lto::Fat | Lto::ThinLocal => {
1163 self.cmd.arg("-Olto");
1164 },
1165
1166 Lto::No => { },
1167 };
1168 }
1169
1170 fn output_filename(&mut self, path: &Path) {
1171 self.cmd.arg("-o").arg(path);
1172 }
1173
1174 fn finalize(&mut self) -> Command {
1175 // Provide the linker with fallback to internal `target-cpu`.
1176 self.cmd.arg("--fallback-arch").arg(match self.sess.opts.cg.target_cpu {
1177 Some(ref s) => s,
1178 None => &self.sess.target.target.options.cpu
1179 });
1180
1181 ::std::mem::replace(&mut self.cmd, Command::new(""))
1182 }
1183
e1599b0c 1184 fn link_dylib(&mut self, _lib: Symbol) {
9fa01778
XL
1185 panic!("external dylibs not supported")
1186 }
1187
e1599b0c 1188 fn link_rust_dylib(&mut self, _lib: Symbol, _path: &Path) {
9fa01778
XL
1189 panic!("external dylibs not supported")
1190 }
1191
e1599b0c 1192 fn link_staticlib(&mut self, _lib: Symbol) {
9fa01778
XL
1193 panic!("staticlibs not supported")
1194 }
1195
e1599b0c 1196 fn link_whole_staticlib(&mut self, _lib: Symbol, _search_path: &[PathBuf]) {
9fa01778
XL
1197 panic!("staticlibs not supported")
1198 }
1199
1200 fn framework_path(&mut self, _path: &Path) {
1201 panic!("frameworks not supported")
1202 }
1203
e1599b0c 1204 fn link_framework(&mut self, _framework: Symbol) {
9fa01778
XL
1205 panic!("frameworks not supported")
1206 }
1207
1208 fn position_independent_executable(&mut self) {
1209 }
1210
1211 fn full_relro(&mut self) {
1212 }
1213
1214 fn partial_relro(&mut self) {
1215 }
1216
1217 fn no_relro(&mut self) {
1218 }
1219
1220 fn build_static_executable(&mut self) {
1221 }
1222
1223 fn gc_sections(&mut self, _keep_metadata: bool) {
1224 }
1225
1226 fn pgo_gen(&mut self) {
1227 }
1228
1229 fn no_default_libraries(&mut self) {
1230 }
1231
1232 fn build_dylib(&mut self, _out_filename: &Path) {
1233 }
1234
1235 fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType) {
1236 }
1237
1238 fn subsystem(&mut self, _subsystem: &str) {
1239 }
1240
1241 fn no_position_independent_executable(&mut self) {
1242 }
1243
1244 fn group_start(&mut self) {
1245 }
1246
1247 fn group_end(&mut self) {
1248 }
1249
1250 fn linker_plugin_lto(&mut self) {
1251 }
1252}