我想让我的 Bazel C++ 构建独立于/usr/include
、/usr/local/include
等。默认情况下,如本线程中所述,编译 C++ 程序时,其中的所有文件/usr/include
都可用,而不仅仅是标准文件。
实现这一目标的最佳方法是什么?
一种选择是将标准头文件放入 tarball 中并通过 HTTP 将其托管在某个位置,然后添加并new_http_repository
运行.gcc
-nostdinc -isysroot
该解决方案由三部分组成:
这是您需要的参考:
https://docs.bazel.build/versions/master/crosstool-reference.html https://docs.bazel.build/versions/master/tutorial/crosstool.html
这是一个特别好的教程:
https://github.com/bazelbuild/bazel/wiki/Yet-Another-CROSSTOOL-Writing-Tutorial
还有一些教程,我不知道它们是如何最新的:
https://github.com/bazelbuild/bazel/wiki/About-the-CROSSTOOL https://github.com/bazelbuild/bazel/wiki/Building-with-a-custom-toolchain
以下是我如何使用 GCC 在 Linux 上实现此功能:
创建一个新工作区,其中包含虚拟 cc_binary 规则。
mkdir /tmp/bar && cd /tmp/bar
touch WORKSPACE
echo "cc_binary(name='x',srcs=['x.cc'])" > BUILD
echo -e "#include <stdio.h>\nint main(void) { return 0; }" > x.cc
Run Code Online (Sandbox Code Playgroud)构建虚拟目标。
bazel build //:x
Run Code Online (Sandbox Code Playgroud)
由于它是 cc_* 规则,Bazel 将初始化 C++ 工具链。这包括自动生成 CROSSTOOL 文件。这是一个描述编译器接口的文本文件,以便 Bazel 知道如何与其对话。
为您的自定义 crosstool 创建一个包,将自动生成的 CROSSTOOL 和 BUILD 文件复制到其中。
mkdir /tmp/bar/my_toolchain
touch /tmp/bar/my_toolchain/WORKSPACE
cat $(bazel info output_base)/external/local_config_cc/CROSSTOOL > /tmp/bar/my_toolchain/CROSSTOOL
cat $(bazel info output_base)/external/local_config_cc/BUILD > /tmp/bar/my_toolchain/BUILD
Run Code Online (Sandbox Code Playgroud)
我们将使用自动生成的文件作为模板开始。
将外部存储库规则添加到 WORKSPACE 文件。
echo "local_repository(name='my_toolchain', path='/tmp/bar/my_toolchain')" >> WORKSPACE
Run Code Online (Sandbox Code Playgroud)
这样您就可以通过 Bazel 构建标签引用您的自定义工具链。
尝试使用您的自定义交叉工具。
bazel build --crosstool_top=@my_toolchain//:toolchain //:x
Run Code Online (Sandbox Code Playgroud)
由于它与自动生成的相同,因此构建应该成功。
从自定义 CROSSTOOL 中的“本地”工具链编辑系统标头路径。
注意:您可能需要编辑不同的工具链(如果要选择该工具链)。请参阅此处的工具链选择: https ://docs.bazel.build/versions/master/crosstool-reference.html#toolchain-selection
在文本编辑器中打开/tmp/bar/my_toolchain/CROSSTOOL
,找到“toolchain_identifier”为“local”的“toolchain”记录,注释掉其中的“cxx_builtin_include_directory”条目(注释字符为“#”)。
然后为您的工具链目录添加新的“cxx_builtin_include_directory”:
cxx_builtin_include_directory: "/tmp/bar/my_toolchain"
Run Code Online (Sandbox Code Playgroud)
您刚刚告诉 Bazel 系统标头在哪里,因此当它验证标头包含时,它会知道该路径下的标头是系统标头并且允许包含。
添加编译器标志来声明系统头的位置。
在刚刚添加的“cxx_builtin_include_directory”行下方,添加以下内容:
compiler_flag: "-isystem=/tmp/bar/my_toolchain"
Run Code Online (Sandbox Code Playgroud)
您刚刚告诉 Bazel 告诉编译器应该从哪里查找系统头文件。
将标头添加到编译操作的默认输入集。
在文本编辑器中,打开/tmp/bar/my_toolchain/BUILD
,找到“compiler_deps”文件组,然后编辑其“srcs”属性,例如如下所示:
srcs = glob(["**/*.h"]),
Run Code Online (Sandbox Code Playgroud)
您刚刚告诉 Bazel 始终将这些文件包含在 C++ 编译操作中,因此构建将与沙箱和远程执行一起使用,并且如果任何系统标头(您刚刚添加到的系统标头)发生更改,Bazel 将重建 C++ 规则srcs
。
创建一个模拟stdc-predef.h
.
这是编译器总是希望包含的头文件。幸运的是,编译器会首先查看你的“-isystem”值,然后再回退到它自己的默认路径(我不知道你是否可以告诉它 ingore),所以我们可以像这样模拟这个文件:
touch /tmp/bar/my_toolchain/std-predef.h
Run Code Online (Sandbox Code Playgroud)尝试使用自定义交叉工具进行构建。
$ bazel build --crosstool_top=@my_toolchain//:toolchain //:x
INFO: Build options have changed, discarding analysis cache.
INFO: Analysed target //:x (0 packages loaded, 61 targets configured).
INFO: Found 1 target...
ERROR: /tmp/bar/BUILD:1:1: undeclared inclusion(s) in rule '//:x':
this rule is missing dependency declarations for the following files included by 'x.cc':
'/usr/include/stdio.h'
(...)
Target //:x failed to build
Use --verbose_failures to see the command lines of failed build steps.
INFO: Elapsed time: 0.332s, Critical Path: 0.09s, Remote (0.00% of the time): [queue: 0.00%, setup: 0.00%, process: 0.00%]
INFO: 0 processes.
FAILED: Build did NOT complete successfully
Run Code Online (Sandbox Code Playgroud)
由于我们的工具链目录中没有该文件stdio.h
,但编译器自己的默认目录中有一个,因此它会找到该文件并抱怨缺少标头。您可以创建一个模拟stdio.h
来消除这种情况。
您可以创建一个假的stdio.h
以使构建工作,或者您可以
#include <stdio.h>
从 中删除该行x.cc
。
在自定义工具链中创建一个假系统头。
我们将使用它来验证 Bazel 是否从自定义工具链中获取文件。
echo 'int foo_func(int x) { return x*2; }' > /tmp/bar/my_toolchain/foo.h
Run Code Online (Sandbox Code Playgroud)重写源文件以包含自定义系统标头。
echo -e '#include <foo.h>\nint main(int argc, char**) { return foo_func(argc); }' > x.cc
Run Code Online (Sandbox Code Playgroud)使用自定义工具链再次构建。现在一切都应该正常了。
bazel build --crosstool_top=@my_toolchain//:toolchain //:x
Run Code Online (Sandbox Code Playgroud)尝试使用 2 个参数运行构建的二进制文件(so argc=3
):
bazel-bin/x hello world ; echo $?
6
Run Code Online (Sandbox Code Playgroud) 归档时间: |
|
查看次数: |
2609 次 |
最近记录: |