查看上次状态更新
初始条件
已经解决了获取输出文件列表的任务,解析输入的codegen文件以获取codegen输入的完整列表。 即add_custom_command第一次提供了正确的依赖项集:
add_custom_command(OUTPUT ${generatedSources}
COMMAND ${codegenCommand} ARGS ${codegenArgs}
DEPENDS ${codegenInputFiles})
问题情景
缺少什么
有没有办法解决它而不进行完整的项目重建?
更新 - 替代(更好?)问题描述
我在cmake邮件列表上找到了类似的未回答的问题,为了更清晰,请在此处发布: http://article.gmane.org/gmane.comp.programming.tools.cmake.user/52279
我正在尝试使用代码生成工具来表现"与"相同关于依赖项的C源文件。我的意思是,假设你有一个C文件" a.c"。因为它可以#include文件,所以每次a.c
的内容发生更改时,其依赖关系也可能已更改。依赖项将使用-MMD重新扫描。我想用某种方法来模拟我的代码生成器。
首先,我尝试了add_custom_command,它接受一个固定的DEPENDS列表,该列表是在定义自定义命令时确定的。具体来说,我的意思是这样的:
function(add_generated_library)
figure_out_dependencies(deps ${ARGN})
add_custom_command(... DEPENDS ${deps})
endfunction()
但这仅捕获构建系统生成时的依赖关系。每次运行自定义命令时,DEPENDS列表可能需要更改,因为更改可能意味着新的依赖关系。我应该怎么做呢?
更新2 - 可能的解决方案
以下我认为是事实 - 网络上有关于cmake支持动态的声音 依赖关系,这是许多人顺利整合所必需的 非平凡的代码生成工具 - 没有现成的最佳解决方案,因为我们实际需要的是将自定义DSL的支持添加到IMPLICIT_DEPENDS
来自cmake手册:
IMPLICIT_DEPENDS选项请求扫描输入文件的隐式依赖项。给定的语言指定了应使用相应依赖性扫描程序的编程语言。目前仅支持C和CXX语言扫描程序。必须为IMPLICIT_DEPENDS列表中的每个文件指定语言。 从扫描中发现的依赖关系会在构建时添加到自定义命令的依赖关系。
下面的解决方案(希望)符合以下标准:
解决方案想法
无法注册自定义语言扫描程序,但可以重用现有语言扫描程序。这个想法是自定义模型文件的依赖关系/层次结构反映为" C"头文件。每个层次结构节点在注册模型文件时添加,C文件包括匹配模型文件。如果模型文件包含更改,则C文件包含更改。因此,每个codegen调用将仅依赖于反映传递模型的一个生成的C头。每个反射文件都依赖于模型文件,并触及模型文件更改。
总结:可能,我的措辞在这一点上并不是那么清楚,但是对于其他人的需求和社区帮助我调查这个问题,我将发布通用解决方案(+链接到github或者新的cmake wiki page)一旦准备好(1-3天内),没有我的项目细节。
答案 0 :(得分:1)
您能说明如何初始化变量codegenInputFiles
吗?您可以在那里使用file(GLOB ... )
或file(GLOB_RECURSE ... )
命令。
请参阅documentation。
但请注意,您必须重新运行cmake才能生成命令。你在使用git吗?然后你可以a hook每次拉动时强制进行一次cmake调用(这样如果有人修改了codegenInputFiles
,你的自动生成的文件就会被更新。)
在澄清问题后,您应该能够使用IMPLICIT_DEPENDS
代替DEPENDS
找到解决方法。限制:
修改强>
经过一些迭代,我终于得到了你的问题。 我提出以下解决方案:在单独的cmake子项目中分离文件生成。当您构建主项目(通过调用make)时,您将触发子项目的cmake和make。调用cmake是保持更新依赖关系的必要条件,同时调用make来实际构建自动生成的源。
这里我展示了一个项目和子项目的示例,项目调用cmake并为子项目生成。
结构:
.
├── CMakeLists.txt
├── a.cpp
├── build
└── subProject
└── CMakeLists.txt
文件内容
<强> ./的CMakeLists.txt 强>:
cmake_minimum_required(VERSION 2.8)
add_custom_target(subProjectTarget ALL)
add_custom_command(TARGET subProjectTarget PRE_BUILD COMMAND mkdir -p ${CMAKE_BINARY_DIR}/subProject && cd ${CMAKE_BINARY_DIR}/subProject && ${CMAKE_COMMAND} ${CMAKE_SOURCE_DIR}/subProject && make)
include_directories(${CMAKE_BINARY_DIR}/subProject)
add_executable (dummy a.cpp)
add_dependencies (dummy subProjectTarget)
./ a.cpp (请注意,b.h尚不存在)
#include "b.h"
int main () {
}
<强> ./子项目/的CMakeLists.txt 强>
cmake_minimum_required(VERSION 2.8)
file(WRITE ${CMAKE_BINARY_DIR}/b.h "//I am a dummy file\n")
构建项目(使用默认make
)
me@here:~/example/build$ cmake ..
-- The C compiler identification is GNU 4.8.2
-- The CXX compiler identification is GNU 4.8.2
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/me/example/build
me@here:~/example/build$ make
Scanning dependencies of target subProjectTarget
-- The C compiler identification is GNU 4.8.2
-- The CXX compiler identification is GNU 4.8.2
-- Check for working C compiler: /usr/bin/cc
-- Check for working C compiler: /usr/bin/cc -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/me/example/build/subProject
[ 0%] Built target subProjectTarget
Scanning dependencies of target dummy
[100%] Building CXX object CMakeFiles/dummy.dir/a.cpp.o
Linking CXX executable dummy
[100%] Built target dummy
请注意,第二次cmake调用是在子项目上。
下次通话时,一切都会更快:
me@here:~/example/build$ make
-- Configuring done
-- Generating done
-- Build files have been written to: /home/me/example/build/subProject
[ 0%] Built target subProjectTarget
Scanning dependencies of target dummy
[100%] Building CXX object CMakeFiles/dummy.dir/a.cpp.o
Linking CXX executable dummy
[100%] Built target dummy
(虽然每次都会写入文件b.h,导致重新编译a.cpp)
通过使用cmake命令生成输出目录(而不是mkdir)并级联为主项目选择的生成器(这里我假设一切都使用make),可以大大改善这个存根。
如果您需要进一步澄清,请与我们联系。
答案 1 :(得分:0)
我认为${codegenInputFiles}
应包含硬编码源文件列表,并包含自定义命令所需的文件。 file(GLOB ...) 州的文件:
我们不建议使用GLOB从中收集源文件列表 你的源代码树。如果源没有更改CMakeLists.txt文件 添加或删除然后生成的构建系统无法知道何时 让CMake重新生成。
努力工作(我们付出的代价)是让${codegenInputFiles}
保持最新状态(导致整个项目重建)。无论如何,如果有人创建了一个新的源文件并且没有将其添加到${codegenInputFiles}
,你会遇到类似的问题,对吗?所以我认为对包含文件的额外依赖应该被视为相同。