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

如何在Bazel的cc_library规则中生成cool_app.h的预处理输出?

为Bazel构建的C++头文件生成预处理输出

问题描述

我用Bazel构建C++项目,完全不熟悉Bazel,只会复制现有规则或者给规则添加源文件。当前有如下cc_library规则:

cc_library(
    name = "cool_app",
    srcs = ["cool_app.cpp"],
    hdrs = ["cool_app.h"],
    deps = ["//modules/common"],
)

我想为cool_app.h生成预处理后的可读输出,能否通过给这个现有规则添加选项实现?

更新补充

cool_app.h的内容如下:

#pragma once

#define ENUM_INIT_LIST \
    ADD_VALUE(First) \
    ADD_VALUE(Second) \

#define ADD_VALUE(topic) topic,
enum class Topic : int {
    Invalid = -1,
    TOPIC_INIT_LIST
    LAST_ENUM_ELEMENT,
};
#undef ADD_VALUE

#define ADD_VALUE(topic) Topic::topic,
constexpr auto kAvailableTopics =
    std::initializer_list<Topic>({TOPIC_INIT_LIST});
#undef ADD_VALUE

我需要保存预处理后的输出,最终要得到类似这样的可读内容:

#pragma once

enum class Topic : int {
    Invalid = -1,
    First,
    Second,
    LAST_ENUM_ELEMENT,
};

constexpr auto AvailableTopics =
    std::initializer_list<Topic>({
        Topic::First,
        Topic::Second,
    });

解决方案

没办法直接给现有的cc_library规则添加选项来生成预处理输出——你需要新增一个专门的规则来完成这个任务。Bazel内置的cc_library是用来编译库的,不负责生成预处理文件这类辅助输出。

最直接的方式是用Bazel的genrule调用C++编译器的预处理命令,具体步骤如下:

1. 添加genrule规则到BUILD文件

在你的BUILD文件里新增如下规则:

genrule(
    name = "preprocess_cool_app_h",
    srcs = ["cool_app.h"],
    outs = ["cool_app_preprocessed.h"],
    cmd = "$(CXX) -E -P -x c++ $< | sed 's/kAvailableTopics/AvailableTopics/g' > $@",
    tools = ["@bazel_tools//tools/cpp:cpp_compiler"],
)

参数说明:

  • -E:让编译器只执行预处理步骤,不进行编译、汇编等后续操作
  • -P:移除预处理生成的行号和文件标记,让输出更干净易读
  • -x c++:明确指定处理的是C++文件,避免编译器因头文件后缀产生识别问题
  • sed命令用于将原文件中的kAvailableTopics替换为你想要的AvailableTopics,如果不需要修改变量名,可以去掉这部分
  • $<代表规则的输入源文件(这里就是cool_app.h),$@代表规则的输出文件

2. 处理依赖(如果有)

如果cool_app.h依赖//modules/common中的头文件,需要把这些依赖的头文件加入srcs,并在编译命令中添加包含路径:

genrule(
    name = "preprocess_cool_app_h",
    srcs = ["cool_app.h", "//modules/common:common_hdrs"], # 假设common模块有导出头文件的规则
    outs = ["cool_app_preprocessed.h"],
    cmd = "$(CXX) -E -P -x c++ -I$(GENDIR)/modules/common $< | sed 's/kAvailableTopics/AvailableTopics/g' > $@",
    tools = ["@bazel_tools//tools/cpp:cpp_compiler"],
)

3. 运行生成命令

在项目根目录执行以下命令:

bazel build //path/to/your/package:preprocess_cool_app_h

生成的预处理文件会位于bazel-bin/path/to/your/package/cool_app_preprocessed.h路径下。

如果后续需要频繁生成预处理文件,可以封装自定义Bazel规则,但对于新手来说,genrule是最快速上手的方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 04:50:30