Search code examples
opencvbazel

How to use Bazel to build project uses OpenCV


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

  • 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.