From 55205ef8f41ed0993198e3a9ccff0038a95f465e Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Fri, 9 Nov 2018 21:40:12 +0000 Subject: [PATCH 1/5] Add cargo:rustc-link-arg to pass custom linker arguments It is useful to produce correct cdylibs on platforms such as Linux and MacOS. --- src/cargo/core/compiler/build_context/mod.rs | 7 +++++++ src/cargo/core/compiler/custom_build.rs | 5 +++++ src/cargo/core/compiler/mod.rs | 4 ++++ 3 files changed, 16 insertions(+) diff --git a/src/cargo/core/compiler/build_context/mod.rs b/src/cargo/core/compiler/build_context/mod.rs index 789acc8a3ed..9d9f611f48a 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-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..bf587b18b62 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-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..3a217bbe995 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -367,6 +367,10 @@ fn rustc<'a, 'cfg>( rustc.arg("-l").arg(name); } } + for arg in output.linker_args.iter() { + let link_arg = format!("link-arg={}", arg); + rustc.arg("-C").arg(link_arg); + } } } Ok(()) From d426f124ad9daa4ba9f6c39fd5dcb95fd03d620e Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Sun, 18 Nov 2018 09:56:20 +0000 Subject: [PATCH 2/5] Restrict to cdylib the link arg feature --- src/cargo/core/compiler/mod.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 3a217bbe995..6b1563ace0c 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_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_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_link_args: bool, current_id: PackageId, ) -> CargoResult<()> { for key in build_scripts.to_link.iter() { @@ -367,9 +370,11 @@ fn rustc<'a, 'cfg>( rustc.arg("-l").arg(name); } } - for arg in output.linker_args.iter() { - let link_arg = format!("link-arg={}", arg); - rustc.arg("-C").arg(link_arg); + if pass_link_args { + for arg in output.linker_args.iter() { + let link_arg = format!("link-arg={}", arg); + rustc.arg("-C").arg(link_arg); + } } } } From 9741016e24cba076f45a1d06ddccb6ec1d02fa5b Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Fri, 8 Mar 2019 19:36:36 +0000 Subject: [PATCH 3/5] Restrict the link-arg key to rustc-cdylib-link-arg for now --- src/cargo/core/compiler/build_context/mod.rs | 2 +- src/cargo/core/compiler/custom_build.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cargo/core/compiler/build_context/mod.rs b/src/cargo/core/compiler/build_context/mod.rs index 9d9f611f48a..cc3096c4eb5 100644 --- a/src/cargo/core/compiler/build_context/mod.rs +++ b/src/cargo/core/compiler/build_context/mod.rs @@ -259,7 +259,7 @@ impl TargetConfig { .library_paths .extend(list.iter().map(|v| PathBuf::from(&v.0))); } - "rustc-link-arg" => { + "rustc-cdylib-link-arg" => { let args = value.list(k)?; output .linker_args diff --git a/src/cargo/core/compiler/custom_build.rs b/src/cargo/core/compiler/custom_build.rs index bf587b18b62..66074f6997a 100644 --- a/src/cargo/core/compiler/custom_build.rs +++ b/src/cargo/core/compiler/custom_build.rs @@ -487,7 +487,7 @@ impl BuildOutput { } "rustc-link-lib" => library_links.push(value.to_string()), "rustc-link-search" => library_paths.push(PathBuf::from(value)), - "rustc-link-arg" => linker_args.push(value.to_string()), + "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()), From 064afa6d2ca26f6282abd3872d28e6c41cb58648 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Sun, 10 Mar 2019 21:28:37 +0000 Subject: [PATCH 4/5] Document the rustc-cdylib-link-arg key --- src/doc/src/reference/build-scripts.md | 4 ++++ 1 file changed, 4 insertions(+) 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 From f608ed6197feb8b21fba0db8ee24227f40548ed3 Mon Sep 17 00:00:00 2001 From: Luca Barbato Date: Mon, 11 Mar 2019 20:40:55 +0000 Subject: [PATCH 5/5] Rename pass_link_args to pass_cdylib_link_args --- src/cargo/core/compiler/mod.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cargo/core/compiler/mod.rs b/src/cargo/core/compiler/mod.rs index 6b1563ace0c..edf8ac1b88d 100644 --- a/src/cargo/core/compiler/mod.rs +++ b/src/cargo/core/compiler/mod.rs @@ -211,7 +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_link_args = unit.target.is_cdylib(); + 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(); @@ -258,7 +258,7 @@ fn rustc<'a, 'cfg>( &build_state, &build_deps, pass_l_flag, - pass_link_args, + pass_cdylib_link_args, current_id, )?; add_plugin_deps(&mut rustc, &build_state, &build_deps, &root_output)?; @@ -348,7 +348,7 @@ fn rustc<'a, 'cfg>( build_state: &BuildMap, build_scripts: &BuildScripts, pass_l_flag: bool, - pass_link_args: bool, + pass_cdylib_link_args: bool, current_id: PackageId, ) -> CargoResult<()> { for key in build_scripts.to_link.iter() { @@ -370,7 +370,7 @@ fn rustc<'a, 'cfg>( rustc.arg("-l").arg(name); } } - if pass_link_args { + 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);