如何使用 Bazel 构建项目使用 OpenCV
How to use Bazel to build project uses OpenCV
使用 Bazel 构建使用 OpenCV 库的 C++ 代码的最佳方法是什么?即,构建规则是什么样的?
为了使用 bazel 编译以下代码,WORKSPACE
和 BUILD
文件应该是什么样子:
#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;
}
有几个选项。最简单的方法可能是按照 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=/path/to/opencv/install ..
make install
然后将以下内容添加到您的 WORKSPACE 文件中:
new_local_repository(
name = "opencv",
path = "/path/to/opencv/install",
build_file = "opencv.BUILD",
)
使用以下内容在与 WORKSPACE 相同的目录中创建 opencv.BUILD
:
cc_library(
name = "opencv",
srcs = glob(["lib/*.so*"]),
hdrs = glob(["include/**/*.hpp"]),
includes = ["include"],
visibility = ["//visibility:public"],
linkstatic = 1,
)
然后您的代码可以依赖于 lib/ 下的 .so 中的 @opencv//:opencv
到 link 并引用 include/ 下的 headers。
但是,这不是很便携。如果您想要一个可移植的解决方案(并且您有雄心壮志),您可以将 OpenCV git 存储库添加到您的工作区并下载并构建它。类似于:
# WORKSPACE
new_git_repository(
name = "opencv",
remote = "https://github.com/Itseez/opencv.git",
build_file = "opencv.BUILD",
tag = "3.1.0",
)
并使 opencv.BUILD 类似于:
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"],
)
...
那么您的代码可以依赖于更具体的目标,例如 @opencv//:core
。
作为第三种选择,您在 WORKSPACE 文件中同时声明 cmake 和 OpenCV,并在 Bazel 中对 OpenCV 使用 genrule 运行 cmake。
@kristina 的第一个选项我成功了。
安装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
更改 WORKSPACE 文件(在 tensorflow/WORKSPACE 从 github 克隆)
new_local_repository(
name = "opencv",
path = "/usr/local",
build_file = "opencv.BUILD",
)
在与 WORKSPACE 文件相同的位置制作 opencv.BUILD 文件:
cc_library(
name = "opencv",
srcs = glob(["lib/*.so*"]),
hdrs = glob(["include/**/*.hpp"]),
includes = ["include"],
visibility = ["//visibility:public"],
linkstatic = 1,
)
您可能需要配置 opencv 库路径:
一个。确保你有 /etc/ld.so.conf.d/opencv.conf 文件,内容为:
/usr/local/lib
b。 运行 命令:
sudo ldconfig -v
这是我为 OpenCV 2.4.13.2 所做的,仅 core/
。这种方法来自 opencv 源代码,它改编自@kristina 上面接受的答案。
首先是为opencv 2.4版本添加http_archive:
# OpenCV 2.4.13.2
new_http_archive(
name = "opencv2",
url = "https://github.com/opencv/opencv/archive/2.4.13.2.zip",
build_file = "third_party/opencv2.BUILD",
strip_prefix = "opencv-2.4.13.2",
)
然后,将文件 third_party/opencv2.BUILD
添加为:
cc_library(
name = "dynamicuda",
hdrs = glob([
"modules/dynamicuda/include/**/*.hpp",
]),
includes = [
"modules/dynamicuda/include"
],
)
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",
":cvconfig",
":version_string",
],
copts = [
"-Imodules/dynamicuda/include",
],
# Note that opencv core requires zlib and pthread to build.
linkopts = ["-pthread", "-lz"],
includes = [
"modules/core/include",
],
deps = [
":dynamicuda",
],
)
genrule(
name = "module_includes",
cmd = "echo '#define HAVE_OPENCV_CORE' > $@",
outs = ["opencv2/opencv_modules.hpp"],
)
genrule(
name = "cvconfig",
outs = ["cvconfig.h"],
cmd = """
cat > $@ <<"EOF"
// JPEG-2000
#define HAVE_JASPER
// IJG JPEG
#define HAVE_JPEG
// PNG
#define HAVE_PNG
// TIFF
#define HAVE_TIFF
// Compile for 'real' NVIDIA GPU architectures
#define CUDA_ARCH_BIN ""
// NVIDIA GPU features are used
#define CUDA_ARCH_FEATURES ""
// Compile for 'virtual' NVIDIA PTX architectures
#define CUDA_ARCH_PTX ""
EOF"""
)
genrule(
name = "version_string",
outs = ["version_string.inc"],
cmd = """
cat > $@ <<"EOF"
"\n"
)
请注意,我没有在 version_string.inc
中输入任何内容。它只是一个 C++ 字符串文字,不会影响 OpenCV 的功能。如果您真的对此文件感兴趣,请参阅此 example.
在此之后,您应该能够添加依赖于 @opencv2//:core
的目标。
这是一个使用 Bazel 构建的 OpenCV 和 C++ 的简单演示:https://github.com/jcju/opencv_bazel_win
您可以在WORKSPACE中设置OpenCV路径,运行:
bazel run //src:main
这是一个适用于当前 bazel
(v3.1.0) 集的更新解决方案。在这个小项目中,我想构建一个依赖于最新 openCV
版本 (4.3.0) 的 C++ 程序,但仅依赖于一组选定的模块(core、highgui、imgcodecs、imgproc)。
无需本地安装 openCV
,bazel
从 github 加载所需的文件(尽管即使安装了旧版本的 openCV
也能正常工作):
/WORKSPACE
文件的内容:
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()
/BUILD
文件的内容:
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"],
)
最后,你的目标取决于 opencv
,在我的例子中是一个文件 /opencv/BUILD
:
cc_binary(
name = "opencv",
srcs = ["opencv.cpp"],
data = [
"LinuxLogo.jpg",
"WindowsLogo.jpg",
],
deps = ["//:opencv"],
)
如果你想尝试一下,剩下的就是:blackliner/automata
git clone https://github.com/blackliner/automata.git
cd automata
bazel build ...
使用 Bazel 构建使用 OpenCV 库的 C++ 代码的最佳方法是什么?即,构建规则是什么样的?
为了使用 bazel 编译以下代码,WORKSPACE
和 BUILD
文件应该是什么样子:
#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;
}
有几个选项。最简单的方法可能是按照 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=/path/to/opencv/install ..
make install
然后将以下内容添加到您的 WORKSPACE 文件中:
new_local_repository(
name = "opencv",
path = "/path/to/opencv/install",
build_file = "opencv.BUILD",
)
使用以下内容在与 WORKSPACE 相同的目录中创建 opencv.BUILD
:
cc_library(
name = "opencv",
srcs = glob(["lib/*.so*"]),
hdrs = glob(["include/**/*.hpp"]),
includes = ["include"],
visibility = ["//visibility:public"],
linkstatic = 1,
)
然后您的代码可以依赖于 lib/ 下的 .so 中的 @opencv//:opencv
到 link 并引用 include/ 下的 headers。
但是,这不是很便携。如果您想要一个可移植的解决方案(并且您有雄心壮志),您可以将 OpenCV git 存储库添加到您的工作区并下载并构建它。类似于:
# WORKSPACE
new_git_repository(
name = "opencv",
remote = "https://github.com/Itseez/opencv.git",
build_file = "opencv.BUILD",
tag = "3.1.0",
)
并使 opencv.BUILD 类似于:
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"],
)
...
那么您的代码可以依赖于更具体的目标,例如 @opencv//:core
。
作为第三种选择,您在 WORKSPACE 文件中同时声明 cmake 和 OpenCV,并在 Bazel 中对 OpenCV 使用 genrule 运行 cmake。
@kristina 的第一个选项我成功了。
安装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
更改 WORKSPACE 文件(在 tensorflow/WORKSPACE 从 github 克隆)
new_local_repository( name = "opencv", path = "/usr/local", build_file = "opencv.BUILD", )
在与 WORKSPACE 文件相同的位置制作 opencv.BUILD 文件:
cc_library( name = "opencv", srcs = glob(["lib/*.so*"]), hdrs = glob(["include/**/*.hpp"]), includes = ["include"], visibility = ["//visibility:public"], linkstatic = 1, )
您可能需要配置 opencv 库路径:
一个。确保你有 /etc/ld.so.conf.d/opencv.conf 文件,内容为:
/usr/local/lib
b。 运行 命令:
sudo ldconfig -v
这是我为 OpenCV 2.4.13.2 所做的,仅 core/
。这种方法来自 opencv 源代码,它改编自@kristina 上面接受的答案。
首先是为opencv 2.4版本添加http_archive:
# OpenCV 2.4.13.2
new_http_archive(
name = "opencv2",
url = "https://github.com/opencv/opencv/archive/2.4.13.2.zip",
build_file = "third_party/opencv2.BUILD",
strip_prefix = "opencv-2.4.13.2",
)
然后,将文件 third_party/opencv2.BUILD
添加为:
cc_library(
name = "dynamicuda",
hdrs = glob([
"modules/dynamicuda/include/**/*.hpp",
]),
includes = [
"modules/dynamicuda/include"
],
)
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",
":cvconfig",
":version_string",
],
copts = [
"-Imodules/dynamicuda/include",
],
# Note that opencv core requires zlib and pthread to build.
linkopts = ["-pthread", "-lz"],
includes = [
"modules/core/include",
],
deps = [
":dynamicuda",
],
)
genrule(
name = "module_includes",
cmd = "echo '#define HAVE_OPENCV_CORE' > $@",
outs = ["opencv2/opencv_modules.hpp"],
)
genrule(
name = "cvconfig",
outs = ["cvconfig.h"],
cmd = """
cat > $@ <<"EOF"
// JPEG-2000
#define HAVE_JASPER
// IJG JPEG
#define HAVE_JPEG
// PNG
#define HAVE_PNG
// TIFF
#define HAVE_TIFF
// Compile for 'real' NVIDIA GPU architectures
#define CUDA_ARCH_BIN ""
// NVIDIA GPU features are used
#define CUDA_ARCH_FEATURES ""
// Compile for 'virtual' NVIDIA PTX architectures
#define CUDA_ARCH_PTX ""
EOF"""
)
genrule(
name = "version_string",
outs = ["version_string.inc"],
cmd = """
cat > $@ <<"EOF"
"\n"
)
请注意,我没有在 version_string.inc
中输入任何内容。它只是一个 C++ 字符串文字,不会影响 OpenCV 的功能。如果您真的对此文件感兴趣,请参阅此 example.
在此之后,您应该能够添加依赖于 @opencv2//:core
的目标。
这是一个使用 Bazel 构建的 OpenCV 和 C++ 的简单演示:https://github.com/jcju/opencv_bazel_win
您可以在WORKSPACE中设置OpenCV路径,运行:
bazel run //src:main
这是一个适用于当前 bazel
(v3.1.0) 集的更新解决方案。在这个小项目中,我想构建一个依赖于最新 openCV
版本 (4.3.0) 的 C++ 程序,但仅依赖于一组选定的模块(core、highgui、imgcodecs、imgproc)。
无需本地安装 openCV
,bazel
从 github 加载所需的文件(尽管即使安装了旧版本的 openCV
也能正常工作):
/WORKSPACE
文件的内容:
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()
/BUILD
文件的内容:
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"],
)
最后,你的目标取决于 opencv
,在我的例子中是一个文件 /opencv/BUILD
:
cc_binary(
name = "opencv",
srcs = ["opencv.cpp"],
data = [
"LinuxLogo.jpg",
"WindowsLogo.jpg",
],
deps = ["//:opencv"],
)
如果你想尝试一下,剩下的就是:blackliner/automata
git clone https://github.com/blackliner/automata.git
cd automata
bazel build ...