Use Cargo's build script metadata feature to make reliable include dirs #346
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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 alinks
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.
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.