I have a project for a plugin in C/C++ where I have different implementations and I would like to be able to select which implementation to use when building.
WORKSPACE
plugin/
BUILD
plugin.c
plugin.h
plugin_impl1/
BUILD
...
plugin_impl2/
BUILD
...
plugin_impl1/BUILD:
cc_library(
name = "plugin_impl1"
srcs = [...]
hdrs = [...]
)
plugin_impl2/BUILD:
cc_library(
name = "plugin_impl2"
srcs = [...]
hdrs = [...]
)
I want to know how to write plugin/BUILD so that I could write something like:
bazel build //plugin --which plugin_impl2
The executable name should always be the same so having multiple rules with different target names (for plugin) is not an option.
Related
I am working on extending a project using bazel to build. However, one of my thrid_party dependency relying on a dynamic linked QT library. And I had a hard time linking it.
My project base is envpool, and I am using procgen as my third-party dependency. However, procgen relies on a series of QT library.
My approachs so far:
In the WorkSpace file, I specify the local directory of the qt library. (I am working on a new EC2 instance of Ubuntu 20.04 LTS on amazon cloud, and install qt5 and other base tools)
// download the github project
maybe(
http_archive,
name = "procgen",
sha256 = "8d443b7b8fba44ef051b182e9a87abfa4e05292568e476ca1e5f08f9666a1b72",
strip_prefix = "procgen-0.10.7/procgen/src/",
urls = [
"https://github.com/openai/procgen/archive/refs/tags/0.10.7.zip"
]
build_file = "//third_party/procgen:procgen.BUILD",
)
new_local_repository(
name = "qt",
path = "/usr/include/x86_64-linux-gnu/qt5", // I check indeed the header files are there
build_file = "BUILD.qt"
)
And the BUILD.qt file is
cc_library(
name = "qt_core",
hdrs = glob(["QtCore/**"]),
includes = ["."],
linkopts = [
"-lQt5Core",
],
visibility = ["//visibility:public"],
)
cc_library(
name = "qt_widgets",
hdrs = glob(["QtWidgets/**"]),
includes = ["."],
deps = [":qt_core"],
linkopts = [
"-lQt5Widgets",
],
visibility = ["//visibility:public"],
)
cc_library(
name = "qt_gui",
hdrs = glob(["QtGui/**"]),
includes = ["."],
deps = [":qt_core"],
linkopts = [
"-lQt5Gui",
],
visibility = ["//visibility:public"],
)
And the BUILD file for the procgen is
package(default_visibility = ["//visibility:public"])
cc_library(
name = "procgen",
srcs = glob(["*.cpp", "games/*.cpp"]),
hdrs = glob(["*.h"]),
deps = [
"#qt//:qt_widgets",
"#qt//:qt_gui",
"#qt//:qt_core",
]
)
However, when I use Bazel to build the project, it gives back the error that
Use --sandbox_debug to see verbose messages from the sandbox
In file included from external/procgen/games/starpilot.cpp:2:
external/procgen/games/../assetgen.h:10:10: fatal error: QColor: No such file or directory
10 | #include <QColor>
| ^~~~~~~~
compilation terminated.
I know I probably mess up the path or header file's include somewhere. For example, I am basically follow this post to include the QT library in the project, but I notice that guys use the full path "#include <qt/QTWidgets/xxxx>" instead. But I cannot change the code for "include" in the procgen.
This is the first time I use bazel, and on such a big project. Really appreciate if someone could help me out.
I put my current whole project package at here for reproducibility. You can use short-cut "sudo make bazel-build" to build it.
Best,
YJ
Given a C++ application, built with Bazel, that depends on an external, system provided shared library:
cc_binary(
name = 'app',
srcs = ['app.cpp'],
linkstatic = False,
deps = ['#my_system//:system_lib'],
)
The WORKSPACE and BUILD.my_system files:
new_local_repository(
name = 'my_system',
build_file = 'BUILD.my_system',
path = '/usr/lib/my_system/',
)
cc_import(
name = 'system_lib',
shared_library = 'system_lib.so',
visibility = ['//visibility:public'],
)
This builds, but first copies the system provided lib to the cache, and links to that:
$ ldd bazel-bin/app/app
system_lib.so => /home/erenon/bazel/proj/bazel-bin/app/../_solib_k8/_U#my_system_S_S_Csystem_Ulib___Uexternal_Smy_system/system_lib.so
[...]
If I move app to an identical system that has /usr/lib/my_system/system_lib.so, it breaks, as it misses the cache. I'd like to package app in a way that it directly links to the original .so, without the intermediate cache copy or name mangling, i.e: I'd like to achieve:
$ ldd bazel-bin/app/app
system_lib.so => /usr/lib/my_system/system_lib.so
[...]
I tried cc_import.system_provided, but that appears only work for Windows lib/dlls.
Wrap your library with another cc_library.
I can't explain why it works, but it does.
cc_library(
name = "libsystem_lib",
srcs = [ ":system_lib" ],
hdrs = ...
)
Depend on this one instead.
I'm working on a project, which depends on a third party project, let's say project E, which is a precompiled libraries. I've set a new repository_rule and invoked it in the workspace.bzl, and in the BUILD of the project E, the corresponding library rule has been set like following:
cc_library(
name = "e_lib",
srcs = [
"#e//:e_lib1",
"#e//:e_lib2",
],
hdrs = ["#e//:e_headers"],
visibility = ["//visibility:public"],
)
And the target e_lib1, e_lib2 and e_headers are defined in the file e.BUILD, and it is correctly symblo linked to the downloaded contents folder in the last part of implementation function of repository_rule.
The e.BUILD is something like:
filegroup(
name = "e_headers",
srcs = glob(["include/*"]),
visibility = ["//visibility:public"],
)
filegroup(
name = "e_lib1",
srcs = if_darwin(["lib/lib1.dylib"])
+ if_linux_x86_64(["lib/lib1.so"]),
visibility = ["//visibility:public"],
)
filegroup(
name = "e_lib2",
srcs = if_darwin(["lib/lib2.dylib"])
+ if_linux_x86_64(["lib/lib2.so"]),
visibility = ["//visibility:public"],
)
Let's say there is a header baz.h in the directory include of the project E.But during the building phase, an error, baz.h file not found, occurred when bazel tried to compile a file core.cc. The pseudocodes are something like:
// core.cc
#include "core.h"
...
// core.h
#include "im.h"
...
// im.h
#include "baz.h"
// This file doesn't have the corresponding
// .cc file since all the implementations
// are put in this header.
The dependency of these files is core.cc -> core.h -> im.h -> baz.h, and the building rule of core.cc is:
cc_library(
name = "core",
srcs = [
"core.cc",
],
hdrs = "core.h",
deps = [
"//third_party/E:e_lib"],
alwayslink = 1,
)
So is there something wrong with my BUILD file? I guess that maybe the core.cc doesn't directly depend on the e_lib, so the deps of it is actually useless. Should I build a cc_library for the im.h?
I am currently using Bazel to build a C++ project. Here is my WORKSPACE file:
cc_library(
name = "Boost",
srcs = glob(["/usr/local/lib/libboost*.so"]),
hdrs = glob(["/home/duttama/boost_1_55_0/**/*.h"]),
)
cc_library(
name = "OpenCV",
srcs = glob(["/usr/lib/x86_64-linux-gnu/libopencv*.so"]),
hdrs = glob(["/home/duttama/opencv-2.4.13/**/*.h"]),
)
cc_library(
name = "AffectivaSources",
srcs = glob(["/root/affdex-sdk/lib/*.so"]),
hdrs = glob(["/root/affdex-sdk/include/*.h"]),
)
And here is my BUILD file:
cc_binary(
name = "video-demo",
srcs = ["video-demo.cpp"],
deps = ["//lib:OpenCV",
"//lib:AffectivaSources",
"//lib:Boost",
],
)
When I run it, I get this error:
ERROR: /root/sdk-samples/WORKSPACE:17:12: Traceback (most recent call last):
File "/root/sdk-samples/WORKSPACE", line 15
cc_library(name = "AffectivaSources", srcs = ..."]), ..."]))
File "/root/sdk-samples/WORKSPACE", line 17, in cc_library
glob
name 'glob' is not defined
My question is why is it not finding the glob function. I am not sure what else to specify in the WORKSPACE file or how to import this glob function.
The WORKSPACE file is not meant for cc_binary/cc_rules; it's for defining project-wide rules such as external dependencies, and the glob function is not available in WORKSPACE files. See https://docs.bazel.build/versions/master/be/workspace.html for WORKSPACE rules.
It seems like you're importing c++ dependencies into your project: check out the new_local_repository rule here. This allows you to point to a folder in your local system. It will require you to write BUILD files containing the respective cc_library rules for each external dependency.
For example, in your WORKSPACE file:
new_local_repository(
name = "affectivalibrary",
path = "/root/affdex-sdk/",
build_file = "BUILD.affectiva",
)
and in your project, create a BUILD.affectiva:
cc_library(
name = "aff",
srcs = glob(["lib/*.so"]),
hdrs = glob(["include/*.h"]),
)
Once you've done this, you can depend on them in your BUILD files with the syntax:
cc_binary(
name = "video-demo",
srcs = ["video-demo.cpp"],
deps = ["#affectivalibrary//:aff", ...]
)
I'm also seeing that you are using absolute file paths in the srcs/hdrs attributes - glob patterns cannot be absolute. Please refer to the BUILD file target label syntax here: https://docs.bazel.build/versions/master/build-ref.html#lexi
If you're still confused, there's an example c++ project in the Bazel repository: https://github.com/bazelbuild/bazel/tree/master/examples/cpp
I am playing with LLVM and I hit an issue when trying to use JIT. I was able to build a compiler, it can be compiled, linked and it runs correctly (it compiles my toy programs). However, when I am trying to use build a JIT, it fails.
dyld: Symbol not found: __ZN4llvm11RuntimeDyld13MemoryManager6anchorEv
Referenced from: /Users/gruszczy/Projects/shwifty/./bazel-bin/_solib_darwin//liblibjit.so
Expected in: flat namespace
in /Users/gruszczy/Projects/shwifty/./bazel-bin/_solib_darwin//liblibjit.so
Abort trap: 6
I use Bazel to build everything, these are my build rules:
new_local_repository(
name = "llvm",
path = "/opt/local/libexec/llvm-4.0",
build_file= "llvm.BUILD")
cc_library(
name = "main",
srcs = glob(["lib/*.a"]),
hdrs = glob(["include/**/*.*"]),
visibility = ["//visibility:public"],
copts = ["-Iexternal/llvm/include"],
)
I use JIT in tests (I generate IR in the test then jit it, then run the method to see if it worked).
cc_library(
name = "jit",
srcs = ["jit.cc"],
hdrs = ["jit.h"],
deps = [
":ast",
":common",
"#llvm//:main"
],
copts = GENERAL_COPTS)
cc_test(
name = "codegen_test",
srcs = ["codegen_test.cc"],
deps = [
":ast",
":jit",
":lexer",
":parser",
":codegen",
"#gtest//:main",
"#llvm//:main"
],
copts = TEST_COPTS,
data = [":examples"],
size = "small"
)
Any suggestions what I might be missing?
The source of confusion is that Bazel by default links binaries statically, but tests dynamically. This makes the test-code-refactor loop faster, because changes to the test code only trigger the rebuild of the test, not the whole application. It can be disabled by setting linkstatic = 1 on codegen_test target.
As to why the symbols are not present in codegen_test when built as a shared library, that's much harder question and would need more project-specific information. But a possible solution might be to mark targets producing VMRuntimeDyld.a and VMMCJit.a as alwayslink = 1.
For the completeness, here's the link to an issue you reported on bazel.