diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index f0d320c7c21c9..c26e8d99bbb0e 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -336,6 +336,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>( | NativeLibKind::Dylib { .. } | NativeLibKind::Framework { .. } | NativeLibKind::RawDylib + | NativeLibKind::LinkArg | NativeLibKind::Unspecified => continue, } if let Some(name) = lib.name { @@ -1289,6 +1290,7 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLib]) { } // These are included, no need to print them NativeLibKind::Static { bundle: None | Some(true), .. } + | NativeLibKind::LinkArg | NativeLibKind::RawDylib => None, } }) @@ -2243,6 +2245,9 @@ fn add_local_native_libraries( NativeLibKind::RawDylib => { // Ignore RawDylib here, they are handled separately in linker_with_args(). } + NativeLibKind::LinkArg => { + cmd.arg(name); + } } } } @@ -2380,19 +2385,34 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>( (lib.name, lib.kind, lib.verbatim) }; - if let NativeLibKind::Static { bundle: Some(false), whole_archive } = - lib.kind - { - let verbatim = lib.verbatim.unwrap_or(false); - if whole_archive == Some(true) { + match lib.kind { + NativeLibKind::Static { + bundle: Some(false), + whole_archive: Some(true), + } => { cmd.link_whole_staticlib( name, - verbatim, + lib.verbatim.unwrap_or(false), search_path.get_or_init(|| archive_search_paths(sess)), ); - } else { - cmd.link_staticlib(name, verbatim); } + NativeLibKind::Static { + bundle: Some(false), + whole_archive: Some(false) | None, + } => { + cmd.link_staticlib(name, lib.verbatim.unwrap_or(false)); + } + NativeLibKind::LinkArg => { + cmd.arg(name); + } + NativeLibKind::Dylib { .. } + | NativeLibKind::Framework { .. } + | NativeLibKind::Unspecified + | NativeLibKind::RawDylib => {} + NativeLibKind::Static { + bundle: Some(true) | None, + whole_archive: _, + } => {} } } } @@ -2583,7 +2603,7 @@ fn add_upstream_native_libraries( // already included them in add_local_native_libraries and // add_upstream_rust_crates NativeLibKind::Static { .. } => {} - NativeLibKind::RawDylib => {} + NativeLibKind::RawDylib | NativeLibKind::LinkArg => {} } } } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index fe9ef6045415e..15aacea0d4df1 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1944,9 +1944,22 @@ fn parse_native_lib_kind( "static" => NativeLibKind::Static { bundle: None, whole_archive: None }, "dylib" => NativeLibKind::Dylib { as_needed: None }, "framework" => NativeLibKind::Framework { as_needed: None }, + "link-arg" => { + if !nightly_options::is_unstable_enabled(matches) { + let why = if nightly_options::match_is_nightly_build(matches) { + " and only accepted on the nightly compiler" + } else { + ", the `-Z unstable-options` flag must also be passed to use it" + }; + early_error(error_format, &format!("library kind `link-arg` is unstable{why}")) + } + NativeLibKind::LinkArg + } _ => early_error( error_format, - &format!("unknown library kind `{kind}`, expected one of: static, dylib, framework"), + &format!( + "unknown library kind `{kind}`, expected one of: static, dylib, framework, link-arg" + ), ), }; match modifiers { @@ -2045,7 +2058,7 @@ fn parse_libs(matches: &getopts::Matches, error_format: ErrorOutputType) -> Vec< .into_iter() .map(|s| { // Parse string of the form "[KIND[:MODIFIERS]=]lib[:new_name]", - // where KIND is one of "dylib", "framework", "static" and + // where KIND is one of "dylib", "framework", "static", "link-arg" and // where MODIFIERS are a comma separated list of supported modifiers // (bundle, verbatim, whole-archive, as-needed). Each modifier is prefixed // with either + or - to indicate whether it is enabled or disabled. diff --git a/compiler/rustc_session/src/utils.rs b/compiler/rustc_session/src/utils.rs index bda7b314308a5..9a4f6f9f9ef0c 100644 --- a/compiler/rustc_session/src/utils.rs +++ b/compiler/rustc_session/src/utils.rs @@ -34,6 +34,9 @@ pub enum NativeLibKind { /// Whether the framework will be linked only if it satisfies some undefined symbols as_needed: Option, }, + /// Argument which is passed to linker, relative order with libraries and other arguments + /// is preserved + LinkArg, /// The library kind wasn't specified, `Dylib` is currently used as a default. Unspecified, } @@ -47,7 +50,7 @@ impl NativeLibKind { NativeLibKind::Dylib { as_needed } | NativeLibKind::Framework { as_needed } => { as_needed.is_some() } - NativeLibKind::RawDylib | NativeLibKind::Unspecified => false, + NativeLibKind::RawDylib | NativeLibKind::Unspecified | NativeLibKind::LinkArg => false, } } } diff --git a/src/test/run-make/pass-linker-flags-from-dep/Makefile b/src/test/run-make/pass-linker-flags-from-dep/Makefile new file mode 100644 index 0000000000000..365216b4c35bb --- /dev/null +++ b/src/test/run-make/pass-linker-flags-from-dep/Makefile @@ -0,0 +1,10 @@ +-include ../../run-make-fulldeps/tools.mk + +all: + # Build deps + $(RUSTC) native_dep_1.rs --crate-type=staticlib + $(RUSTC) native_dep_2.rs --crate-type=staticlib + $(RUSTC) rust_dep.rs -l static:-bundle=native_dep_1 -l link-arg=some_flag -l static:-bundle=native_dep_2 --crate-type=lib -Z unstable-options + + # Check sequence of linker args + $(RUSTC) main.rs --extern lib=$(TMPDIR)/librust_dep.rlib --crate-type=bin --print link-args | $(CGREP) -e 'native_dep_1.*some_flag.*native_dep_2' diff --git a/src/test/run-make/pass-linker-flags-from-dep/main.rs b/src/test/run-make/pass-linker-flags-from-dep/main.rs new file mode 100644 index 0000000000000..40952fb22b1f5 --- /dev/null +++ b/src/test/run-make/pass-linker-flags-from-dep/main.rs @@ -0,0 +1,3 @@ +fn main() { + lib::f(); +} diff --git a/src/test/run-make/pass-linker-flags-from-dep/native_dep_1.rs b/src/test/run-make/pass-linker-flags-from-dep/native_dep_1.rs new file mode 100644 index 0000000000000..fdb2d9ca68e63 --- /dev/null +++ b/src/test/run-make/pass-linker-flags-from-dep/native_dep_1.rs @@ -0,0 +1 @@ +pub fn f1() {} diff --git a/src/test/run-make/pass-linker-flags-from-dep/native_dep_2.rs b/src/test/run-make/pass-linker-flags-from-dep/native_dep_2.rs new file mode 100644 index 0000000000000..f788b77118461 --- /dev/null +++ b/src/test/run-make/pass-linker-flags-from-dep/native_dep_2.rs @@ -0,0 +1 @@ +pub fn f2() {} diff --git a/src/test/run-make/pass-linker-flags-from-dep/rust_dep.rs b/src/test/run-make/pass-linker-flags-from-dep/rust_dep.rs new file mode 100644 index 0000000000000..7f5df1139342f --- /dev/null +++ b/src/test/run-make/pass-linker-flags-from-dep/rust_dep.rs @@ -0,0 +1,9 @@ +extern "C" { + pub fn foo(); +} + +pub fn f() { + unsafe { + foo(); + } +} diff --git a/src/test/run-make/pass-linker-flags/Makefile b/src/test/run-make/pass-linker-flags/Makefile new file mode 100644 index 0000000000000..02b1e2179e189 --- /dev/null +++ b/src/test/run-make/pass-linker-flags/Makefile @@ -0,0 +1,4 @@ +-include ../../run-make-fulldeps/tools.mk + +all: + $(RUSTC) rs.rs -Z unstable-options -l static=l1 -l link-arg=a1 -l static=l2 -l link-arg=a2 -l dylib=d1 -l link-arg=a3 --print link-args | $(CGREP) -e 'l1.*a1.*l2.*a2.*d1.*a3' diff --git a/src/test/run-make/pass-linker-flags/rs.rs b/src/test/run-make/pass-linker-flags/rs.rs new file mode 100644 index 0000000000000..f328e4d9d04c3 --- /dev/null +++ b/src/test/run-make/pass-linker-flags/rs.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/src/test/ui/manual/manual-link-bad-kind.rs b/src/test/ui/manual/manual-link-bad-kind.rs index d1609338db666..c50a6c034b593 100644 --- a/src/test/ui/manual/manual-link-bad-kind.rs +++ b/src/test/ui/manual/manual-link-bad-kind.rs @@ -1,5 +1,5 @@ // compile-flags:-l bar=foo -// error-pattern: unknown library kind `bar`, expected one of: static, dylib, framework +// error-pattern: unknown library kind `bar`, expected one of: static, dylib, framework, link-arg fn main() { } diff --git a/src/test/ui/manual/manual-link-bad-kind.stderr b/src/test/ui/manual/manual-link-bad-kind.stderr index 86146956699f3..647c4c61e0212 100644 --- a/src/test/ui/manual/manual-link-bad-kind.stderr +++ b/src/test/ui/manual/manual-link-bad-kind.stderr @@ -1,2 +1,2 @@ -error: unknown library kind `bar`, expected one of: static, dylib, framework +error: unknown library kind `bar`, expected one of: static, dylib, framework, link-arg diff --git a/src/test/ui/manual/manual-link-unsupported-kind.rs b/src/test/ui/manual/manual-link-unsupported-kind.rs index 7a40186d504c6..b8ec575a455ff 100644 --- a/src/test/ui/manual/manual-link-unsupported-kind.rs +++ b/src/test/ui/manual/manual-link-unsupported-kind.rs @@ -1,5 +1,5 @@ // compile-flags:-l raw-dylib=foo -// error-pattern: unknown library kind `raw-dylib`, expected one of: static, dylib, framework +// error-pattern: unknown library kind `raw-dylib`, expected one of: static, dylib, framework, link-arg fn main() { } diff --git a/src/test/ui/manual/manual-link-unsupported-kind.stderr b/src/test/ui/manual/manual-link-unsupported-kind.stderr index 4965c0af5f241..ae4a1ec9a959b 100644 --- a/src/test/ui/manual/manual-link-unsupported-kind.stderr +++ b/src/test/ui/manual/manual-link-unsupported-kind.stderr @@ -1,2 +1,2 @@ -error: unknown library kind `raw-dylib`, expected one of: static, dylib, framework +error: unknown library kind `raw-dylib`, expected one of: static, dylib, framework, link-arg diff --git a/src/test/ui/native-library-link-flags/empty-kind-1.rs b/src/test/ui/native-library-link-flags/empty-kind-1.rs index 086d8cff95770..18937856d20d3 100644 --- a/src/test/ui/native-library-link-flags/empty-kind-1.rs +++ b/src/test/ui/native-library-link-flags/empty-kind-1.rs @@ -1,6 +1,6 @@ // Unspecified kind should fail with an error // compile-flags: -l =mylib -// error-pattern: unknown library kind ``, expected one of: static, dylib, framework +// error-pattern: unknown library kind ``, expected one of: static, dylib, framework, link-arg fn main() {} diff --git a/src/test/ui/native-library-link-flags/empty-kind-1.stderr b/src/test/ui/native-library-link-flags/empty-kind-1.stderr index 37846c0b06f69..3e5b054933999 100644 --- a/src/test/ui/native-library-link-flags/empty-kind-1.stderr +++ b/src/test/ui/native-library-link-flags/empty-kind-1.stderr @@ -1,2 +1,2 @@ -error: unknown library kind ``, expected one of: static, dylib, framework +error: unknown library kind ``, expected one of: static, dylib, framework, link-arg diff --git a/src/test/ui/native-library-link-flags/empty-kind-2.rs b/src/test/ui/native-library-link-flags/empty-kind-2.rs index 45ec8ec85e301..851eb63fcd8b8 100644 --- a/src/test/ui/native-library-link-flags/empty-kind-2.rs +++ b/src/test/ui/native-library-link-flags/empty-kind-2.rs @@ -1,6 +1,6 @@ // Unspecified kind should fail with an error // compile-flags: -l :+bundle=mylib -// error-pattern: unknown library kind ``, expected one of: static, dylib, framework +// error-pattern: unknown library kind ``, expected one of: static, dylib, framework, link-arg fn main() {} diff --git a/src/test/ui/native-library-link-flags/empty-kind-2.stderr b/src/test/ui/native-library-link-flags/empty-kind-2.stderr index 37846c0b06f69..3e5b054933999 100644 --- a/src/test/ui/native-library-link-flags/empty-kind-2.stderr +++ b/src/test/ui/native-library-link-flags/empty-kind-2.stderr @@ -1,2 +1,2 @@ -error: unknown library kind ``, expected one of: static, dylib, framework +error: unknown library kind ``, expected one of: static, dylib, framework, link-arg diff --git a/src/test/ui/native-library-link-flags/link-arg-error.rs b/src/test/ui/native-library-link-flags/link-arg-error.rs new file mode 100644 index 0000000000000..e041650d024f4 --- /dev/null +++ b/src/test/ui/native-library-link-flags/link-arg-error.rs @@ -0,0 +1,4 @@ +// compile-flags: -l link-arg:+bundle=arg -Z unstable-options +// error-pattern: linking modifier `bundle` is only compatible with `static` linking kind + +fn main() {} diff --git a/src/test/ui/native-library-link-flags/link-arg-error.stderr b/src/test/ui/native-library-link-flags/link-arg-error.stderr new file mode 100644 index 0000000000000..e1d01e1415274 --- /dev/null +++ b/src/test/ui/native-library-link-flags/link-arg-error.stderr @@ -0,0 +1,2 @@ +error: linking modifier `bundle` is only compatible with `static` linking kind + diff --git a/src/test/ui/native-library-link-flags/link-arg-from-rs.rs b/src/test/ui/native-library-link-flags/link-arg-from-rs.rs new file mode 100644 index 0000000000000..075e4d9e79e46 --- /dev/null +++ b/src/test/ui/native-library-link-flags/link-arg-from-rs.rs @@ -0,0 +1,8 @@ +// link-arg is not supposed to be usable in #[link] attributes + +// compile-flags: +// error-pattern: error[E0458]: unknown link kind `link-arg`, expected one of: static, dylib, framework, raw-dylib + +#[link(kind = "link-arg")] +extern "C" {} +pub fn main() {} diff --git a/src/test/ui/native-library-link-flags/link-arg-from-rs.stderr b/src/test/ui/native-library-link-flags/link-arg-from-rs.stderr new file mode 100644 index 0000000000000..69a7825c0b105 --- /dev/null +++ b/src/test/ui/native-library-link-flags/link-arg-from-rs.stderr @@ -0,0 +1,16 @@ +error[E0458]: unknown link kind `link-arg`, expected one of: static, dylib, framework, raw-dylib + --> $DIR/link-arg-from-rs.rs:6:15 + | +LL | #[link(kind = "link-arg")] + | ^^^^^^^^^^ unknown link kind + +error[E0459]: `#[link]` attribute requires a `name = "string"` argument + --> $DIR/link-arg-from-rs.rs:6:1 + | +LL | #[link(kind = "link-arg")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `name` argument + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0458, E0459. +For more information about an error, try `rustc --explain E0458`.