Skip to content

Commit 7d4a98e

Browse files
committed
Lib kind -l link-arg:
arbitrary link argument like -C link-arg, but respecting relative order to other `-l` options, unstable
1 parent 9ed0bf9 commit 7d4a98e

22 files changed

+115
-20
lines changed

Diff for: compiler/rustc_codegen_ssa/src/back/link.rs

+29-9
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,7 @@ fn link_rlib<'a, B: ArchiveBuilder<'a>>(
336336
| NativeLibKind::Dylib { .. }
337337
| NativeLibKind::Framework { .. }
338338
| NativeLibKind::RawDylib
339+
| NativeLibKind::LinkArg
339340
| NativeLibKind::Unspecified => continue,
340341
}
341342
if let Some(name) = lib.name {
@@ -1287,6 +1288,7 @@ fn print_native_static_libs(sess: &Session, all_native_libs: &[NativeLib]) {
12871288
}
12881289
// These are included, no need to print them
12891290
NativeLibKind::Static { bundle: None | Some(true), .. }
1291+
| NativeLibKind::LinkArg
12901292
| NativeLibKind::RawDylib => None,
12911293
}
12921294
})
@@ -2225,6 +2227,9 @@ fn add_local_native_libraries(
22252227
// FIXME(#58713): Proper handling for raw dylibs.
22262228
bug!("raw_dylib feature not yet implemented");
22272229
}
2230+
NativeLibKind::LinkArg => {
2231+
cmd.arg(name);
2232+
}
22282233
}
22292234
}
22302235
}
@@ -2362,19 +2367,34 @@ fn add_upstream_rust_crates<'a, B: ArchiveBuilder<'a>>(
23622367
(lib.name, lib.kind, lib.verbatim)
23632368
};
23642369

2365-
if let NativeLibKind::Static { bundle: Some(false), whole_archive } =
2366-
lib.kind
2367-
{
2368-
let verbatim = lib.verbatim.unwrap_or(false);
2369-
if whole_archive == Some(true) {
2370+
match lib.kind {
2371+
NativeLibKind::Static {
2372+
bundle: Some(false),
2373+
whole_archive: Some(true),
2374+
} => {
23702375
cmd.link_whole_staticlib(
23712376
name,
2372-
verbatim,
2377+
lib.verbatim.unwrap_or(false),
23732378
search_path.get_or_init(|| archive_search_paths(sess)),
23742379
);
2375-
} else {
2376-
cmd.link_staticlib(name, verbatim);
23772380
}
2381+
NativeLibKind::Static {
2382+
bundle: Some(false),
2383+
whole_archive: Some(false) | None,
2384+
} => {
2385+
cmd.link_staticlib(name, lib.verbatim.unwrap_or(false));
2386+
}
2387+
NativeLibKind::LinkArg => {
2388+
cmd.arg(name);
2389+
}
2390+
NativeLibKind::Dylib { .. }
2391+
| NativeLibKind::Framework { .. }
2392+
| NativeLibKind::Unspecified
2393+
| NativeLibKind::RawDylib => {}
2394+
NativeLibKind::Static {
2395+
bundle: Some(true) | None,
2396+
whole_archive: _,
2397+
} => {}
23782398
}
23792399
}
23802400
}
@@ -2565,7 +2585,7 @@ fn add_upstream_native_libraries(
25652585
// already included them in add_local_native_libraries and
25662586
// add_upstream_rust_crates
25672587
NativeLibKind::Static { .. } => {}
2568-
NativeLibKind::RawDylib => {}
2588+
NativeLibKind::RawDylib | NativeLibKind::LinkArg => {}
25692589
}
25702590
}
25712591
}

Diff for: compiler/rustc_session/src/config.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -1942,9 +1942,22 @@ fn parse_native_lib_kind(
19421942
"static" => NativeLibKind::Static { bundle: None, whole_archive: None },
19431943
"dylib" => NativeLibKind::Dylib { as_needed: None },
19441944
"framework" => NativeLibKind::Framework { as_needed: None },
1945+
"link-arg" => {
1946+
if !nightly_options::is_unstable_enabled(matches) {
1947+
let why = if nightly_options::match_is_nightly_build(matches) {
1948+
" and only accepted on the nightly compiler"
1949+
} else {
1950+
", the `-Z unstable-options` flag must also be passed to use it"
1951+
};
1952+
early_error(error_format, &format!("library kind `link-arg` is unstable{why}"))
1953+
}
1954+
NativeLibKind::LinkArg
1955+
}
19451956
_ => early_error(
19461957
error_format,
1947-
&format!("unknown library kind `{kind}`, expected one of: static, dylib, framework"),
1958+
&format!(
1959+
"unknown library kind `{kind}`, expected one of: static, dylib, framework, link-arg"
1960+
),
19481961
),
19491962
};
19501963
match modifiers {
@@ -2043,7 +2056,7 @@ fn parse_libs(matches: &getopts::Matches, error_format: ErrorOutputType) -> Vec<
20432056
.into_iter()
20442057
.map(|s| {
20452058
// Parse string of the form "[KIND[:MODIFIERS]=]lib[:new_name]",
2046-
// where KIND is one of "dylib", "framework", "static" and
2059+
// where KIND is one of "dylib", "framework", "static", "link-arg" and
20472060
// where MODIFIERS are a comma separated list of supported modifiers
20482061
// (bundle, verbatim, whole-archive, as-needed). Each modifier is prefixed
20492062
// with either + or - to indicate whether it is enabled or disabled.

Diff for: compiler/rustc_session/src/utils.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ pub enum NativeLibKind {
3434
/// Whether the framework will be linked only if it satisfies some undefined symbols
3535
as_needed: Option<bool>,
3636
},
37+
/// Argument which is passed to linker, relative order with libraries and other arguments
38+
/// is preserved
39+
LinkArg,
3740
/// The library kind wasn't specified, `Dylib` is currently used as a default.
3841
Unspecified,
3942
}
@@ -47,7 +50,7 @@ impl NativeLibKind {
4750
NativeLibKind::Dylib { as_needed } | NativeLibKind::Framework { as_needed } => {
4851
as_needed.is_some()
4952
}
50-
NativeLibKind::RawDylib | NativeLibKind::Unspecified => false,
53+
NativeLibKind::RawDylib | NativeLibKind::Unspecified | NativeLibKind::LinkArg => false,
5154
}
5255
}
5356
}
+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
-include ../../run-make-fulldeps/tools.mk
2+
3+
all:
4+
# Build deps
5+
$(RUSTC) native_dep_1.rs --crate-type=staticlib
6+
$(RUSTC) native_dep_2.rs --crate-type=staticlib
7+
$(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
8+
9+
# Check sequence of linker args
10+
$(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 for: src/test/run-make/pass-linker-flags-from-dep/main.rs

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn main() {
2+
lib::f();
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub fn f1() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub fn f2() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
extern "C" {
2+
pub fn foo();
3+
}
4+
5+
pub fn f() {
6+
unsafe {
7+
foo();
8+
}
9+
}

Diff for: src/test/run-make/pass-linker-flags/Makefile

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
-include ../../run-make-fulldeps/tools.mk
2+
3+
all:
4+
$(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 for: src/test/run-make/pass-linker-flags/rs.rs

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
fn main() {}

Diff for: src/test/ui/manual/manual-link-bad-kind.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// compile-flags:-l bar=foo
2-
// error-pattern: unknown library kind `bar`, expected one of: static, dylib, framework
2+
// error-pattern: unknown library kind `bar`, expected one of: static, dylib, framework, link-arg
33

44
fn main() {
55
}

Diff for: src/test/ui/manual/manual-link-bad-kind.stderr

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
error: unknown library kind `bar`, expected one of: static, dylib, framework
1+
error: unknown library kind `bar`, expected one of: static, dylib, framework, link-arg
22

Diff for: src/test/ui/manual/manual-link-unsupported-kind.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// compile-flags:-l raw-dylib=foo
2-
// error-pattern: unknown library kind `raw-dylib`, expected one of: static, dylib, framework
2+
// error-pattern: unknown library kind `raw-dylib`, expected one of: static, dylib, framework, link-arg
33

44
fn main() {
55
}
+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
error: unknown library kind `raw-dylib`, expected one of: static, dylib, framework
1+
error: unknown library kind `raw-dylib`, expected one of: static, dylib, framework, link-arg
22

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Unspecified kind should fail with an error
22

33
// compile-flags: -l =mylib
4-
// error-pattern: unknown library kind ``, expected one of: static, dylib, framework
4+
// error-pattern: unknown library kind ``, expected one of: static, dylib, framework, link-arg
55

66
fn main() {}
+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
error: unknown library kind ``, expected one of: static, dylib, framework
1+
error: unknown library kind ``, expected one of: static, dylib, framework, link-arg
22

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Unspecified kind should fail with an error
22

33
// compile-flags: -l :+bundle=mylib
4-
// error-pattern: unknown library kind ``, expected one of: static, dylib, framework
4+
// error-pattern: unknown library kind ``, expected one of: static, dylib, framework, link-arg
55

66
fn main() {}
+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
error: unknown library kind ``, expected one of: static, dylib, framework
1+
error: unknown library kind ``, expected one of: static, dylib, framework, link-arg
22

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// compile-flags: -l link-arg:+bundle=arg -Z unstable-options
2+
// error-pattern: linking modifier `bundle` is only compatible with `static` linking kind
3+
4+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
error: linking modifier `bundle` is only compatible with `static` linking kind
2+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// link-arg is not supposed to be usable in #[link] attributes
2+
3+
// compile-flags:
4+
// error-pattern: error[E0458]: unknown link kind `link-arg`, expected one of: static, dylib, framework, raw-dylib
5+
6+
#[link(kind = "link-arg")]
7+
extern "C" {}
8+
pub fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error[E0458]: unknown link kind `link-arg`, expected one of: static, dylib, framework, raw-dylib
2+
--> $DIR/link-arg-from-rs.rs:6:15
3+
|
4+
LL | #[link(kind = "link-arg")]
5+
| ^^^^^^^^^^ unknown link kind
6+
7+
error[E0459]: `#[link]` attribute requires a `name = "string"` argument
8+
--> $DIR/link-arg-from-rs.rs:6:1
9+
|
10+
LL | #[link(kind = "link-arg")]
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `name` argument
12+
13+
error: aborting due to 2 previous errors
14+
15+
Some errors have detailed explanations: E0458, E0459.
16+
For more information about an error, try `rustc --explain E0458`.

0 commit comments

Comments
 (0)