Bridging a cmake build to a bazel build

6,485 views
Skip to first unread message

jim...@google.com

unread,
Mar 21, 2018, 12:03:17 AM3/21/18
to bazel-discuss
Hello all,
I may post this to stack overflow as well, but I'll try here first. I have a question about using build artifacts from bazel in another build system (cmake).

The setup:
We have project Foo which needs to use some code in project Bar. Project Foo uses cmake for its build system; project Bar uses bazel. Naively, we can use a custom cmake rule (add_custom_target or ExternalProject_Add) to invoke bazel build for Bar however we want, produce Bar's build artifacts, declare that the custom cmake rule produces Bar's artifacts, then use them in Foo's cmake.

Here's what Foo's bazel invocation looks like:
$ bazel build //somedir/subdir:toplevel_target

And let's say that toplevel_target looks like this:
cc_library(
name = "toplevel_target",
srcs = ["toplevel_target.cc"],
hdrs = ["toplevel_target.h"],
deps = [
"//base/some_base_library",
"//third_party/some_third_party_library",
"@some_external_dep/dep",
]
)

Here's the problem:
The above bazel invocation actually produces *many* artifacts, not just toplevel_target because it has dependencies. All of these artifacts are needed to make the final build product work. There isn't a giant .a file that we can just link against (I have tried this approach when the library doesn't have any dependencies and it works fine). Somehow we need to gather up all of the artifacts from the transitive dependencies and either pass them to cmake or somehow stuff them all into a single .a file that cmake can use.
Naively, I can use cquery to find my transitive dependencies, munge through bazel-bin to find the appropriate files, then stuff them all into the archiver (or something). This seems pretty brittle though - bazel should already have all of this information when it's performing the build (and of course bazel utilizes this information when it tries to link a binary or .so). Ideally, I would be able to write a skylark rule which does this for me, otherwise I'm stuck doing what I describe above. Any better ideas? Pointers to similar work? Being able to use bazel with other build systems is probably something that someone else has done in the past?

My only other thought would be to make a dummy binary target that depends on toplevel_target and then use the resulting params file (which is generated for the final link command) for my own purposes. This seems fairly brittle as well.

Thoughts?

Jim

jim...@google.com

unread,
Mar 27, 2018, 1:37:06 AM3/27/18
to bazel-discuss

For posterity:

It seems this problem has been encountered elsewhere:
https://github.com/bazelbuild/bazel/issues/1920

Public design doc that discusses this problem
https://docs.google.com/document/d/1-tv0_79zGyBoDmaP_pYWaBVUwHUteLpAs90_rUl-VY8/edit#heading=h.jwrigiapdkr2

jim...@google.com

unread,
Apr 4, 2018, 6:12:58 PM4/4/18
to bazel-discuss
For more posterity:

I haven't done extensive testing, but AFAICT I was able to write a Skylark rule that could collect all of the transitive deps and put them into a single .a file.

This can be done by using an aspect that propagates along deps and collects the files field from target (https://docs.bazel.build/versions/master/skylark/lib/Target.html) and passes the transitive deps upward via a custom provider. The resulting list of .a files can be output into an MRI script which is then ingested by ar (I couldn't get a thin archive to work).

The aspect example in the bazel example rules is a good place to start IMO.

Marcel Hlopko

unread,
Apr 11, 2018, 3:03:23 AM4/11/18
to jim...@google.com, Carmi Grushko, bazel-discuss
Hi Jim,
sorry for the late reply.

1. email:
Bazel cannot make transitive static library (https://github.com/bazelbuild/bazel/issues/1920), the plan is that it will be able to by the end of 2018. It can create transitive shared library if you use cc_binary with linkshared = 1. Also side note, do not consume outputs of cc_library, they are implementation detail and can (and do) change. Only use cc_binary to produce artifacts for external consumption.

That said, you might be able to write a skylark aspect (https://docs.bazel.build/versions/master/skylark/aspects.html) that will collect all transtive objects and create a static library from that. Just beware that the existing skylark api to the C++ rules will be replaced by a better one in Q3 probably.

2. email:
I'm Captain Obvious with #1920 :)

3. email:
I'm Captain Obvious with aspects :))

+Carmi Grushko since he's experimenting with bazel calling cmake (the reverse direction than you did).


--
You received this message because you are subscribed to the Google Groups "bazel-discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email to bazel-discus...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/bazel-discuss/094ba039-df51-49b0-bf3e-25bf13fcacf7%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.


--
Marcel Hlopko | Software Engineer | hlo...@google.com | 

Google Germany GmbH | Erika-Mann-Str. 33  | 80636 München | Germany | Geschäftsführer: Geschäftsführer: Paul Manicle, Halimah DeLaine Prado | Registergericht und -nummer: Hamburg, HRB 86891
Reply all
Reply to author
Forward
0 new messages