Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Bazel to build project uses OpenCV [closed]

Tags:

opencv

bazel

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;
}

like image 628
John Zhang Avatar asked Jan 25 '16 02:01

John Zhang


3 Answers

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.

like image 177
kristina Avatar answered Sep 21 '22 09:09

kristina


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 ...
like image 21
Florian Berchtold Avatar answered Sep 18 '22 09:09

Florian Berchtold


I succeed with @kristina's first option.

  1. 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
    
  2. Change WORKSPACE file (at tensorflow/WORKSPACE cloned from github)

    new_local_repository(
    
    name = "opencv",
    
    path = "/usr/local",
    
    build_file = "opencv.BUILD",
    
    )
    
  3. 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,
    
    )
    
  4. 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
like image 33
C. Ha Avatar answered Sep 20 '22 09:09

C. Ha