From f7617c1cd4d1910613ffecdfd8de28889002f6cc Mon Sep 17 00:00:00 2001 From: zetanumbers Date: Wed, 29 Nov 2023 02:13:58 -0800 Subject: [PATCH] Enable link-arg link kind inside of #[link] attribute - Implement link-arg as an attribute - Apply suggestions from review - Co-authored-by: Vadim Petrochenkov - Add unstable book entry --- compiler/rustc_feature/src/unstable.rs | 3 +++ compiler/rustc_metadata/messages.ftl | 2 +- compiler/rustc_metadata/src/native_libs.rs | 12 +++++++++++ compiler/rustc_span/src/symbol.rs | 1 + .../language-features/link-arg-attribute.md | 21 +++++++++++++++++++ .../pass-linker-flags-flavor/Makefile | 9 +++++--- .../pass-linker-flags-flavor/attribute.rs | 12 +++++++++++ .../{rs.rs => empty.rs} | 0 .../pass-linker-flags-from-dep/Makefile | 6 ++++-- .../rust_dep_attr.rs | 14 +++++++++++++ .../{rust_dep.rs => rust_dep_flag.rs} | 0 tests/run-make/pass-linker-flags/Makefile | 3 ++- tests/run-make/pass-linker-flags/attribute.rs | 11 ++++++++++ .../pass-linker-flags/{rs.rs => empty.rs} | 0 tests/ui/error-codes/E0458.stderr | 2 +- .../feature-gate-link-arg-attribute.rs | 5 +++++ .../feature-gate-link-arg-attribute.stderr | 12 +++++++++++ .../link-arg-from-rs.rs | 9 ++++---- .../link-arg-from-rs.stderr | 18 +++++----------- 19 files changed, 114 insertions(+), 26 deletions(-) create mode 100644 src/doc/unstable-book/src/language-features/link-arg-attribute.md create mode 100644 tests/run-make/pass-linker-flags-flavor/attribute.rs rename tests/run-make/pass-linker-flags-flavor/{rs.rs => empty.rs} (100%) create mode 100644 tests/run-make/pass-linker-flags-from-dep/rust_dep_attr.rs rename tests/run-make/pass-linker-flags-from-dep/{rust_dep.rs => rust_dep_flag.rs} (100%) create mode 100644 tests/run-make/pass-linker-flags/attribute.rs rename tests/run-make/pass-linker-flags/{rs.rs => empty.rs} (100%) create mode 100644 tests/ui/feature-gates/feature-gate-link-arg-attribute.rs create mode 100644 tests/ui/feature-gates/feature-gate-link-arg-attribute.stderr diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 8182c8779ff91..87acb6f27c565 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -500,6 +500,9 @@ declare_features! ( (incomplete, lazy_type_alias, "1.72.0", Some(112792), None), /// Allows `if/while p && let q = r && ...` chains. (unstable, let_chains, "1.37.0", Some(53667), None), + /// Allows using `#[link(kind = "link-arg", name = "...")]` + /// to pass custom arguments to the linker. + (unstable, link_arg_attribute, "CURRENT_RUSTC_VERSION", Some(99427), None), /// Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check. (unstable, lint_reasons, "1.31.0", Some(54503), None), /// Give access to additional metadata about declarative macro meta-variables. diff --git a/compiler/rustc_metadata/messages.ftl b/compiler/rustc_metadata/messages.ftl index 44b235a6d3d22..8da6f0007f03a 100644 --- a/compiler/rustc_metadata/messages.ftl +++ b/compiler/rustc_metadata/messages.ftl @@ -269,7 +269,7 @@ metadata_unknown_import_name_type = unknown import name type `{$import_name_type}`, expected one of: decorated, noprefix, undecorated metadata_unknown_link_kind = - unknown link kind `{$kind}`, expected one of: static, dylib, framework, raw-dylib + unknown link kind `{$kind}`, expected one of: static, dylib, framework, raw-dylib, link-arg .label = unknown link kind metadata_unknown_link_modifier = diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index f352fa6d46ae9..b3760b1099b4b 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -160,6 +160,18 @@ impl<'tcx> Collector<'tcx> { } NativeLibKind::RawDylib } + "link-arg" => { + if !features.link_arg_attribute { + feature_err( + &sess.parse_sess, + sym::link_arg_attribute, + span, + "link kind `link-arg` is unstable", + ) + .emit(); + } + NativeLibKind::LinkArg + } kind => { sess.emit_err(errors::UnknownLinkKind { span, kind }); continue; diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 46545416b5e1b..f1a1f23e6dd25 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -934,6 +934,7 @@ symbols! { likely, line, link, + link_arg_attribute, link_args, link_cfg, link_llvm_intrinsics, diff --git a/src/doc/unstable-book/src/language-features/link-arg-attribute.md b/src/doc/unstable-book/src/language-features/link-arg-attribute.md new file mode 100644 index 0000000000000..09915a7f2748d --- /dev/null +++ b/src/doc/unstable-book/src/language-features/link-arg-attribute.md @@ -0,0 +1,21 @@ +# `link_arg_attribute` + +The tracking issue for this feature is: [#99427] + +------ + +The `link_arg_attribute` feature allows passing arguments into the linker +from inside of the source code. Order is preserved for link attributes as +they were defined on a single extern block: + +```rust,no_run +#![feature(link_arg_attribute)] + +#[link(kind = "link-arg", name = "--start-group")] +#[link(kind = "static", name = "c")] +#[link(kind = "static", name = "gcc")] +#[link(kind = "link-arg", name = "--end-group")] +extern "C" {} +``` + +[#99427]: https://github.com/rust-lang/rust/issues/99427 diff --git a/tests/run-make/pass-linker-flags-flavor/Makefile b/tests/run-make/pass-linker-flags-flavor/Makefile index bd3d3ed882fbc..1bb05d0f97478 100644 --- a/tests/run-make/pass-linker-flags-flavor/Makefile +++ b/tests/run-make/pass-linker-flags-flavor/Makefile @@ -3,6 +3,9 @@ include ../tools.mk all: - $(RUSTC) rs.rs -Z unstable-options -C linker-flavor=gnu-cc -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.*-Wl,a1.*l2.*-Wl,a2.*d1.*-Wl,a3' - $(RUSTC) rs.rs -Z unstable-options -C linker-flavor=gnu-cc -l static=l1 -l link-arg:+verbatim=a1 -l static=l2 -l link-arg=a2 -l dylib=d1 -l link-arg=a3 --print link-args | $(CGREP) -e 'l1.*"a1".*l2.*-Wl,a2.*d1.*-Wl,a3' - $(RUSTC) rs.rs -Z unstable-options -C linker-flavor=ld -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"' + $(RUSTC) empty.rs -Z unstable-options -C linker-flavor=gnu-cc -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.*-Wl,a1.*l2.*-Wl,a2.*d1.*-Wl,a3' + $(RUSTC) empty.rs -Z unstable-options -C linker-flavor=gnu-cc -l static=l1 -l link-arg:+verbatim=a1 -l static=l2 -l link-arg=a2 -l dylib=d1 -l link-arg=a3 --print link-args | $(CGREP) -e 'l1.*"a1".*l2.*-Wl,a2.*d1.*-Wl,a3' + $(RUSTC) empty.rs -Z unstable-options -C linker-flavor=ld -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"' + $(RUSTC) attribute.rs -Z unstable-options -C linker-flavor=gnu-cc --print link-args | $(CGREP) -e 'l1.*-Wl,a1.*l2.*-Wl,a2.*d1.*-Wl,a3' + $(RUSTC) --cfg 'feature="verbatim"' attribute.rs -Z unstable-options -C linker-flavor=gnu-cc --print link-args | $(CGREP) -e 'l1.*"a1".*l2.*-Wl,a2.*d1.*-Wl,a3' + $(RUSTC) attribute.rs -C linker-flavor=ld --print link-args | $(CGREP) -e 'l1.*"a1".*l2.*"a2".*d1.*"a3"' diff --git a/tests/run-make/pass-linker-flags-flavor/attribute.rs b/tests/run-make/pass-linker-flags-flavor/attribute.rs new file mode 100644 index 0000000000000..d099165301bd3 --- /dev/null +++ b/tests/run-make/pass-linker-flags-flavor/attribute.rs @@ -0,0 +1,12 @@ +#![feature(link_arg_attribute)] + +#[link(kind = "static", name = "l1")] +#[cfg_attr(feature = "verbatim", link(kind = "link-arg", name = "a1", modifiers = "+verbatim"))] +#[cfg_attr(not(feature = "verbatim"), link(kind = "link-arg", name = "a1"))] +#[link(kind = "static", name = "l2")] +#[link(kind = "link-arg", name = "a2")] +#[link(kind = "dylib", name = "d1")] +#[link(kind = "link-arg", name = "a3")] +extern "C" {} + +fn main() {} diff --git a/tests/run-make/pass-linker-flags-flavor/rs.rs b/tests/run-make/pass-linker-flags-flavor/empty.rs similarity index 100% rename from tests/run-make/pass-linker-flags-flavor/rs.rs rename to tests/run-make/pass-linker-flags-flavor/empty.rs diff --git a/tests/run-make/pass-linker-flags-from-dep/Makefile b/tests/run-make/pass-linker-flags-from-dep/Makefile index b57389bb7d491..48b3b26ce81e6 100644 --- a/tests/run-make/pass-linker-flags-from-dep/Makefile +++ b/tests/run-make/pass-linker-flags-from-dep/Makefile @@ -4,7 +4,9 @@ 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 + $(RUSTC) rust_dep_flag.rs -l static:-bundle=native_dep_1 -l link-arg=some_flag -l static:-bundle=native_dep_2 --crate-type=lib -Z unstable-options + $(RUSTC) rust_dep_attr.rs --crate-type=lib # 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' + $(RUSTC) main.rs --extern lib=$(TMPDIR)/librust_dep_flag.rlib --crate-type=bin --print link-args | $(CGREP) -e 'native_dep_1.*some_flag.*native_dep_2' + $(RUSTC) main.rs --extern lib=$(TMPDIR)/librust_dep_attr.rlib --crate-type=bin --print link-args | $(CGREP) -e 'native_dep_1.*some_flag.*native_dep_2' diff --git a/tests/run-make/pass-linker-flags-from-dep/rust_dep_attr.rs b/tests/run-make/pass-linker-flags-from-dep/rust_dep_attr.rs new file mode 100644 index 0000000000000..ac5888ce610b3 --- /dev/null +++ b/tests/run-make/pass-linker-flags-from-dep/rust_dep_attr.rs @@ -0,0 +1,14 @@ +#![feature(link_arg_attribute)] + +#[link(kind = "static", name = "native_dep_1", modifiers = "-bundle")] +#[link(kind = "link-arg", name = "some_flag")] +#[link(kind = "static", name = "native_dep_2", modifiers = "-bundle")] +extern "C" { + pub fn foo(); +} + +pub fn f() { + unsafe { + foo(); + } +} diff --git a/tests/run-make/pass-linker-flags-from-dep/rust_dep.rs b/tests/run-make/pass-linker-flags-from-dep/rust_dep_flag.rs similarity index 100% rename from tests/run-make/pass-linker-flags-from-dep/rust_dep.rs rename to tests/run-make/pass-linker-flags-from-dep/rust_dep_flag.rs diff --git a/tests/run-make/pass-linker-flags/Makefile b/tests/run-make/pass-linker-flags/Makefile index 6ddbcbb1b08e6..226943e93bdc0 100644 --- a/tests/run-make/pass-linker-flags/Makefile +++ b/tests/run-make/pass-linker-flags/Makefile @@ -1,4 +1,5 @@ include ../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' + $(RUSTC) empty.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' + $(RUSTC) attribute.rs --print link-args | $(CGREP) -e 'l1.*a1.*l2.*a2.*d1.*a3' diff --git a/tests/run-make/pass-linker-flags/attribute.rs b/tests/run-make/pass-linker-flags/attribute.rs new file mode 100644 index 0000000000000..6f784c01ff2a1 --- /dev/null +++ b/tests/run-make/pass-linker-flags/attribute.rs @@ -0,0 +1,11 @@ +#![feature(link_arg_attribute)] + +#[link(kind = "static", name = "l1")] +#[link(kind = "link-arg", name = "a1")] +#[link(kind = "static", name = "l2")] +#[link(kind = "link-arg", name = "a2")] +#[link(kind = "dylib", name = "d1")] +#[link(kind = "link-arg", name = "a3")] +extern "C" {} + +fn main() {} diff --git a/tests/run-make/pass-linker-flags/rs.rs b/tests/run-make/pass-linker-flags/empty.rs similarity index 100% rename from tests/run-make/pass-linker-flags/rs.rs rename to tests/run-make/pass-linker-flags/empty.rs diff --git a/tests/ui/error-codes/E0458.stderr b/tests/ui/error-codes/E0458.stderr index e641bba541ee0..c13ae4e78629a 100644 --- a/tests/ui/error-codes/E0458.stderr +++ b/tests/ui/error-codes/E0458.stderr @@ -1,4 +1,4 @@ -error[E0458]: unknown link kind `wonderful_unicorn`, expected one of: static, dylib, framework, raw-dylib +error[E0458]: unknown link kind `wonderful_unicorn`, expected one of: static, dylib, framework, raw-dylib, link-arg --> $DIR/E0458.rs:1:15 | LL | #[link(kind = "wonderful_unicorn")] extern "C" {} diff --git a/tests/ui/feature-gates/feature-gate-link-arg-attribute.rs b/tests/ui/feature-gates/feature-gate-link-arg-attribute.rs new file mode 100644 index 0000000000000..9036095fbc495 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-link-arg-attribute.rs @@ -0,0 +1,5 @@ +#[link(kind = "link-arg", name = "foo")] +//~^ ERROR link kind `link-arg` is unstable +extern "C" {} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-link-arg-attribute.stderr b/tests/ui/feature-gates/feature-gate-link-arg-attribute.stderr new file mode 100644 index 0000000000000..673835b8b9ebf --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-link-arg-attribute.stderr @@ -0,0 +1,12 @@ +error[E0658]: link kind `link-arg` is unstable + --> $DIR/feature-gate-link-arg-attribute.rs:1:15 + | +LL | #[link(kind = "link-arg", name = "foo")] + | ^^^^^^^^^^ + | + = note: see issue #99427 for more information + = help: add `#![feature(link_arg_attribute)]` to the crate attributes to enable + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/native-library-link-flags/link-arg-from-rs.rs b/tests/ui/native-library-link-flags/link-arg-from-rs.rs index 075e4d9e79e46..4a6017fea339a 100644 --- a/tests/ui/native-library-link-flags/link-arg-from-rs.rs +++ b/tests/ui/native-library-link-flags/link-arg-from-rs.rs @@ -1,8 +1,7 @@ -// link-arg is not supposed to be usable in #[link] attributes +#![feature(link_arg_attribute)] -// compile-flags: -// error-pattern: error[E0458]: unknown link kind `link-arg`, expected one of: static, dylib, framework, raw-dylib - -#[link(kind = "link-arg")] +#[link(kind = "link-arg", name = "arg", modifiers = "+bundle")] +//~^ ERROR linking modifier `bundle` is only compatible with `static` linking kind extern "C" {} + pub fn main() {} diff --git a/tests/ui/native-library-link-flags/link-arg-from-rs.stderr b/tests/ui/native-library-link-flags/link-arg-from-rs.stderr index 69a7825c0b105..f31e15f1da615 100644 --- a/tests/ui/native-library-link-flags/link-arg-from-rs.stderr +++ b/tests/ui/native-library-link-flags/link-arg-from-rs.stderr @@ -1,16 +1,8 @@ -error[E0458]: unknown link kind `link-arg`, expected one of: static, dylib, framework, raw-dylib - --> $DIR/link-arg-from-rs.rs:6:15 +error: linking modifier `bundle` is only compatible with `static` linking kind + --> $DIR/link-arg-from-rs.rs:3:53 | -LL | #[link(kind = "link-arg")] - | ^^^^^^^^^^ unknown link kind +LL | #[link(kind = "link-arg", name = "arg", modifiers = "+bundle")] + | ^^^^^^^^^ -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 +error: aborting due to 1 previous error -Some errors have detailed explanations: E0458, E0459. -For more information about an error, try `rustc --explain E0458`.