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
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
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.
--
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.