Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bazel & automatically generated cpp / hpp files

Tags:

c++

bazel

I am starting to use Bazel as my C++ project build system.

However I am stuck with the following problem:

I am in a scenario where I automatically generate the file.hpp file.cpp (literate programming).

To reproduce my problem one can simply use this minimal generator:

-- file.sh --
#!/bin/sh
echo "int foo();" >> file.hpp
echo "#include \"myLib/file.hpp\"\n\nint foo() { return 2017; }" >> file.cpp

My project repo is: (WORKSPACE is an empty file)

├── myLib
│   ├── BUILD
│   └── file.sh
└── WORKSPACE

The BUILD file is

genrule(
  name = "tangle_file",
  srcs = ["file.sh"],
  outs = ["file.cpp","file.hpp"],
  cmd =  "./$(location file.sh);cp file.cpp $(@D);cp file.hpp $(@D);"
)

cc_library(
    name = "file",
    srcs = ["file.cpp"],
    hdrs = ["file.hpp"],
#    deps = [":tangle_file"],
    visibility = ["//bin:__pkg__"],
)

I have two problems:

Question (A), dealing with the genrule() part:

The fact that I must use

cmd =  "./$(location file.sh);cp file.cpp $(@D);cp file.hpp $(@D);"

is quite mysterious.

My first attempt was:

cmd =  "./$(location file.sh)"

However in that case I get the following error:

declared output 'myLib/file.cpp' was not created by genrule. This is probably because the genrule actually didn't create this output, or because the output was a directory and the genrule was run remotely (note that only the contents of declared file outputs are copied from genrules run remotely)

Question (B), dealing with the cc_library() part

I do not know how to make Bazel aware of that the :file target depends on the :tangle_file target.

If I uncomment:

deps = [":tangle_file"],

I get the following error:

in deps attribute of cc_library rule //myLib:file: genrule rule '//myLib:tangle_file' is misplaced here (expected cc_inc_library, cc_library, objc_library, experimental_objc_library or cc_proto_library).

like image 249
Picaud Vincent Avatar asked Jun 01 '17 16:06

Picaud Vincent


People also ask

What is Bazel used for?

Bazel is a tool that automates software builds and tests. Supported build tasks include running compilers and linkers to produce executable programs and libraries, and assembling deployable packages for Android, iOS and other target environments.

Is Bazel better than Maven?

Bazel supports multiple build files and multiple targets per BUILD file, allowing for builds that are more incremental than Maven's. Maven takes charge of steps for the deployment process. Bazel does not automate deployment. Bazel enables you to express dependencies between languages.

Is Bazel any good?

Bazel is fast and builds correctly - It can cache build results and only rebuild what it needs to, which make it fast. Its platform independent - It can run on Linux, macOS, Windows. Bazel scales - It can handle large source files easily. It works with various repositories and user bases in the tens of thousands.

Is Bazel better than Gradle?

In summary, the data and analysis indicates clearly that Gradle is a better choice than Bazel for most JVM projects. We will provide an equivalent comparison for Android projects in a follow up article.


1 Answers

Question (A)

The error that you are seeing is because the genrule cmd is not run inside of its output directory. If you hardcoded bazel-out/local-fastbuild/genfiles/myLib/file.cpp instead of file.cpp in your file.sh script, it would work. However, the recommended approach would be for your script to takes its output directory as an argument.

For example,

genrule(
  name = "tangle_file",
  srcs = ["file.sh"],
  outs = ["file.cpp","file.hpp"],
  cmd =  "./$(location file.sh) $(@D)"
)

and

#!/bin/sh
echo "int foo();" >> $1/file.hpp
echo "#include \"myLib/file.hpp\"\n\nint foo() { return 2017; }" >> $1/file.cpp

Question (B)

The fact that you have

srcs = ["file.cpp"],
hdrs = ["file.hpp"],

in your cc_library is what tells Bazel that it depends on the genrule, since the genrule creates those files. If you want to make it more explicit, you could use the label syntax, which does the same thing:

srcs = ["//myLib:file.cpp"],
hdrs = ["//myLib:file.hpp"],
like image 168
Adam Avatar answered Oct 17 '22 01:10

Adam