c-api: install headers from build.rs without requiring cmake - #14144
c-api: install headers from build.rs without requiring cmake#14144Isekai923 wants to merge 1 commit into
Conversation
The build script previously shelled out to `cmake -P cmake/install-headers.cmake` to produce the C API headers in OUT_DIR. cmake was only being used as a scripting engine there: it substitutes the #cmakedefine lines in conf.h.in and copies the .h/.hh files. This made cmake a build requirement for every crate that transitively depends on wasmtime-c-api-impl (e.g. anything using tree-sitter's `wasm` feature), even though nothing is compiled with it. Reimplement the header install directly in build.rs with std only: - conf.h is generated from conf.h.in by turning each `#cmakedefine WASMTIME_FEATURE_X` line into `#define ...` or `/* #undef ... */` based on the corresponding CARGO_FEATURE_* env var, with CRLF newlines to match cmake's NEWLINE_STYLE CRLF. The feature list is read from the template itself, so build.rs no longer needs its own copy of WASMTIME_FEATURE_LIST. - headers are copied recursively, matching file(INSTALL ... FILES_MATCHING REGEX "\.hh?$"). The cmake scripts are untouched and still used by the standalone CMake build; build.rs simply no longer invokes cmake. Verified that the OUT_DIR include tree is byte-for-byte identical to the cmake-generated one (all-features-off and a cranelift/gc-drc/wasi/ wat set), and that `cargo check -p wasmtime-c-api-impl` succeeds with cmake removed from PATH.
|
I'm fine with this change in principle but I don't know why cmake was originally used here, so I'm passing this to Alex. |
|
Thanks for the PR, and while I've no doubt an LLM can reproduce CMake's One strategy we've taken in the past for situations like this is to add extra CI checks to ensure that two systems intended to do the same thing actually do the same thing. For example there'd be some sort of CI check that the CMake-created set of header files is the same as the Rust-build-script-created set of header files. That would reduce the likelihood of divergence between the two, and while it wouldn't solve the duplication problem the duplication here is in theory not going to get all that much more complicated than it currently is. |
Currently
wasmtime-c-api-impl's build script shells out tocmake -P cmake/install-headers.cmaketo produce the C API headers inOUT_DIR. cmake is only used as a scripting engine there — it substitutes the#cmakedefinelines inconf.h.inand copies the.h/.hhfiles — but this makes cmake a build requirement for every crate that transitively depends onwasmtime-c-api-impl, most notably anything using tree-sitter'swasmfeature, even though nothing is actually compiled with cmake.This regularly surprises downstream users because the failure only appears when the build-script fingerprint is invalidated ("it built yesterday"), and the error (
failed to spawn 'cmake') doesn't look related to their code. See e.g. zed-industries/zed#18084; we hit the same thing in our project when a dev machine lost its cmake install.What this PR does
Reimplements the header install directly in
build.rsusing std only (~60 lines):wasmtime/conf.his generated fromconf.h.inby turning each#cmakedefine WASMTIME_FEATURE_Xline into#define ...//* #undef ... */based on the correspondingCARGO_FEATURE_*env var, with CRLF newlines matching cmake'sNEWLINE_STYLE CRLF. The feature list is read from the template itself, sobuild.rsno longer needs its own copy of theWASMTIME_FEATURE_LIST.file(INSTALL ... FILES_MATCHING REGEX "\.hh?$").The cmake scripts themselves are untouched and still used by the standalone CMake build of the C API;
build.rssimply no longer invokes cmake.Verification
OUT_DIR/includetree is byte-for-byte identical (diff -r) to the cmake-generated one, tested in both directions: all features off, and withgc-drc/cranelift/wasi/watenabled (covering#defineand/* #undef */paths, CRLF endings, and the recursive copy).cargo check -p wasmtime-c-api-implsucceeds with cmake removed fromPATH.