如何在Bazel的BUILD文件中便捷引用DirectX SDK环境变量?
在Bazel中引用DirectX SDK的简便方案
遗憾的是,Bazel的设计理念(追求构建可重现性)决定了它不能像Make那样直接在BUILD文件里用$(DXSDK_DIR)这种方式引用环境变量——BUILD文件的评估阶段会隔离外部环境变量,避免环境差异导致构建结果不一致。不过你也不用写复杂的插件,有几个相对简便的方案可以实现需求:
方案1:用简单的仓库规则自动关联DXSDK
这是最推荐的方式,只需要写几行轻量的Bazel规则代码,就能在BUILD文件里直接依赖DXSDK,不用手动处理路径:
- 在项目根目录创建
tools/dxsdk.bzl文件,内容如下:
def _dxsdk_repository_impl(ctx): # 从环境变量读取DXSDK路径 dx_dir = ctx.os.environ.get("DXSDK_DIR") if not dx_dir: fail("请设置DXSDK_DIR环境变量,或通过--action_env=DXSDK_DIR参数传递") # 把DXSDK目录软链到仓库中 ctx.symlink(dx_dir, "dxsdk") # 生成仓库的BUILD文件,定义一个包含DXSDK头文件的cc_library ctx.file("BUILD.bazel", content=""" cc_library( name = "dxsdk", hdrs = glob(["dxsdk/Include/**/*.h"]), includes = ["dxsdk/Include"], visibility = ["//visibility:public"], ) """) # 定义仓库规则,声明需要读取DXSDK_DIR环境变量 dxsdk_repository = repository_rule( implementation = _dxsdk_repository_impl, environ = ["DXSDK_DIR"], )
- 在
WORKSPACE文件中添加以下内容,加载并调用这个规则:
load("//tools:dxsdk.bzl", "dxsdk_repository") # 创建名为dxsdk的外部仓库 dxsdk_repository(name = "dxsdk")
- 现在你可以在任何BUILD文件里直接依赖这个仓库,自动获取DXSDK的头文件路径:
cc_binary( name = "my_dx_app", srcs = ["main.cpp"], deps = ["@dxsdk//:dxsdk"], )
构建时只需要传递--action_env=DXSDK_DIR参数即可,比如:
bazel build //:my_dx_app --action_env=DXSDK_DIR=C:/path/to/DirectXSDK
方案2:手动传递路径(不推荐,可维护性差)
如果你完全不想写任何.bzl文件,也可以通过--define参数传递DXSDK路径,然后在BUILD文件里用select配合构建变量实现,但这种方式需要手动维护路径,灵活性差:
- 构建时传递路径:
bazel build //:my_dx_app --define=DXSDK_DIR=C:/path/to/DirectXSDK
- 在BUILD文件里使用:
cc_binary( name = "my_dx_app", srcs = ["main.cpp"], includes = select({ "@bazel_tools//src/conditions:windows": ["$(DXSDK_DIR)/Include"], "//conditions:default": [], }), )
不过这种方式有个弊端:--define的变量在BUILD文件里只能通过select或者在bzl规则里用ctx.var获取,而且无法自动验证路径是否存在,可维护性远不如方案1。
为什么不能像Make那样直接引用?
Bazel的核心目标是可重现构建,而环境变量是外部可变因素——不同机器上的DXSDK_DIR可能不同,直接引用会导致相同代码在不同环境下构建结果不一致。因此Bazel限制了BUILD文件直接访问环境变量,必须通过repository_rule或构建动作(actions)来安全地引入外部依赖。
内容的提问来源于stack exchange,提问作者shybovycha
相关产品推荐
相关产品推荐

