Reputation: 33
I am new to Bazel. I have a project which is built with Bazel. But some of the source files are pre-codegened and then compile them with Bazel. Now I can run the bash script standalone and run the bazel command:
.
|-- project
| |-- BUILD (will depend on temp_output:codegen)
| |-- scripts
| | |-- codegen.sh (read config.yaml and generate codegen.cpp/hpp and a BUILD.bazel)
| |-- config
| | |-- config.yaml
| |-- temp_output
| | |-- codegen.cpp (not existed before running codegen.sh)
| | |-- codegen.hpp (not existed before running codegen.sh)
| | |-- BAZEL.build (not existed before running codegen.sh)
|-- WORKSPACE
$ ./scripts/codegen.sh
$ bazel build :project
What are done in the codegen.sh:
My goal is to embed the bash script in the bazel system. I tried with rule + action.run. But the failures are for:
Is there a fancy way to do this? Or any examples I can refer to?
Upvotes: 3
Views: 5327
Reputation: 3868
The simple way to do this is with genrule. Something like this in project/BUILD
:
genrule(
name = "run_codegen",
srcs = [
"codegen.sh",
"config.yaml",
],
outs = [
"codegen.cpp",
"codegen.hpp",
],
cmd = "$(location codegen.sh) --config $(location config.yaml) --cpp $(location codegen.cpp) --hpp $(location codegen.hpp)",
)
cc_library(
name = "codegen",
hdrs = [ "codegen.hpp" ],
srcs = [ "codegen.cpp" ],
)
Some things to note:
$(location)
to get the paths for the input and output files. If the script uses relative paths, I'd modify it to take the paths as arguments, or write a wrapper script that creates a temporary directory and moves things to/from there based on flags. The only other reliable way to create paths is with "make" variables, but those are generally harder to work with and more brittle with respect to modifications to the genrule.BUILD
file. You can only do this from a repository rule, and it gets significantly more complicated. I don't think you need to for this use case, just write the rule in project/BUILD
.If you want to embed this in a rule instead of using genrule for some reason, make sure you're using File.path to get all the paths to embed in the command. That's the equivalent of $(location)
. It's hard to be more specific about why your rule doesn't work without seeing a copy of it.
Upvotes: 1