rules_rust icon indicating copy to clipboard operation
rules_rust copied to clipboard

rust_bindgen rule cannot find stdarg.h during remote execution

Open djmarcin opened this issue 3 years ago • 6 comments

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

djmarcin avatar Sep 08 '21 04:09 djmarcin

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.

djmarcin avatar Sep 08 '21 04:09 djmarcin

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

illicitonion avatar Sep 08 '21 09:09 illicitonion

I tried both with and without a custom toolchain and they both exhibited the issue.

djmarcin avatar Sep 08 '21 14:09 djmarcin

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.

djmarcin avatar Sep 08 '21 15:09 djmarcin

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?

illicitonion avatar Sep 09 '21 10:09 illicitonion

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.

djmarcin avatar Mar 15 '22 19:03 djmarcin