rules_rust
rules_rust copied to clipboard
rust_bindgen rule cannot find stdarg.h during remote execution
When I try to use rust_bindgen
for the following files, it fails.
foo.h:
#include <stdarg.h>
int call(int foo);
foo.cc:
#include "foo.h"
int call(int foo) {}
BUILD
cc_library(
name = "foo",
srcs = ["foo.cc"],
hdrs = ["foo.h"],
)
rust_bindgen(
name = "foo_bindgen",
cc_lib = ":foo",
header = "foo.h",
)
Error:
ERROR: /home/david/test/BUILD:67:13: Generating bindings for foo.h.. failed: (Exit 1): cargo_bin_bindgen failed: error executing command bazel-out/k8-opt-exec-2B5CBBC6/bin/external/rules_rust_bindgen__bindgen__0_58_1/cargo_bin_bindgen --no-rustfmt-bindings foo.h --output ... (remaining 6 arguments skipped)
foo.h:1:10: fatal error: 'stdarg.h' file not found
foo.h:1:10: fatal error: 'stdarg.h' file not found, err: true
thread 'main' panicked at 'Unable to generate bindings: ()', external/rules_rust_bindgen__bindgen__0_58_1/src/main.rs:54:36
Specifically, this is a problem when using remote execution. When executing locally, it works, so it is probably finding stdarg.h via some undeclared inputs.
I have a hacky workaround where I create a header-only library that contains the stdlib and depend on that from my cc_library. This causes this line to make the stdlib headers explicit inputs to the action, so they appear on the remote exec machine, and then I pass a manual -Iexternal/toolchain/path/to/stdlib/include
in clang_flags to bindgen so that it can find the headers. Maybe that gives some insight into how this should be fixed.
Are you using a custom cc_toolchain?
See also https://github.com/bazelbuild/rules_rust/issues/899#issuecomment-902600722 for a similar issue where we're not propagating information from the cc_toolchain through to bindgen
I tried both with and without a custom toolchain and they both exhibited the issue.
I think what makes this issue different from the linked issue is that remote execution only works if all inputs from the execroot are declared, whereas local execution can get away with not declaring some inputs in certain cases.
I believe the libclang bindgen uses is attempting to look up the system headers in a location relative to itself, which works locally because those files exist in the execroot, but remotely, since they were not declared explicit inputs, they don’t exist and therefore cannot be found.
I think that means that you need to be fleshing out a cc_toolchain to declare those as inputs, so that they're present when doing remote execution?
When you say "you need to" that implies that this isn't just broken with the base rules_rust
-- it is. I agree that the problem is likely that the rust_bindgen_toolchain rule does not accurately capture all the dependencies that are needed to run clang, so it fails when executed remotely.
Here is an example repository that reproduces the issue: https://github.com/djmarcin/bindgen_example I am using our internal build cluster so the example probably can't be trivially executed as written but it should reproduce on any remote execution environment with a few tweaks to set the flags correctly.