在编译时为大型 C/C++ 项目使用 GNU m4

Posted

技术标签:

【中文标题】在编译时为大型 C/C++ 项目使用 GNU m4【英文标题】:Use GNU m4 at compile time for large C/C++ project 【发布时间】:2017-11-17 19:05:46 【问题描述】:

背景

我目前正在重构一个大型项目。问题之一是大量滥用字符串文字(300 多个实例)用于产品使用的公共路径(即引用 /opt/dev 和该位置的子路径),包括:

C/C++ 源文件和头文件。 python 脚本。 bash 脚本。 systemd 脚本。 二进制图像(驱动程序)。

目标

我想使用 GNU m4 来定义一个包含一组通用宏的文件,这样我们就可以“一次编写,到处使用”,这样如果我们的代码是分支的(典型的新产品),我们可以只更改该文件中的宏,而不是寻找重复的字符串文字并调试它们数天。这对于脚本之类的简单事物来说很容易,因为我只需在构建输出路径中创建源树的副本,然后直接在脚本上运行 M4。


问题

到目前为止,唯一的缺点是这看起来对于 C/C++ 项目来说将是一项巨大的工作,因为我只想在编译时执行 M4 宏扩展/替换。这意味着,为了避免修改从 git 签出的源文件,我将不得不修改我的构建脚本(大量 Makefile)来处理代码的临时副本,而不是原始源文件本身。否则,直接在受版本控制的源代码上运行M4 会生成对本地工作副本的更改,并且开发人员可能会将这个经过 M4 评估的代码副本提交给版本控制,从而破坏 M4 工作。


问题

是否可以通过某些外部工具或 GCC 本身的某些功能在编译期间指示 gcc 评估 m4 宏/扩展?如果没有,我的构建脚本可能需要进行大规模检修才能支持 M4 宏。

【问题讨论】:

使用 m4 为 C 和/或 C++ 代码生成 project-config.h 标头。在需要使用其中一个宏的每个文件中使用该标题。确保程序员知道应该使用什么。可能在签入前或定期执行代码检查?当该标头更改时重新编译。不要不必要地改变它。 @JonathanLeffler 叹息,如此优雅和简单。不知道我怎么忽略了这一点。如果您将此转换为答案,我会将其标记为已接受。 【参考方案1】:

使用m4 为C 和/或C++ 代码生成project-config.h 标头。在需要使用其中一个宏的每个文件中使用该标题。确保程序员知道应该使用什么。可能在签入前强制使用代码检查,或定期扫描代码库?当该标头更改时重新编译受影响的文件。不要不必要地改变它。

【讨论】:

我认为我出错的地方是将 M4 视为流编辑器(即像 sed + grep 的“花式”版本)而不是文件生成工具。错误的心智模型。 容易犯错误。 AutoConf 系统使用m4,并生成配置文件。这大致类似。

以上是关于在编译时为大型 C/C++ 项目使用 GNU m4的主要内容,如果未能解决你的问题,请参考以下文章

大型项目使用Automake/Autoconf完成编译配置(标准的编译过程已经变成了简单的三部曲:configure/make/make install,)

LINUX编译m4

如何调试大型 Linux C/C++ 项目?

Xcode 在更改时为每个应用程序目标编译情节提要

指示 gnu make 只使用静态库

不同 C/C++ 语言版本 + GNU 扩展的 ABI 兼容性