You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Bazel构建的二进制文件中使用整个目录

问题:Bazel运行二进制程序时无法访问指定目录

场景复现

我们有一个C++二进制程序,通过Bazel构建,功能是遍历固定目录下的子目录并解析其中的.json文件,核心代码如下:

for (const auto& entry : std::filesystem::directory_iterator("/system/artefacts")) {
  if (entry.is_directory()) {
    // 查找.json文件并进行处理
  }
}

对应的Bazel配置:

cc_binary(
    name = "dir_iterator",
    srcs = ["dir_iterator.cpp"],
    data = [":data"],
    deps = [
        #...
    ],
)
filegroup(
    name = "data",
    srcs = glob([
        "system/artefacts", # 此配置无效
    ]),
)

运行bazel run //utils:dir_iterator时出现报错:

terminate called after throwing an instance of 'std::filesystem::__cxx11::filesystem_error'
  what():  filesystem error: directory iterator cannot open directory: No such file or directory [system/artefacts/]

工作区目录结构:

.
├── system
│   └── artefacts
│       ├── x
│       │   └── a.json
│       ├── y
│       │   └── a.json
│       └── z
│           └── a.json
└── util
    ├── BUILD
    └── dir_iterator.cpp

问题原因

  1. Filegroup配置错误:原filegroup仅指定了目录system/artefacts,Bazel不会自动递归包含目录内的文件和子目录,导致数据未被纳入运行环境。
  2. 路径硬编码问题:代码中使用绝对路径/system/artefacts,但Bazel运行时的工作目录是其输出目录(如bazel-bin),该绝对路径不存在;实际数据文件会被复制到Bazel的runfiles目录下。

解决方案

步骤1:修正Filegroup配置

修改filegroup,用**/*递归匹配目录下所有文件和子目录:

filegroup(
    name = "data",
    srcs = glob([
        "system/artefacts/**/*",
    ]),
)

方案A:通过Runfiles目录获取正确路径

利用Bazel提供的Runfiles机制获取数据文件的实际路径,需要依赖Bazel的Runfiles库:

  1. 更新cc_binary配置,添加Runfiles依赖:
cc_binary(
    name = "dir_iterator",
    srcs = ["dir_iterator.cpp"],
    data = [":data"],
    deps = [
        "@bazel_tools//tools/cpp/runfiles",
    ],
)
  1. 修改C++代码,获取Runfiles目录并拼接正确路径(替换your_workspace_name为你的Bazel工作区根目录名称):
#include <filesystem>
#include <iostream>
#include "tools/cpp/runfiles/runfiles.h"

namespace fs = std::filesystem;
using bazel::tools::cpp::runfiles::Runfiles;

int main(int argc, char** argv) {
    std::string error;
    std::unique_ptr<Runfiles> runfiles(Runfiles::Create(argv[0], &error));
    if (!runfiles) {
        std::cerr << "Failed to init runfiles: " << error << std::endl;
        return 1;
    }

    // 拼接工作区下的system/artefacts路径
    std::string artefacts_path = runfiles->Rlocation("your_workspace_name/system/artefacts");

    try {
        for (const auto& entry : fs::directory_iterator(artefacts_path)) {
            if (entry.is_directory()) {
                // 处理子目录中的JSON文件
                for (const auto& json_entry : fs::directory_iterator(entry.path())) {
                    if (json_entry.path().extension() == ".json") {
                        // 执行解析逻辑
                    }
                }
            }
        }
    } catch (const fs::filesystem_error& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}

方案B:通过命令行参数传递路径

通过Bazel的$(location)宏将数据目录路径作为命令行参数传递给程序,无需依赖额外库:

  1. 更新cc_binary配置,添加args传递路径:
cc_binary(
    name = "dir_iterator",
    srcs = ["dir_iterator.cpp"],
    data = [":data"],
    deps = [],
    args = ["$(location :data)"],
)
  1. 修改C++代码,读取命令行参数作为目标路径:
#include <filesystem>
#include <iostream>

namespace fs = std::filesystem;

int main(int argc, char* argv[]) {
    if (argc != 2) {
        std::cerr << "Usage: " << argv[0] << " <artefacts_dir>" << std::endl;
        return 1;
    }

    fs::path artefacts_path = argv[1];

    try {
        for (const auto& entry : fs::directory_iterator(artefacts_path)) {
            if (entry.is_directory()) {
                // 处理子目录中的JSON文件
                for (const auto& json_entry : fs::directory_iterator(entry.path())) {
                    if (json_entry.path().extension() == ".json") {
                        // 执行解析逻辑
                    }
                }
            }
        }
    } catch (const fs::filesystem_error& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return 1;
    }

    return 0;
}

内容的提问来源于stack exchange,提问作者Curious

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 19:53:12