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

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.

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)

Bazel how to add prefix to dependency?

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.

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",
],
)

Bazel cc_library dependency on other cc_library when each compile with a different crosstool

I have a code generator tool that generates C/C++ code. This code generator tool is compiled with crosstool1. The generated C/C++ code needs to be compiled with crosstool2.
So the actions are:
Using Crosstool1 compile 'code_generator'.
Execute 'code_generator' and generate 'generated_code.cpp'
Using Crosstool2 compile 'generated_code.cpp'
Is it possible to make a cc_library() determine the crosstool to use? I saw that Skylark rules now allow a 'toolchains' parameter which I'm not sure how this is used, also I do not want to do the heavy lifting of C/C++ compiling bare bone with Skylark.
Is there an example of using a proper Host Crosstool and Target Crosstool except for the Tenserflow example? I get a headache each time I read it :D
Assume //crosstool1:toolchain is a label for cc_toolchain_suite rule describing first crosstool, //crosstool2:toolchain is a label for cc_toolchain_suite for second crosstool, and the build file for the project is:
cc_binary(
name = "generator",
srcs = [ "main.cc" ],
)
genrule(
name = "generate",
outs = ["generated.cc"],
cmd = "$(location :generator) > $#",
tools = [":generator"],
)
cc_binary(
name = "generated",
srcs = [ "generated.cc" ],
)
Then running:
bazel build --host_crosstool_top=//crosstool1:toolchain --crosstool_top=//crosstool2:toolchain :generated
will do exactly what you describe, it will use crosstool1 to build :generator, and crosstool2 to build generated. Genrules use host configuration by default, so all should just work.

OSX Tensorflow + Opencv: Symbol Not Found, expected in Flat Namespace

I use OSX10.12, I try to use OpenCV in tensorflow, I use the first method which is mentioned in this question.
I build my code successfully but there are some questions as following when I execute it:
dyld: lazy symbol binding failed: Symbol not found: __ZN2cv6String8allocateEm
Referenced from: /Users/philokey/Practice/github/tensorflow/./bazel-bin/tensorflow/examples/test_cv/test_cv
Expected in: flat namespace
The build file is as following:
cc_binary(
name = "test_cv",
srcs = [
"test_cv.cc",
],
deps = [
"#opencv//:opencv",
],
)
How can I solve this problem?
You need to make sure you updated following files under tensorflow directory, correctly:
in WORKSPACE - (./tensorflow/tensorflow/WORKSPACE) add following:
new_local_repository(
name = "opencv",
path = "/usr/local/",
build_file = "opencv.BUILD",
)
opencv.BUILD - (./tensorflow/tensorflow/opencv.BUILD) add following:
cc_library(
name = "opencv",
srcs = glob(["lib/*.dylib*"]), <<<<<<<
hdrs = glob(["include/**/*.hpp"]),
includes = ["include"],
visibility = ["//visibility:public"],
linkstatic = 1,
)
[NOTE] for different operating systems, different dynamic libraries are created, example:
linux -> *.so,
windows -> *.dll, and
on OSx -> *.dylib
Even then if you face any problems please set DYLD_PRINT_LIBRARY environment variable to check if the correct libraries are linked, at times different versions of libraries may keep you busy.

Resources