Skip to content

Commit 6ef861d

Browse files
borsehuss
authored andcommitted
Auto merge of rust-lang#9563 - ehuss:link-cdylib-warning, r=alexcrichton
Change `rustc-cdylib-link-arg` error to a warning. In rust-lang#9523, an error was added if `cargo:rustc-cdylib-link-arg` was issued in a build script without actually having a cdylib target. This uncovered that there was an unintentional change in rust-lang#8441 to cause those link args to be applied to transitive dependencies. This changes it so that the error is now a warning, with a note that this may become an error in the future. It also changes it so that the unstable `rustc-link-arg*` instructions only apply to the package that emitted them.
1 parent aa8b092 commit 6ef861d

File tree

3 files changed

+145
-17
lines changed

3 files changed

+145
-17
lines changed

src/cargo/core/compiler/custom_build.rs

+13-7
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ pub struct BuildOutput {
3838
/// Environment variables which, when changed, will cause a rebuild.
3939
pub rerun_if_env_changed: Vec<String>,
4040
/// Warnings generated by this build.
41+
///
42+
/// These are only displayed if this is a "local" package, `-vv` is used,
43+
/// or there is a build error for any target in this package.
4144
pub warnings: Vec<String>,
4245
}
4346

@@ -571,13 +574,16 @@ impl BuildOutput {
571574
"rustc-link-search" => library_paths.push(PathBuf::from(value)),
572575
"rustc-link-arg-cdylib" | "rustc-cdylib-link-arg" => {
573576
if !targets.iter().any(|target| target.is_cdylib()) {
574-
bail!(
575-
"invalid instruction `cargo:{}` from {}\n\
576-
The package {} does not have a cdylib target.",
577-
key,
578-
whence,
579-
pkg_descr
580-
);
577+
warnings.push(format!(
578+
"cargo:{} was specified in the build script of {}, \
579+
but that package does not contain a cdylib target\n\
580+
\n\
581+
Allowing this was an unintended change in the 1.50 \
582+
release, and may become an error in the future. \
583+
For more information, see \
584+
<https://github.com/rust-lang/cargo/issues/9562>.",
585+
key, pkg_descr
586+
));
581587
}
582588
linker_args.push((LinkType::Cdylib, value))
583589
}

src/cargo/core/compiler/mod.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,12 @@ fn rustc(cx: &mut Context<'_, '_>, unit: &Unit, exec: &Arc<dyn Executor>) -> Car
394394
}
395395

396396
for (lt, arg) in &output.linker_args {
397-
if lt.applies_to(target) {
397+
// There was an unintentional change where cdylibs were
398+
// allowed to be passed via transitive dependencies. This
399+
// clause should have been kept in the `if` block above. For
400+
// now, continue allowing it for cdylib only.
401+
// See https://github.com/rust-lang/cargo/issues/9562
402+
if lt.applies_to(target) && (key.0 == current_id || *lt == LinkType::Cdylib) {
398403
rustc.arg("-C").arg(format!("link-arg={}", arg));
399404
}
400405
}

tests/testsuite/build_script_extra_link_arg.rs

+126-9
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
//! Tests for -Zextra-link-arg.
22
3-
use cargo_test_support::{basic_bin_manifest, project};
3+
// NOTE: Many of these tests use `without_status()` when passing bogus flags
4+
// because MSVC link.exe just gives a warning on unknown flags (how helpful!),
5+
// and other linkers will return an error.
6+
7+
use cargo_test_support::registry::Package;
8+
use cargo_test_support::{basic_bin_manifest, basic_manifest, project};
49

510
#[cargo_test]
611
fn build_script_extra_link_arg_bin() {
@@ -125,14 +130,16 @@ fn link_arg_missing_target() {
125130
)
126131
.build();
127132

128-
p.cargo("check")
129-
.with_status(101)
130-
.with_stderr("\
131-
[COMPILING] foo [..]
132-
error: invalid instruction `cargo:rustc-link-arg-cdylib` from build script of `foo v0.0.1 ([ROOT]/foo)`
133-
The package foo v0.0.1 ([ROOT]/foo) does not have a cdylib target.
134-
")
135-
.run();
133+
// TODO: Uncomment this if cdylib restriction is re-added (see
134+
// cdylib_link_arg_transitive below).
135+
// p.cargo("check")
136+
// .with_status(101)
137+
// .with_stderr("\
138+
// [COMPILING] foo [..]
139+
// error: invalid instruction `cargo:rustc-link-arg-cdylib` from build script of `foo v0.0.1 ([ROOT]/foo)`
140+
// The package foo v0.0.1 ([ROOT]/foo) does not have a cdylib target.
141+
// ")
142+
// .run();
136143

137144
p.change_file(
138145
"build.rs",
@@ -183,3 +190,113 @@ The instruction should have the form cargo:rustc-link-arg-bin=BIN=ARG
183190
)
184191
.run();
185192
}
193+
194+
#[cargo_test]
195+
fn cdylib_link_arg_transitive() {
196+
// There was an unintended regression in 1.50 where rustc-link-arg-cdylib
197+
// arguments from dependencies were being applied in the parent package.
198+
// Previously it was silently ignored.
199+
// See https://github.com/rust-lang/cargo/issues/9562
200+
let p = project()
201+
.file(
202+
"Cargo.toml",
203+
r#"
204+
[package]
205+
name = "foo"
206+
version = "0.1.0"
207+
208+
[lib]
209+
crate-type = ["cdylib"]
210+
211+
[dependencies]
212+
bar = {path="bar"}
213+
"#,
214+
)
215+
.file("src/lib.rs", "")
216+
.file("bar/Cargo.toml", &basic_manifest("bar", "1.0.0"))
217+
.file("bar/src/lib.rs", "")
218+
.file(
219+
"bar/build.rs",
220+
r#"
221+
fn main() {
222+
println!("cargo:rustc-link-arg-cdylib=--bogus");
223+
}
224+
"#,
225+
)
226+
.build();
227+
p.cargo("build -v")
228+
.without_status()
229+
.with_stderr_contains(
230+
"\
231+
[COMPILING] bar v1.0.0 [..]
232+
[RUNNING] `rustc --crate-name build_script_build bar/build.rs [..]
233+
[RUNNING] `[..]build-script-build[..]
234+
warning: cargo:rustc-link-arg-cdylib was specified in the build script of bar v1.0.0 \
235+
([ROOT]/foo/bar), but that package does not contain a cdylib target
236+
237+
Allowing this was an unintended change in the 1.50 release, and may become an error in \
238+
the future. For more information, see <https://github.com/rust-lang/cargo/issues/9562>.
239+
[RUNNING] `rustc --crate-name bar bar/src/lib.rs [..]
240+
[COMPILING] foo v0.1.0 [..]
241+
[RUNNING] `rustc --crate-name foo src/lib.rs [..]-C link-arg=--bogus[..]`
242+
",
243+
)
244+
.run();
245+
}
246+
247+
#[cargo_test]
248+
fn link_arg_transitive_not_allowed() {
249+
// Verify that transitive dependencies don't pass link args.
250+
//
251+
// Note that rustc-link-arg doesn't have any errors or warnings when it is
252+
// unused. Perhaps that could be more aggressive, but it is difficult
253+
// since it could be used for test binaries.
254+
Package::new("bar", "1.0.0")
255+
.file("src/lib.rs", "")
256+
.file(
257+
"build.rs",
258+
r#"
259+
fn main() {
260+
println!("cargo:rustc-link-arg=--bogus");
261+
}
262+
"#,
263+
)
264+
.publish();
265+
266+
let p = project()
267+
.file(
268+
"Cargo.toml",
269+
r#"
270+
[package]
271+
name = "foo"
272+
version = "0.1.0"
273+
274+
[lib]
275+
crate-type = ["cdylib"]
276+
277+
[dependencies]
278+
bar = "1.0"
279+
"#,
280+
)
281+
.file("src/lib.rs", "")
282+
.build();
283+
284+
p.cargo("build -v -Zextra-link-arg")
285+
.masquerade_as_nightly_cargo()
286+
.with_stderr(
287+
"\
288+
[UPDATING] [..]
289+
[DOWNLOADING] [..]
290+
[DOWNLOADED] [..]
291+
[COMPILING] bar v1.0.0
292+
[RUNNING] `rustc --crate-name build_script_build [..]
293+
[RUNNING] `[..]/build-script-build[..]
294+
[RUNNING] `rustc --crate-name bar [..]
295+
[COMPILING] foo v0.1.0 [..]
296+
[RUNNING] `rustc --crate-name foo src/lib.rs [..]
297+
[FINISHED] dev [..]
298+
",
299+
)
300+
.with_stderr_does_not_contain("--bogus")
301+
.run();
302+
}

0 commit comments

Comments
 (0)