Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cargo vendor regression for git sources containing exclude = ["build.rs"] #14348

Closed
dtolnay opened this issue Aug 3, 2024 · 5 comments · Fixed by #14367
Closed

Cargo vendor regression for git sources containing exclude = ["build.rs"] #14348

dtolnay opened this issue Aug 3, 2024 · 5 comments · Fixed by #14367
Labels
A-git Area: anything dealing with git C-bug Category: bug Command-vendor regression-from-stable-to-stable Regression in stable that worked in a previous stable release. S-needs-mentor Status: Issue or feature is accepted, but needs a team member to commit to helping and reviewing.

Comments

@dtolnay
Copy link
Member

dtolnay commented Aug 3, 2024

Problem

In Rust 1.79 and older releases, cargo vendor used to work for crates that have build scripts applying only to their source repo, and not published to crates.io. An example of such a crate is https://github.com/dtolnay/cxx/blob/1.0.124/macro/Cargo.toml#L8. The build script was correctly omitted from being vendored.

Since Rust 1.80, Cargo still does not vendor the build script, but now it inserts build = "build.rs" into the vendored Cargo.toml, which causes compilation of the vendored sources to fail.

Steps

Create an empty project with this Cargo manifest:

# Cargo.toml

[package]
name = "repro"
version = "0.0.0"
edition = "2021"
publish = false

[dependencies]
cxxbridge-macro = { git = "https://github.com/dtolnay/cxx", tag = "1.0.124" }
$ mkdir .cargo
$ cargo vendor > .cargo/config.toml
$ cargo check
...
   Compiling cxxbridge-macro v1.0.124 (https://github.com/dtolnay/cxx?tag=1.0.124#afd4aa3f)
error: couldn't read /path/to/vendor/vendor/cxxbridge-macro/build.rs: No such file or directory (os error 2)

error: could not compile `cxxbridge-macro` (build script) due to 1 previous error
warning: build failed, waiting for other jobs to finish...

Possible Solution(s)

Do not inject build = "build.rs" into the vendored manifest if build.rs is not being vendored.

Notes

Bisects to 1e60477.

Version

No response

@dtolnay dtolnay added C-bug Category: bug S-triage Status: This issue is waiting on initial triage. labels Aug 3, 2024
@epage
Copy link
Contributor

epage commented Aug 3, 2024

cxx-bridge-macro has an inferred build.rs

https://github.com/dtolnay/cxx/blob/master/macro%2FCargo.toml

We cover a lot of these cases for build.rs for package

fn discovery_inferred_build_rs_included() {

But only had minimal tests for cargo vendor, like

fn git_deterministic() {

@epage
Copy link
Contributor

epage commented Aug 3, 2024

We are using a PathSource to list the files to copy for vendor

let paths = pathsource.list_files(pkg)?;

but only vendoring the normlalized git Cargo.toml

let contents = pkg.manifest().to_normalized_contents()?;

This is not the first time we've been bitten by cargo vendor being almost but not quite like cargo package

// When vendoring git dependencies, the manifest has not been normalized like it would be

While we might want to do a minimal change for backporting, we should evaluate packaging sources to fully unify these so we stop having these problems.

@epage epage added A-git Area: anything dealing with git S-needs-mentor Status: Issue or feature is accepted, but needs a team member to commit to helping and reviewing. Command-vendor regression-from-stable-to-stable Regression in stable that worked in a previous stable release. and removed S-triage Status: This issue is waiting on initial triage. labels Aug 3, 2024
@weihanglo
Copy link
Member

Cargo flavored UI test for the situation of excluding build script.

Details

#[cargo_test]
fn dont_copy_excluded_build_script_for_git_dep() {
    let git = git::new("git_dep", |p| {
        p.file(
            "Cargo.toml", 
            r#"
                [package]
                name = "git_dep"
                edition = "2021"
                exclude = ["build.rs"]
            "#,
        )
            .file("src/lib.rs", "")
            .file("build.rs", "fn main() {}")
    });

    let p = project()
        .file(
            "Cargo.toml",
            &format!(
                r#"
                    [package]
                    name = "foo"
                    edition = "2021"

                    [dependencies]
                    git_dep = {{ git = '{}' }}
                "#,
                git.url()
            ),
        )
        .file("src/lib.rs", "")
        .build();

    let output = p
        .cargo("vendor --respect-source-config")
        .exec_with_output()
        .unwrap();

    // Before 1.80.0 `package.build` expected to be false
    // After cargo#13713 it normalized Carg.toml before copying source from git repo.
    // Taht make `package.build=["build.rs"] get into Cargo.toml.
    //
    // While the behavior of vendoring a git source is not well-defined,
    // this is considered a regression in 1.80.0
    //
    // See cargo#14348 for more.
    assert_e2e().eq(
        p.read_file("vendor/git_dep/Cargo.toml"),
        str![[r##"
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
#
# When uploading crates to the registry Cargo will automatically
# "normalize" Cargo.toml files for maximal compatibility
# with all versions of Cargo and also rewrite `path` dependencies
# to registry (e.g., crates.io) dependencies.
#
# If you are reading this file be aware that the original Cargo.toml
# will likely look very different (and much more reasonable).
# See Cargo.toml.orig for the original contents.

bin = []
example = []
test = []
bench = []

[package]
edition = "2021"
name = "git_dep"
build = "build.rs"
exclude = ["build.rs"]
autobins = false
autoexamples = false
autotests = false
autobenches = false
readme = false

[lib]
name = "git_dep"
path = "src/lib.rs"

"##]],
    );

    let output = String::from_utf8(output.stdout).unwrap();
    p.change_file(".cargo/config.toml", &output);

    // TODO: this should success when we fix cargo#14348.
    p.cargo("check")
        .with_status(101)
        .with_stderr_data(
            str![[r#"
[COMPILING] git_dep v0.0.0 ([ROOTURL]/git_dep#[..])
[ERROR] couldn't read [ROOT]/foo/vendor/git_dep/build.rs: [NOT_FOUND]

[ERROR] could not compile `git_dep` (build script) due to 1 previous error

"#]]
        )
        .run();
}

I am checking if there is any regression beyond build scripts.

@epage
Copy link
Contributor

epage commented Aug 5, 2024

We have cargo package tests that would be good models, testing every build target type. We likely don't need to cover implicit vs explicit as well.

facebook-github-bot pushed a commit to facebookincubator/reindeer that referenced this issue Aug 6, 2024
Summary:
This is a workaround for [rust-lang/cargo#14348](rust-lang/cargo#14348), which is a regression in Rust 1.80's `cargo vendor`.

4 crates in fbsource/third-party/rust are currently impacted:

- `cxx-build`
- `cxxbridge-cmd`
- `cxxbridge-macro`
- `orjson` (https://github.com/ijl/orjson)

The workaround works by writing a build.rs containing just `fn main() {}` for crates where Cargo has injected `build = "build.rs"` into their manifest without vendoring the corresponding build.rs.

We can delete this workaround once the Cargo bug is fixed.

Reviewed By: diliop

Differential Revision: D60855541

fbshipit-source-id: 553c3e45e8f0998fb3091b1f1a82f33b2d7c0a6f
epage added a commit to epage/cargo that referenced this issue Aug 7, 2024
This is a **very** hacky solution, duplicating the minimum of what
`prepare_for_publish` does to fix this one issue and in the least
intrusive way to the vendor code.

The intention is to keep this low risk for backporting to beta and
stable.
We need to revisit this, refactoring the `cargo package` code so that we
can call into that for each vendored dependency.

Fixes rust-lang#14348
bors added a commit that referenced this issue Aug 7, 2024
fix(vendor): Strip excluded build targets

### What does this PR try to resolve?

Fixes #14348

### How should we test and review this PR?

The commits are setup to be able to show, through the tests, how the `cargo package` and `cargo vendor` behavior diverge and then how `cargo vendor`s behavior changes over time.

This is a **very** hacky solution, duplicating the minimum of what
`prepare_for_publish` does to fix this one issue and in the least
intrusive way to the vendor code.

The intention is to keep this low risk for backporting to beta and
stable.
We need to revisit this, refactoring the `cargo package` code so that we
can call into that for each vendored dependency.

### Additional information
@bors bors closed this as completed in 1ae77f5 Aug 7, 2024
epage added a commit to epage/cargo that referenced this issue Aug 7, 2024
This is a **very** hacky solution, duplicating the minimum of what
`prepare_for_publish` does to fix this one issue and in the least
intrusive way to the vendor code.

The intention is to keep this low risk for backporting to beta and
stable.
We need to revisit this, refactoring the `cargo package` code so that we
can call into that for each vendored dependency.

Fixes rust-lang#14348
@epage
Copy link
Contributor

epage commented Aug 7, 2024

#14368 backports this to 1.81

epage added a commit to epage/cargo that referenced this issue Aug 8, 2024
This is a **very** hacky solution, duplicating the minimum of what
`prepare_for_publish` does to fix this one issue and in the least
intrusive way to the vendor code.

The intention is to keep this low risk for backporting to beta and
stable.
We need to revisit this, refactoring the `cargo package` code so that we
can call into that for each vendored dependency.

Fixes rust-lang#14348
epage added a commit to epage/cargo that referenced this issue Aug 8, 2024
This is a **very** hacky solution, duplicating the minimum of what
`prepare_for_publish` does to fix this one issue and in the least
intrusive way to the vendor code.

The intention is to keep this low risk for backporting to beta and
stable.
We need to revisit this, refactoring the `cargo package` code so that we
can call into that for each vendored dependency.

Fixes rust-lang#14348
epage added a commit to epage/cargo that referenced this issue Aug 8, 2024
This is a **very** hacky solution, duplicating the minimum of what
`prepare_for_publish` does to fix this one issue and in the least
intrusive way to the vendor code.

The intention is to keep this low risk for backporting to beta and
stable.
We need to revisit this, refactoring the `cargo package` code so that we
can call into that for each vendored dependency.

Fixes rust-lang#14348
antoniospg pushed a commit to antoniospg/cargo that referenced this issue Sep 8, 2024
This is a **very** hacky solution, duplicating the minimum of what
`prepare_for_publish` does to fix this one issue and in the least
intrusive way to the vendor code.

The intention is to keep this low risk for backporting to beta and
stable.
We need to revisit this, refactoring the `cargo package` code so that we
can call into that for each vendored dependency.

Fixes rust-lang#14348
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-git Area: anything dealing with git C-bug Category: bug Command-vendor regression-from-stable-to-stable Regression in stable that worked in a previous stable release. S-needs-mentor Status: Issue or feature is accepted, but needs a team member to commit to helping and reviewing.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants