diff --git a/src/cargo/core/compiler/build_context/mod.rs b/src/cargo/core/compiler/build_context/mod.rs index 789acc8a3ed..cc3096c4eb5 100644 --- a/src/cargo/core/compiler/build_context/mod.rs +++ b/src/cargo/core/compiler/build_context/mod.rs @@ -223,6 +223,7 @@ impl TargetConfig { let mut output = BuildOutput { library_paths: Vec::new(), library_links: Vec::new(), + linker_args: Vec::new(), cfgs: Vec::new(), env: Vec::new(), metadata: Vec::new(), @@ -258,6 +259,12 @@ impl TargetConfig { .library_paths .extend(list.iter().map(|v| PathBuf::from(&v.0))); } + "rustc-cdylib-link-arg" => { + let args = value.list(k)?; + output + .linker_args + .extend(args.iter().map(|v| v.0.clone())); + } "rustc-cfg" => { let list = value.list(k)?; output.cfgs.extend(list.iter().map(|v| v.0.clone())); diff --git a/src/cargo/core/compiler/custom_build.rs b/src/cargo/core/compiler/custom_build.rs index 24658c781b7..66074f6997a 100644 --- a/src/cargo/core/compiler/custom_build.rs +++ b/src/cargo/core/compiler/custom_build.rs @@ -21,6 +21,8 @@ pub struct BuildOutput { pub library_paths: Vec, /// Names and link kinds of libraries, suitable for the `-l` flag. pub library_links: Vec, + /// Linker arguments suitable to be passed to `-C link-arg=` + pub linker_args: Vec, /// Various `--cfg` flags to pass to the compiler. pub cfgs: Vec, /// Additional environment variables to run the compiler with. @@ -437,6 +439,7 @@ impl BuildOutput { ) -> CargoResult { let mut library_paths = Vec::new(); let mut library_links = Vec::new(); + let mut linker_args = Vec::new(); let mut cfgs = Vec::new(); let mut env = Vec::new(); let mut metadata = Vec::new(); @@ -484,6 +487,7 @@ impl BuildOutput { } "rustc-link-lib" => library_links.push(value.to_string()), "rustc-link-search" => library_paths.push(PathBuf::from(value)), + "rustc-cdylib-link-arg" => linker_args.push(value.to_string()), "rustc-cfg" => cfgs.push(value.to_string()), "rustc-env" => env.push(BuildOutput::parse_rustc_env(&value, &whence)?), "warning" => warnings.push(value.to_string()), @@ -496,6 +500,7 @@ impl BuildOutput { Ok(BuildOutput { library_paths, library_links, + linker_args, cfgs, env, metadata, diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 22f70bf67aa..edf8ac1b88d 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -211,6 +211,7 @@ fn rustc<'a, 'cfg>( // If we are a binary and the package also contains a library, then we // don't pass the `-l` flags. let pass_l_flag = unit.target.is_lib() || !unit.pkg.targets().iter().any(|t| t.is_lib()); + let pass_cdylib_link_args = unit.target.is_cdylib(); let do_rename = unit.target.allows_underscores() && !unit.mode.is_any_test(); let real_name = unit.target.name().to_string(); let crate_name = unit.target.crate_name(); @@ -257,6 +258,7 @@ fn rustc<'a, 'cfg>( &build_state, &build_deps, pass_l_flag, + pass_cdylib_link_args, current_id, )?; add_plugin_deps(&mut rustc, &build_state, &build_deps, &root_output)?; @@ -346,6 +348,7 @@ fn rustc<'a, 'cfg>( build_state: &BuildMap, build_scripts: &BuildScripts, pass_l_flag: bool, + pass_cdylib_link_args: bool, current_id: PackageId, ) -> CargoResult<()> { for key in build_scripts.to_link.iter() { @@ -367,6 +370,12 @@ fn rustc<'a, 'cfg>( rustc.arg("-l").arg(name); } } + if pass_cdylib_link_args { + for arg in output.linker_args.iter() { + let link_arg = format!("link-arg={}", arg); + rustc.arg("-C").arg(link_arg); + } + } } } Ok(()) diff --git a/src/doc/src/reference/build-scripts.md b/src/doc/src/reference/build-scripts.md index e9727e181b8..f44564ecddd 100644 --- a/src/doc/src/reference/build-scripts.md +++ b/src/doc/src/reference/build-scripts.md @@ -62,6 +62,7 @@ cargo:rustc-link-lib=static=foo cargo:rustc-link-search=native=/path/to/foo cargo:rustc-cfg=foo cargo:rustc-env=FOO=bar +cargo:rustc-cdylib-link-arg=-Wl,-soname,libfoo.so.1.2.3 # arbitrary user-defined metadata cargo:root=/path/to/foo cargo:libdir=/path/to/foo/lib @@ -93,6 +94,9 @@ crate is built: This is useful for embedding additional metadata in crate's code, such as the hash of Git HEAD or the unique identifier of a continuous integration server. +* `rustc-cdylib-link-arg=FLAG` is a flag passed to the compiler as + `-C link-arg=FLAG` when building a `cdylib`. Its usage is highly platform + specific. It is useful to set the shared library version or the runtime-path. * `rerun-if-changed=PATH` is a path to a file or directory which indicates that the build script should be re-run if it changes (detected by a more-recent last-modified timestamp on the file). Normally build scripts are re-run if