How to use Bazel to build project uses OpenCV [closed]
What is the best way to build C++ code that uses the OpenCV library using Bazel? I.e., what would the BUILD rules look like?
How should be the WORKSPACE
and BUILD
files look like in order to compile the following code using bazel:
#include "opencv2/opencv.hpp"
#include "iostream"
int main(int, char**) {
using namespace cv;
VideoCapture cap(0);
Mat save_img; cap >> save_img;
if(save_img.empty())
{
std::cerr << "ERROR >> Something is wrong with camera..." << std::endl;
}
imwrite("test.jpg", save_img);
return 0;
}
Solution 1:
There are a couple of options. The easiest way is probably to install locally in the way the OpenCV site recommends:
git clone https://github.com/Itseez/opencv.git
cd opencv/
mkdir build install
cd build
cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/path/to/opencv/install ..
make install
Then add the following to your WORKSPACE file:
new_local_repository(
name = "opencv",
path = "/path/to/opencv/install",
build_file = "opencv.BUILD",
)
Create opencv.BUILD
in the same directory as WORKSPACE with the following:
cc_library(
name = "opencv",
srcs = glob(["lib/*.so*"]),
hdrs = glob(["include/**/*.hpp"]),
includes = ["include"],
visibility = ["//visibility:public"],
linkstatic = 1,
)
Then your code can depend on @opencv//:opencv
to link in the .so's under lib/ and reference the headers under include/.
However, this isn't very portable. If you want a portable solution (and you're feeling ambitious), you could add the OpenCV git repo to your workspace and download & build it. Something like:
# WORKSPACE
new_git_repository(
name = "opencv",
remote = "https://github.com/Itseez/opencv.git",
build_file = "opencv.BUILD",
tag = "3.1.0",
)
And make opencv.BUILD something like:
cc_library(
name = "core",
visibility = ["//visibility:public"],
srcs = glob(["modules/core/src/**/*.cpp"]),
hdrs = glob([
"modules/core/src/**/*.hpp",
"modules/core/include/**/*.hpp"]
) + [":module-includes"],
)
genrule(
name = "module-includes",
cmd = "echo '#define HAVE_OPENCV_CORE' > $@",
outs = ["opencv2/opencv_modules.hpp"],
)
...
Then your code could depend on more specific targets, e.g., @opencv//:core
.
As a third option, you declare both cmake and OpenCV in your WORKSPACE file and use a genrule to run cmake on OpenCV from within Bazel.
Solution 2:
Here is an up2date solution that works with the current set of bazel
(v3.1.0). In this little project i wanted to build a C++ program that depends on the newest openCV
release (4.3.0), but only on a selected set of modules (core,highgui,imgcodecs,imgproc).
No local installed openCV
required, bazel
loads the needed files from github (although it works even when there is an old version of openCV
installed):
Content of /WORKSPACE
file:
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
all_content = """filegroup(name = "all", srcs = glob(["**"]), visibility = ["//visibility:public"])"""
http_archive(
name = "opencv",
build_file_content = all_content,
strip_prefix = "opencv-4.3.0",
urls = ["https://github.com/opencv/opencv/archive/4.3.0.zip"],
)
http_archive(
name = "rules_foreign_cc",
strip_prefix = "rules_foreign_cc-master",
url = "https://github.com/bazelbuild/rules_foreign_cc/archive/master.zip",
)
load("@rules_foreign_cc//:workspace_definitions.bzl", "rules_foreign_cc_dependencies")
rules_foreign_cc_dependencies()
Content of /BUILD
file:
load("@rules_foreign_cc//tools/build_defs:cmake.bzl", "cmake_external")
cmake_external(
name = "opencv",
cmake_options = [
"-GNinja",
"-DBUILD_LIST=core,highgui,imgcodecs,imgproc",
],
lib_source = "@opencv//:all",
make_commands = [
"ninja",
"ninja install",
],
out_include_dir = "include/opencv4",
shared_libraries = [
"libopencv_core.so",
"libopencv_highgui.so",
"libopencv_imgcodecs.so",
"libopencv_imgproc.so",
],
visibility = ["//visibility:public"],
)
And finally, your target that depends on opencv
, in my case a file /opencv/BUILD
:
cc_binary(
name = "opencv",
srcs = ["opencv.cpp"],
data = [
"LinuxLogo.jpg",
"WindowsLogo.jpg",
],
deps = ["//:opencv"],
)
If you want to try it out, here is the rest: blackliner/automata
git clone https://github.com/blackliner/automata.git
cd automata
bazel build ...
Solution 3:
I succeed with @kristina's first option.
-
Install opencv:
git clone https://github.com/Itseez/opencv.git cd opencv/ mkdir build install cd build cmake -D CMAKE_BUILD_TYPE=Release -D CMAKE_INSTALL_PREFIX=/usr/local .. make install
-
Change WORKSPACE file (at tensorflow/WORKSPACE cloned from github)
new_local_repository( name = "opencv", path = "/usr/local", build_file = "opencv.BUILD", )
-
Make opencv.BUILD file at the same place as WORKSPACE file:
cc_library( name = "opencv", srcs = glob(["lib/*.so*"]), hdrs = glob(["include/**/*.hpp"]), includes = ["include"], visibility = ["//visibility:public"], linkstatic = 1, )
You may have to config the opencv libs path:
a. Make sure you have /etc/ld.so.conf.d/opencv.conf file with content:
/usr/local/lib
b. Run the command:
sudo ldconfig -v