隔离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
    ,但是在编译器自己的目录中有一个 默认目录下,它将查找文件并抱怨缺少标题。您可以创建一个 mock
    stdio.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
    
  • 尝试使用2个参数运行构建的二进制文件(因此
    argc=3
    ):


  • 在什么意义上是独立的——您希望您的构建忽略预安装的系统头,还是希望通过使系统头成为源代码树的一部分(通过外部存储库)使构建更加封闭?@LászlóI希望通过使系统头来自外部存储库使构建更加封闭,不是来自/usr/include中安装的任何内容。谢谢您的详细回答!我会试试这个。有更新的信息吗?顶部的大多数链接都是DOA,从v3.0.0开始,看起来不再生成CROSSTOOL文件。