Manishearth / compiletest-rs

An extraction of the compiletest utility from the Rust compiler
Apache License 2.0
216 stars 59 forks source link

[Question] how do I get compiletest-rs to find the parent crate? #281

Open koenichiwa opened 1 year ago

koenichiwa commented 1 year ago

I have a test package that depends on its parent package. The test code thus depends on the parent package. It seems that compiletest-rs doesn't use the dependencies in Cargo.toml, and I'm trying to figure out another solution.

I'm creating a proc_macro, and tried to test compilation fails with trybuild but ran into this issue. Now I'm trying to do something similar with compiletest-rs, but I can't get it to work. I have the following package structure:

const_typed_builder
|____Cargo.toml
|____target
| |____tests
| |____CACHEDIR.TAG
| |____debug
|____Cargo.lock
|____const_typed_builder_derive
| |____Cargo.toml
| |____src
|____const_typed_builder_test
| |____Cargo.toml
| |____compile_fail
| |____src
| |____workflows
|____src
| |____lib.rs

const_typed_builder_test/src/Cargo.toml includes this line:

[dependencies] # First I tried dev-dependencies but I get that that might not work
const_typed_builder = { path = "../../const_typed_builder", version = "=0.1.1" }

In const_typed_builder_test/src/lib.rs I have the following test

    #[test]
    fn compile_fail_tests() {
        let mut config = compiletest_rs::Config::default();

        config.mode = compiletest_rs::common::Mode::CompileFail;
        config.src_base = std::path::PathBuf::from("./compile_fail");
        // config.run_lib_path = std::path::PathBuf::from(concat!(env!("CARGO_MANIFEST_DIR"),"../../target/"));  // <-- I'm not sure what I was doing with this
        config.link_deps(); // Populate config.target_rustcflags with dependencies on the path
        config.clean_rmeta(); // If your tests import the parent crate, this helps with E0464

        compiletest_rs::run_tests(&config);
    }

In const_typed_builder_test/compile_fail/simple_mandatory_1.rs I have this code:

use const_typed_builder::Builder;

fn main() {
    #[derive(Debug, Default, PartialEq, Eq, Builder)]
    #[builder(assume_mandatory)]
    pub struct Foo {
        bar: Option<String>,
    }
    let foo = Foo::builder().bar(Some("Hello world!".to_string())).build(); //~ ERROR E0599
}

Which is run by

command: "rustc" "./compile_fail/simple_mandatory_1.rs" "-L" "/var/folders/yl/f_6j5mzj01b8hc3zb9vsbfpw0000gn/T/" "--target=x86_64-apple-darwin" "--error-format" "json" "-C" "prefer-dynamic" "-o" "/var/folders/yl/f_6j5mzj01b8hc3zb9vsbfpw0000gn/T/simple_mandatory_1.stage-id" "-A" "unused" "-L" "/var/folders/yl/f_6j5mzj01b8hc3zb9vsbfpw0000gn/T/simple_mandatory_1.stage-id.aux"

And the first unexpected error I get is "1:5: 1:24: unresolved importconst_typed_builder[E0432]"

koenichiwa commented 1 year ago

I got it to work by adding

config.target_rustcflags = Some("-L dependency=../target/debug/deps --extern const_typed_builder=../target/debug/libconst_typed_builder.rlib ".to_string());

Is this best practice?

Manishearth commented 1 year ago

I think that might be fine, I'm not sure what the best way is (and this crate is not actively maintained). Hope it works!