自定义源文件中的动态依赖项



我有不是C/C++的自定义源文件。这些文件被编译为C源文件,然后这些C文件像往常一样由cmake编译。

但是,我的自定义文件可以具有在开发过程中可能会更改的依赖项。

例如,假设我有文件source1.langsource2.langsource3.lang...

来源1.朗

... some code

来源2.朗

import source1;
... some code

我将这些文件编译为

./langc source1.lang
./langc source2.lang
...

我得到source1.csource2.c...

现在,如您所见source2.lang取决于source1.lang.我可以随时通过预处理这些自定义文件找到它们的这些依赖项。然后生成对source1.lang的显式依赖关系source2.lang,以便在修改source1.lang时对其进行重新编译。

现在,我有一个这样的自定义命令

# This is populated automatically.
set(SOURCE2_DEPENDS source2.lang source1.lang) 
add_custom_command(
DEPENDS ${SOURCE2_DEPENDS }
COMMAND ./langc source2.lang
OUTPUT source2.c 
COMMENT "Compiling source2.c"
)

问题是依赖项在开发过程中可能会更改。也就是说,SOURCE1_DEPENDS可以在配置后更改。例如,我可以修改source2.lang以导入source3.lang

来源2.朗

import source1;
import source3;
... some code

我现在可以看到source2.lang被修改了。所以我对它进行了预处理以找到新的依赖项。但是我如何让 cmake 知道依赖项已更改?

到目前为止,我能看到的唯一方法是让 Makefile 生成器修改生成的 build.make 文件以手动添加和删除这些依赖项。

但是,我如何以通用方式告诉 cmake 这些是新的依赖项? 基本上就像 cmake 通常向 C 源文件添加新#include时所做的那样。这样事情也适用于其他发电机。

我认为以下内容仅适用于Ninja生成器。我认为它也适用于生成文件生成器,但我没有检查。

add_custom_commandDEPFILE选项。你必须从你的命令中生成一个类似 makefile 风格的 depfile。例如:

add_custom_command(
DEPENDS ${SOURCE2_DEPENDS}
DEPFILE ${CMAKE_CURRENT_BINARY_DIR}/source2.d
COMMAND ./langc 
--depfile ${CMAKE_CURRENT_BINARY_DIR}/source2.d
--depfile-relative ${CMAKE_BINARY_DIR}
source2.lang
OUTPUT source2.c 
COMMENT "Compiling source2.c"
)

生成的 depfile 应看起来像使用标准-MT/-MD选项gcc生成的生成文件依赖项文件。请注意,目标路径必须相对于${CMAKE_BINARY_DIR}。所以langc程序应该在${CMAKE_CURRENT_BINARY_DIR}/source2.d中生成以下文件:

buildir/subdir/source2.c: /absolute/path/to/be/safe/source2.lang /absolute/path/to/be/safe/source1.lang /etc..
# ^^ must be relative to CMAKE_BINARY_DIR

Cmake将depfile命令插入生成的忍者构建系统中,它们被忍者挑选,然后生成器知道了缺陷。但是,您可以考虑将自己的语言添加到cmake,以便cmake自动选取*.lang文件。

我对一个m4用于预处理源文件的项目进行了DEPFILE生成。使用--debug=pm4选项,预处理器在预处理文件时打印m4debug: including file <the file>或类似的东西。从这些消息中,我提取了文件并生成了依赖项文件。代码可在此处获得 m4.cmake 和 m4.sh.