如何在使用 Bazel(版本 0.25.2)构建的 C++ 项目中使用 Eigen?我喜欢使用
http_archive
或 git_repository
获取特征依赖关系。
我尝试过以下方法:
main.cpp
#include <iostream>
#include <Eigen/Dense>
using Eigen::MatrixXd;
int main() {
MatrixXd m(2, 2);
m(0, 0) = 3;
m(1, 0) = 2.5;
m(0, 1) = -1;
m(1, 1) = m(1, 0) + m(0, 1);
std::cout << m << std::endl;
}
工作空间
workspace(name = "EigenDemo")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
# Eigen
http_archive(
name = "eigen",
build_file = "//:eigen.BUILD",
sha256 = "3a66f9bfce85aff39bc255d5a341f87336ec6f5911e8d816dd4a3fdc500f8acf",
url = "https://bitbucket.org/eigen/eigen/get/c5e90d9.tar.gz",
)
构建
cc_binary(
name = "EigenDemo",
srcs = ["main.cpp"],
deps = [
"@eigen",
],
)
特征.BUILD
# Copyright 2017 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS-IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
package(
default_visibility = ["//visibility:public"],
)
cc_library(
name = "eigen",
hdrs = glob(
["Eigen/**"],
exclude = [
"Eigen/src/OrderingMethods/Amd.h",
"Eigen/src/SparseCholesky/**",
"Eigen/Eigen",
"Eigen/IterativeLinearSolvers",
"Eigen/MetisSupport",
"Eigen/Sparse",
"Eigen/SparseCholesky",
"Eigen/SparseLU",
],
),
defines = [
"EIGEN_MPL_ONLY",
"EIGEN_NO_DEBUG",
],
includes = ["."],
)
错误输出:
INFO: Analysed target //:EigenTest (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
ERROR: /BazelDemos/EigenDemo/BUILD:1:1: C++ compilation of rule '//:EigenTest' failed (Exit 1) gcc failed: error executing command /usr/bin/gcc -U_FORTIFY_SOURCE -fstack-protector -Wall -Wunused-but-set-parameter -Wno-free-nonheap-object -fno-omit-frame-pointer '-std=c++0x' -MD -MF ... (remaining 40 argument(s) skipped)
Use --sandbox_debug to see verbose messages from the sandbox
main.cpp:2:10: fatal error: Eigen/Dense: No such file or directory
#include <Eigen/Dense>
^~~~~~~~~~~~~
compilation terminated.
Target //:EigenTest failed to build
Use --verbose_failures to see the command lines of failed build steps.
INFO: Elapsed time: 0.258s, Critical Path: 0.10s
INFO: 0 processes.
FAILED: Build did NOT complete successfully
strip_prefix
在 WORKSPACE
文件中丢失:
workspace(name = "EigenDemo")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
# Eigen
http_archive(
name = "eigen",
build_file = "//:eigen.BUILD",
sha256 = "3a66f9bfce85aff39bc255d5a341f87336ec6f5911e8d816dd4a3fdc500f8acf",
url = "https://bitbucket.org/eigen/eigen/get/c5e90d9.tar.gz",
strip_prefix="eigen-eigen-c5e90d9e764e"
)
Tensorflow 不再使用单独的 eigen.BUILD 文件。相反,您可以将以下内容放入 WORKSPACE 文件中(无需单独的 eigen.BUILD 文件):
http_archive(
name = "com_gitlab_libeigen_eigen",
sha256 = "0215c6593c4ee9f1f7f28238c4e8995584ebf3b556e9dbf933d84feb98d5b9ef",
strip_prefix = "eigen-3.3.8",
urls = [
"https://gitlab.com/libeigen/eigen/-/archive/3.3.8/eigen-3.3.8.tar.bz2",
],
build_file_content =
"""
# TODO(keir): Replace this with a better version, like from TensorFlow.
# See https://github.com/ceres-solver/ceres-solver/issues/337.
cc_library(
name = 'eigen',
srcs = [],
includes = ['.'],
hdrs = glob(['Eigen/**']),
visibility = ['//visibility:public'],
)
"""
)
(正如你可能从 TODO 中看出的那样,我从 Ceres 上撕下了这个。)
我用的是最新的
rules_foreign_cc
。有一个新的 cmake 规则。这是我所拥有的:
工作空间
workspace(name="bazelt")
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
http_archive(
name = "rules_foreign_cc",
sha256 = "6041f1374ff32ba711564374ad8e007aef77f71561a7ce784123b9b4b88614fc",
strip_prefix = "rules_foreign_cc-0.8.0",
url = "https://github.com/bazelbuild/rules_foreign_cc/archive/0.8.0.tar.gz",
)
load("@rules_foreign_cc//foreign_cc:repositories.bzl", "rules_foreign_cc_dependencies")
# This sets up some common toolchains for building targets. For more details, please see
# https://bazelbuild.github.io/rules_foreign_cc/0.8.0/flatten.html#rules_foreign_cc_dependencies
rules_foreign_cc_dependencies()
_ALL_CONTENT = """\
filegroup(
name = "all_srcs",
srcs = glob(["**"]),
visibility = ["//visibility:public"],
)
"""
http_archive(
name="eigen",
build_file_content = _ALL_CONTENT,
strip_prefix = "eigen-3.4",
urls=["https://gitlab.com/libeigen/eigen/-/archive/3.4/eigen-3.4.tar.bz2"],
sha256 = "a6f7aaa7b19c289dfeb33281e1954f19bf2ba1c6cae2c182354d820f535abef8",
)
建造
load("@rules_foreign_cc//foreign_cc:defs.bzl", "cmake")
cmake(
name = "eigen",
cache_entries = {
"CMAKE_C_FLAGS": "-fPIC",
},
lib_source = "@eigen//:all_srcs",
out_headers_only = True,
includes = ["eigen3/",],
install = True,
)
cc_binary(
name = "bazelt",
srcs = [
"main.cpp",
],
visibility = ["//visibility:public"],
deps = [":eigen",],
)
注意 cmake 规则中的
"includes"
参数。默认情况下,cmake 规则会将头文件放入缓存中的“include”目录中。所以你所需要的只是相对路径。
还有main.cpp
#include <iostream>
#include <Eigen/Dense>
int main()
{
Eigen::MatrixXd m = Eigen::MatrixXd::Random(4,6);
std::cout << m << '\n';
return 0;
}
依赖于
http_archive
的方法是有效的,但自从发布答案以来,Bazel 已经使这变得更加方便。这是一个 MWE,所有文件都位于同一(项目根)目录中:
模块.bazel:
# Check the url below for the most recent available version:
# https://registry.bazel.build/modules/eigen
bazel_dep(name = "eigen", version = "3.4.0")
构建.bazel:
cc_binary(
name = "eigen_mwe",
deps = ["@eigen"],
srcs = ["eigen_demo.cpp"],
)
eigen_demo.cpp:
#include <iostream>
#include <Eigen/Dense>
int main() {
Eigen::MatrixXd m(2, 2);
m(0, 0) = 3;
m(1, 0) = 2.5;
m(0, 1) = -1;
m(1, 1) = m(1, 0) + m(0, 1);
std::cout << m << std::endl;
}
运行
bazel run //:eigen_mwe
应打印
3 -1
2.5 1.5