Bazel how to add prefix to dependency? - bazel

I have two libraries, libA and libB.
both have their own BUILD files.
libA.BUILD looks like this:
#libA.BUILD file
cc_library(
name "libA_foo",
srcs = ["foo.cc"],
hdrs = ["foo.h"],
)
cc_library(
name "libA_bar",
srcs = ["bar.cc"],
hdrs = ["bar.h"],
deps = [":libA_foo"],
)
now I want to include some headers of libA in a cc_library in libB
I can do that like so
#libB.BUILD file
cc_library(
name "libB_qux",
srcs = ["qux.cc"],
hdrs = ["qux.h"],
deps = ["#libA//:libA_foo"]
)
in qux.cc I would like to include the headers of libA_foo however as #include "libA/foo.h" rather than just #include "foo.h"
I know that I could add a include_prefix = "libA" to libA_foo, but then it would mess up the includes of other libraries in libA and I don't want to make changes to libA.
can I somehow declare the prefix when listing the dependency instead?

Try this:
Use include_prefix to add a prefix to the exported headers of //libA:libA_foo.
Add foo.h in the srcs of //libA:libA_foo so that they are available without the prefix.
Add foo.h in the srcs of //libA:libA_bar as well.
Example:
cc_library(
name "libA_foo",
srcs = ["foo.cc", "foo.h"],
hdrs = ["foo.h"],
include_prefix = "libA",
)
cc_library(
name "libA_bar",
srcs = ["bar.cc", "foo.h"],
hdrs = ["bar.h"],
deps = [":libA_foo"],
)
From the cc_library documentation:
A .h file will not be compiled, but will be available for inclusion by sources in this rule. Both .cc and .h files can directly include headers listed in these srcs or in the hdrs of any rule listed in the deps argument.
Meaning, the foo.h in the srcs will be accessible by libA_foo, and the foo.h in the hdrs will be accessible by other rules with the include prefix.

Related

With Bazel how do I make part of one genrules' source files (e.g. header files) available to another genrule?

Maybe this is a no-brainer and I just didn't get the concept yet.
I have a genrule, basically wrapping an existing make/config workflow to integrate it into a Bazel-based build configuration. In my example I'd like to build openssl, and then (with the same approach) some library depending on openssl, say xmlsec1
My (shortened) rule for openssl looks like this:
genrule(
name = "build",
visibility = ["//visibility:public"],
srcs = glob(["**/*"], exclude=["bazel-*"]),
outs = [
"libssl.a",
"libcrypto.a",
"include/openssl/opensslconf.h",
],
cmd = """
OUT_DIR="$$(realpath $(RULEDIR))"
pushd "$$(dirname $(location config))"
./config
make
make -j6 DESTDIR="$$OUT_DIR" install_sw install_ssldirs
"""
)
This builds fine and $OUT_DIR contains all files I need to build against openssl
I'd now like to create another genrule building xmlsec1 which needs the path to openssls header files.
Now if I want to access a header, say include/opensslv.h it won't be part of #openssl//:builds artifacts since I didn't explicitly listing it in outs. But doing so results in
ERROR: Traceback (most recent call last):
File "/bla/blubb/.cache/bazel/_bazel_me/f68917ddf601b6533d6db04f8101d580/external/openssl/BUILD.bazel", line 37, column 8, in <toplevel>
genrule(
Error in genrule: rule 'build' has file 'include/openssl/opensslv.h' as both an input and an output
which is correct of course, but what can I do about it?
Removing those header files from srcs doen't work neither, since they wouldn't be available at build time.
One way would be to make install openssl to some destination directory, listing each of the dozens of header files explicitly and using that prefix in all dependent projects. But that doesn't feel right.
What's the recommended way to pass lists of files from one genrule to another?
xmlsec1 could have include/openssl/opensslv.h in its own srcs directly. The build genrule shouldn't really need include/openssl/opensslv.h in its outs both because that would be a circular dependency as bazel said, and because the genrule doesn't really build that file: it already exists on disk (I assume it's getting captured by the glob())
There may be nicer way to organize the library though, something like this:
genrule(
name = "build_openssl",
visibility = ["//visibility:private"],
outs = [
"libssl.a",
"libcrypto.a",
"include/openssl/opensslconf.h",
],
.....,
)
cc_library(
name = "openssl",
srcs = [":build_openssl"],
hdrs = [
"include/openssl/opensslv.h",
# other headers that openssl should provide
],
)
then your other rules can depend on the openssl cc_library and get both the .a files and the header files. (I have not tested this though)

Build EFI Application with Bazel

I am trying to build a simple EFI app with Bazel on Linux, which apparently means I need to use a cross compiler: x86_64-w64-mingw32-gcc. Right now I have:
cc_binary(
name = "boot-loader",
srcs = ["efi-main.c"],
copts = ["-ffreestanding"],
linkopts = ["-nostdlib", "-dll", "--subsystem 10", "-e efi_main"],
deps = ["#efi//:headers"],
)
From my own research it seems that a toolchain configuration could work, but I only want this single package to be cross compiled.
What I would like to have is:
efi_binary(
name = "boot-loader",
srcs = ["efi-main.c"],
copts = ["-ffreestanding"],
linkopts = ["-nostdlib", "-dll", "--subsystem 10", "-e efi_main"],
deps = ["#efi//:headers"],
)
But I cannot figure out how I could create the efi_binary rule easily. Ideally, I would like to duplicate the cc_binary rule and change it's compiler and linker, but that's not a feature.
Is there anything that I've missed?

How to include an up-level reference in Bazel?

I'm new to Bazel (version 0.28.1).
How do you include a header file in another directory? The directory structure below is a representation of my problem.
.
├── WORKSPACE
├── src
│   ├── Makefile
│   ├── hellomake.c
│   ├── hellofunc.c
│   └── BUILD
└── include
└── hellomake.h
The tree builds fine with the Makefile in src. However, using Make I'm able to reference the include file with "-I ../include". When I try to build the same tree with Bazel I am unable to successfully include the header file hellomake.h. Obviously, an up-level references, '..', does not work.
My BUILD file:
cc_library (
name = "hellomake",
srcs = ["hellomake.c"],
hdrs = ["//include/hellomake.h"],
copts = ["-I include"],
)
cc_library (
name = "hellofunc",
srcs = ["hellofunc.c"],
hdrs = ["//include/hellomake.h"],
copts = ["-I include"],
)
cc_binary(
name = "hello",
deps = [ ":hellomake", ":hellofunc", ],
)
From '.' my command is:
bazel build //src/hello
Direct answer would be, you cannot just reach across package boundaries. Package is each node in workspace directory tree that has its BUILD file, so the minimal change would be to make your tree with sources and headers one package (move BUILD up by one directory) and heave it read like this instead:
cc_library (
name = "hellomake",
srcs = ["src/hellomake.c"],
hdrs = ["include/hellomake.h"],
copts = ["-I include"],
)
cc_library (
name = "hellofunc",
srcs = ["src/hellofunc.c"],
hdrs = ["include/hellomake.h"],
copts = ["-I include"],
)
cc_binary(
name = "hello",
deps = [ ":hellomake", ":hellofunc", ],
)
You could then build:
bazel build //:hello
But I suspect there is a bit more to unpack here. Based on linking order (deps) of cc_binary rule, I suspect hellomake.c actually isn't as much a library, but a source of your binary with it's own main() and hence:
it could be directly declared as such
and hellomake.h is actually interface of hellofunc.c and should be named accordingly
Based on that assumption, the BUILD file would now look like this:
cc_library (
name = "hellofunc",
srcs = ["src/hellofunc.c"],
hdrs = ["include/hellofunc.h"],
includes = ["include"],
)
cc_binary (
name = "hello",
srcs = ["src/hellomake.c"],
deps = [":hellofunc"],
)
Now if you actually wanted to use sources and headers as separate packages, you could do that, but you'd have to declare the header file(s) as a cc_library in //include package by putting this in ./include/BUILD:
cc_library (
name = "hellofunc_hdr",
hdrs = ["hellofunc.h"],
includes = ["."],
visibility = ["//src:__pkg__"],
)
And then in //src (./src/BUILD) you could say:
cc_library (
name = "hellofunc",
srcs = ["hellofunc.c"],
deps = ["//include:hellofunc_hdr"],
)
cc_binary (
name = "hello",
srcs = ["hellomake.c"],
deps = [":hellofunc"],
)
With that you could run bazel build //src:hello.
Admittedly, this looks a bit odd and such packaging does not seem to convey much meaningful structure, so perhaps we could end up having a hellofunc (library) as one (func) package and hellomake as source for our binary as another (hello). The tree would look like this:
.
├── WORKSPACE
├── func
│   ├── BUILD
│   ├── hellofunc.c
│   └── hellofunc.h
└── hello
├── BUILD
└── hellomake.c
And the BUILD file in ./func/ could be:
cc_library (
name = "func",
srcs = ["hellofunc.c"],
hdrs = ["hellofunc.h"],
includes = ["."],
visibility = ["//hello:__pkg__"],
)
With the in ./hello/:
cc_binary (
name = "hello",
srcs = ["hellomake.c"],
deps = ["//func"],
)
We could then run build bazel //hello

How can I place a data dependency of a cc_library's shared object in the same directory as the shared object?

I have a cc_library() of a shared object (libname.so), and it requires a data file, data.xml, in the same directory as itself.
Bazel *.runfiles/ places the data file in the same relative path as in the software repository, but I want it as above. Thank you!
I've tried:
cc_library(
name = "libname",
srcs = ["libname.so"],
data = ["data.xml"],
)
I expected data.xml and libname.so to be in the same path (bazel-bin/proj/program.runfiles/repo/_solib_k8/_U_S_Slibname/) but the data file is in a directory relative to the project root. (bazel-bin/proj/program.runfiles/repo/src/data.xml)
Best solution yet, runfiles executable works, but bazel run program fails to dynamically load libraries.
1) Group shared libraries and data files together:
filegroup(
name = "libs_and_data",
# This creates *.runfiles/.../path/to/data/files, for runpath
data =glob(["*.so*"]) + glob(["*.xml"]),
)
2) Manually build-link the shared libraries from their original folder,
3) Manually set the runpath to the runfiles data dependency directory that contains the shared libraries and data files.
cc_library(
name = "lib",
data = [
# Shared objects are data, not library deps, to avoid _solib in RUNPATH
"//path/to/libs_and_data",
],
linkopts = [
# Explicit build-linking of libraries, because we are avoiding cc_library()
"-lLibrary1",
"-lLibrary2",
"-Lpath/to/libs",
# Point dynamic loader to runfiles location of libraries and datafiles
# Only the *.runfiles executable will successfully load libraries
"-Wl,-rpath='../../../path/to/libs'",
],
deps = [
"//path/to/headers",
],
)

How to add *.i files in bazel BUILD script file

I want to add features2d into the build script for building opencv with bazel. Here is the build script which this module to be added.
I was able to add a few other modules except for features2d because inside this module it consists of some *.i files (https://github.com/opencv/opencv/tree/2.4.13.2/modules/features2d/src)
Problem is that there is no rule so as to include *.i in the src directory.
cc_library(
name = "features2d",
srcs = glob(["modules/features2d/src/**/*.cpp"]),
hdrs = glob([
"modules/features2d/src/**/*.hpp",
"modules/features2d/src/**/*.h",
"modules/features2d/include/**/*.hpp",
"modules/features2d/include/**/*.h"
]) + [
":module_includes",
],
includes = [
"modules/features2d/include",
],
visibility = ["//visibility:public"],
deps = [
":imgproc",
":flann",
],
)
This is the error is trowing:
#opencv2//:modules/features2d/src/generated_32.i' does not produce any cc_library srcs files (expected .cc, .cpp, .cxx, .c++, .C, .c, .h, .hh, .hpp, .hxx, .inc, .S, .s, .asm, .a, .lib, .pic.a, .lo, .pic.lo, .so, .dylib, .dll, .o or .pic.o).
If anybody has an idea how this can be done, really helpful.

Resources