隔离Bazel C++;从系统包含目录生成 我想让我的BAZEL C++构建与 >代码> /Ur/Prime/It/等。默认情况下,如C++所描述的,在编译C++程序时,所有代码中的文件都是可用的,而不是标准程序。
实现这一目标的最佳方式是什么隔离Bazel C++;从系统包含目录生成 我想让我的BAZEL C++构建与 >代码> /Ur/Prime/It/等。默认情况下,如C++所描述的,在编译C++程序时,所有代码中的文件都是可用的,而不是标准程序。,bazel,Bazel,实现这一目标的最佳方式是什么 一种选择是将标准头文件放入tarball中,并通过HTTP将其托管在某个地方,然后添加一个新的\u HTTP_存储库,并使用-nostinc-isysroot运行gcc。解决方案包括三个部分: < LI>创建自定义C++工具链定义 说服Bazel使用这个工具链 说服编译器忽略其默认系统头并使用您的系统头 以下是您需要的参考资料: 这里有一个特别好的教程: 还有一些教程,我不知道它们有多先进: 下面是我如何在Linux上使用GCC实现这一点的: 创建一
一种选择是将标准头文件放入tarball中,并通过HTTP将其托管在某个地方,然后添加一个
新的\u HTTP_存储库
,并使用-nostinc-isysroot运行gcc
。解决方案包括三个部分:
< LI>创建自定义C++工具链定义
- 说服Bazel使用这个工具链
- 说服编译器忽略其默认系统头并使用您的系统头
以下是您需要的参考资料:
这里有一个特别好的教程:
还有一些教程,我不知道它们有多先进:
下面是我如何在Linux上使用GCC实现这一点的:
创建一个包含伪cc_二进制规则的新工作区
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
因为它是Cc**规则,Bazel将初始化C++工具链。这包括自动生成
交叉工具文件。这是一个描述编译器接口的文本文件,因此Bazel知道如何使用它
跟它说话
为自定义crosstool创建一个包,复制自动生成的crosstool并在其中生成文件
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
我们将使用自动生成的文件作为模板开始
将外部存储库规则添加到工作区文件
echo "local_repository(name='my_toolchain', path='/tmp/bar/my_toolchain')" >> WORKSPACE
这样,您可以通过Bazel构建标签引用自定义工具链
尝试使用您的自定义交叉工具
bazel build --crosstool_top=@my_toolchain//:toolchain //:x
$ 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
因为它与自动生成的相同,所以构建应该成功
从自定义CROSSTOOL中的“本地”工具链编辑系统标题路径
注意:如果要选择其他工具链,则可能需要编辑其他工具链。看见
此处的工具链选择:
在文本编辑器中,打开/tmp/bar/my_toolchain/CROSSTOOL
,找到“toolchain”记录
“toolchain_identifier”是“local”,并注释掉其“cxx_内置_include_目录”条目
(注释字符为“#”)
然后为您的工具链目录添加新的“cxx\u内置\u包含\u目录”:
cxx_builtin_include_directory: "/tmp/bar/my_toolchain"
您刚刚告诉Bazel系统头在哪里,所以当它验证头包含时,它将知道此路径下的头是系统头,并且允许包含
添加编译器标志以声明系统头的位置
在刚刚添加的“cxx\U内置\U包含\U目录”行下方,添加以下内容:
compiler_flag: "-isystem=/tmp/bar/my_toolchain"
您刚刚告诉Bazel告诉编译器应该从哪里查找系统头
将标题添加到编译操作的默认输入集
在文本编辑器中,打开/tmp/bar/my_toolchain/BUILD
,找到“compiler_deps”文件组,然后
编辑其“srcs”属性,例如:
srcs = glob(["**/*.h"]),
touch /tmp/bar/my_toolchain/std-predef.h
<>你刚刚告诉Bazel总是把这些文件包含在C++编译动作中,所以编译
将使用沙箱和远程执行,Bazel将重建C++规则,如果有
系统标题(您刚刚添加到srcs
)会发生变化
创建一个模拟的stdc predef.h
这是编译器始终希望包含的头文件。幸运的是,编译器将首先
在返回到自己的默认路径(我不知道是否为默认路径)之前,请查看“-isystem”值
您可以告诉ingore),这样我们就可以模拟此文件:
srcs = glob(["**/*.h"]),
touch /tmp/bar/my_toolchain/std-predef.h
bazel build --crosstool_top=@my_toolchain//:toolchain //:x
$ 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
因为在我们的工具链目录中没有stdio.h
,但是在编译器自己的目录中有一个
默认目录下,它将查找文件并抱怨缺少标题。您可以创建一个
mockstdio.h
使其静音
您可以创建一个假的stdio.h
使构建工作,也可以删除
#包括x.cc
中的
行echo 'int foo_func(int x) { return x*2; }' > /tmp/bar/my_toolchain/foo.h
我们将使用它来验证Bazel是否从自定义工具链中拾取文件
echo 'int foo_func(int x) { return x*2; }' > /tmp/bar/my_toolchain/foo.h
echo -e '#include <foo.h>\nint main(int argc, char**) { return foo_func(argc); }' > x.cc
argc=3
):
在什么意义上是独立的——您希望您的构建忽略预安装的系统头,还是希望通过使系统头成为源代码树的一部分(通过外部存储库)使构建更加封闭?@LászlóI希望通过使系统头来自外部存储库使构建更加封闭,不是来自/usr/include中安装的任何内容。谢谢您的详细回答!我会试试这个。有更新的信息吗?顶部的大多数链接都是DOA,从v3.0.0开始,看起来不再生成CROSSTOOL文件。