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

Use Cargo's build script metadata feature to make reliable include dirs #346

Merged
merged 3 commits into from
Oct 8, 2020

Conversation

dtolnay
Copy link
Owner

@dtolnay dtolnay commented Oct 8, 2020

This is the second near complete rewrite of cxx-build (following #276) but I am feeling good about this one.

Background

References:

Cargo has some functionality for build scripts where they can emit metadata as key-value pairs to be made available as environment variables to the build scripts of directly dependent crates. This is exactly the limitation that we want to impose. By building on this, we're able to require that your crate declare a direct dependency on the other crate in order to be able to #include their headers in your C++ build. Headers from transitive dependencies are not made available.

Additionally, the key-value metadata feature forces the the dependency's manifest to contain a links key. This is important because Cargo imposes no ordering on the execution of build scripts not having a links key. When exposing a generated header from a dependency, we need to be sure the dependency's build script has already finished executing and emitted that generated header. Prior to this PR, there wasn't necessarily that ordering and builds which included a header from a dependency could flake depending on what order those build scripts happened to be executed by Cargo.

Directory layout

This PR lays out the OUT_DIR as follows. Everything is namespaced under a cxxbridge subdirectory to avoid stomping on other things that the caller's build script might be doing inside OUT_DIR.

$OUT_DIR/
   cxxbridge/
      crate/
         $CARGO_PKG_NAME -> $CARGO_MANIFEST_DIR
      include/
         rust/
            cxx.h
         $CARGO_PKG_NAME/
            .../
               lib.rs.h
      sources/
         $CARGO_PKG_NAME/
            .../
               lib.rs.cc

Include paths

The generated crate/ and include/ directories are placed on the #include path for the current build as well as for downstream builds that have a direct dependency on the current crate.

We always place include/ before crate/ on the include line so that #include "path/to/file.rs" from C++ magically works and refers to the API generated from that Rust source file. The canonical import path which we'd show in docs is still "path/to/file.rs.h" but I've heard some people really dig the "include a .rs file" style.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant