Bazel构建阶段复制重命名目录及依赖报错解决问询
错误原因
Bazel的执行分为配置阶段和构建阶段:
- 配置阶段会扫描所有真实存在的目录,解析BUILD文件和依赖关系
- 你用
copy_directory生成的directory_real是在构建阶段才会创建的临时目录,配置阶段Bazel根本找不到这个目录的BUILD文件,所以报错no such package 'directory_real'。
正确实现方案
不需要复制目录,用Bazel的config_setting+alias机制就能实现根据标志切换依赖,更高效简洁。
步骤1:定义配置标志
在根目录的BUILD文件中添加配置规则,用来识别构建时的标志:
config_setting( name = "use_directory_b", define_values = {"use_dir": "b"}, ) config_setting( name = "use_directory_a", define_values = {"use_dir": "a"}, # 默认用directory_a,当没有指定--define use_dir=b时生效 visibility = ["//visibility:public"], )
步骤2:定义别名库
在根目录BUILD中添加一个别名cc_library,根据标志自动切换到directory_a或directory_b的mylib:
alias( name = "real_mylib", actual = select({ ":use_directory_b": "//directory_b:mylib", ":use_directory_a": "//directory_a:mylib", "//conditions:default": "//directory_a:mylib", }), visibility = ["//visibility:public"], )
步骤3:调整main.cpp的include和构建配置
修改main.cpp的include路径(不需要虚拟的directory_real):
#include "interface.h" // do something int main(){ // 注意:C++标准中main返回int,不是void // say hello world return 0; }
然后修改directoryC/BUILD中的cc_binary配置,添加include路径并依赖别名库:
cc_binary( name = "test", srcs = ["main.cpp"], visibility = ["//visibility:public"], copts = select({ "//:use_directory_b": ["-I../directory_b"], "//:use_directory_a": ["-I../directory_a"], "//conditions:default": ["-I../directory_a"], }), deps = ["//:real_mylib"], )
构建命令
- 默认用directory_a构建:
bazel build //directoryC:test
- 指定用directory_b构建:
bazel build //directoryC:test --define use_dir=b
(可选)坚持使用directory_real作为include路径的方案
如果必须保留#include "directory_real/interface.h"的写法,可以用genrule生成包含头文件的directory_real目录,然后用cc_library依赖生成的文件:
- 根目录BUILD添加genrule:
genrule( name = "generate_directory_real", srcs = select({ ":use_directory_b": ["//directory_b:interface.h", "//directory_b:mylib.cpp"], ":use_directory_a": ["//directory_a:interface.h", "//directory_a:mylib.cpp"], }), outs = [ "directory_real/interface.h", "directory_real/mylib.cpp", ], cmd = """ mkdir -p $(@D)/directory_real cp $(SRCS) $(@D)/directory_real/ """, ) cc_library( name = "directory_real_mylib", srcs = [":generate_directory_real"], hdrs = [":generate_directory_real"], visibility = ["//visibility:public"], )
- 修改directoryC/BUILD:
cc_binary( name = "test", srcs = ["main.cpp"], visibility = ["//visibility:public"], copts = ["-I.."], # 让编译器能找到根目录下生成的directory_real deps = ["//:directory_real_mylib"], )
这种方式需要生成文件副本,不如别名方案高效,优先推荐第一种方案。
内容的提问来源于stack exchange,提问作者Exia
相关产品推荐
相关产品推荐

