C++ cmake生成的头导致双重生成
一个非常简单的场景-我需要生成标题,包括它,如果生成的标题在cmake构建时更新,所有依赖的cpp单元也必须重建 一个简化的例子:C++ cmake生成的头导致双重生成,c++,cmake,ninja,C++,Cmake,Ninja,一个非常简单的场景-我需要生成标题,包括它,如果生成的标题在cmake构建时更新,所有依赖的cpp单元也必须重建 一个简化的例子: add_custom_command( OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/test.h COMMAND ... DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/test.in" add_custom_target(test_target DEPENDS ${C
add_custom_command(
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/test.h
COMMAND ...
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/test.in"
add_custom_target(test_target DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/test.h)
add_executable(test_exe
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
)
add_dependencies(test_exe test_target)
main.cpp
只是:
#包括“test.h”
int main()
{
返回0;
}
当我进行全面重建时,一切都很顺利。但是当我更改test.in
时,只运行cmake.exe--build--仅重新生成test.h
,但不重新编译main.cpp
。但是当我运行cmake.exe时——build--再次(第二次)瞄准所有对象,重新编译main.cpp
,并重新链接test_exe
我错了什么
另外,如果我明确使用OBJECT\u dependens
,则没有问题,重建工作正常,但文档称不再需要它-
更新:
我使用Windows 10、CMake 3.19.2和忍者1.10.2
解决方案:
在项目目录中使用build目录,那么就没有问题了。但是,如果构建目录在我们的项目目录之外,那么就有问题了。作为答案发布,以便能够显示完整的示例
CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
project(example)
add_custom_command(
OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/test.h
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/test.in" ${CMAKE_CURRENT_SOURCE_DIR}/test.h
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/test.in")
add_custom_target(test_target DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/test.h)
add_executable(test_exe
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp
)
add_dependencies(test_exe test_target)
main.cpp
#include "stdio.h"
#include "test.h"
int main()
{
printf("The value is %d\n", FOO);
return 0;
}
test.in
#define FOO 4
这适用于装有CMake 3.19.2和Ninja 1.10.2的windows,用户可以在test中更改FOO
定义。在初始构建后的中,可以看到结果可执行文件被重建,并看到其值被更改
用于测试的命令
$ cmake -B build -G Ninja
-- The C compiler identification is Clang 11.0.0 with GNU-like command-line
-- The CXX compiler identification is Clang 11.0.0 with GNU-like command-line
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: C:/Program Files/LLVM/bin/clang.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: C:/Program Files/LLVM/bin/clang++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: <some_path>
$ cmake --build build
[3/3] Linking CXX executable test_exe.exe
$ ./build/test_exe.exe
The value is 4
$ echo "#define FOO 3" > test.in
$ cmake --build build
[3/3] Linking CXX executable test_exe.exe
$ ./build/test_exe.exe
The value is 3
$cmake-B build-G忍者
--C编译器标识是使用类似GNU的命令行的Clang 11.0.0
--CXX编译器标识为Clang 11.0.0,使用类似GNU的命令行
--检测C编译器ABI信息
--检测C编译器ABI信息-完成
--检查C编译器是否工作:C:/Program Files/LLVM/bin/clang.exe-已跳过
--检测C编译特性
--检测C编译特性-完成
--检测CXX编译器ABI信息
--检测CXX编译器ABI信息-完成
--检查CXX编译器是否工作:C:/Program Files/LLVM/bin/clang++.exe-已跳过
--检测CXX编译特性
--检测CXX编译功能-完成
--配置完成
--生成完成
--生成文件已写入:
$cmake——构建
[3/3]链接CXX可执行文件test_exe.exe
$./build/test_exe.exe
值为4
$echo“#定义FOO 3”>test.in
$cmake——构建
[3/3]链接CXX可执行文件test_exe.exe
$./build/test_exe.exe
值为3
不相关,但您可以直接在添加可执行文件
命令中添加目标,您不需要添加依赖项
。我预见到了有关使用添加自定义目标
和添加依赖项
的响应,因此决定使用它们。我尝试了所有可能的变体(没有显式依赖项,使用它们,使用静态库)。唯一有效的变体是设置OBJECT\u dependence
,但在我看来,它已经过时且不实用。add\u dependencies
只提供目标之间的顺序。要使可执行文件依赖于自定义命令生成的头文件,请将该头文件添加到add_executable
调用中:add_executable(test_exe${CMAKE_CURRENT_SOURCE_DIR}/main.cpp${CMAKE_CURRENT_SOURCE_DIR}/test.h)
@Tsyvarevtest.h
包含在main.cpp>中。但我试过了,它不起作用。可能需要使用什么样的CMake版本、平台和生成器。将COMMAND${CMAKE\u COMMAND}-E copy“${CMAKE\u CURRENT\u SOURCE\u DIR}/test.in”${CMAKE\u CURRENT\u SOURCE\u DIR}/test.h
与CMAKE\u minimum\u required
和project
一起添加到示例中,将在我的windows机器上重新编译main.cpp。CMake版本3.18.2使用msbuild和Ninja。您是否碰巧整合了多个CMakeLists.txt文件以最小化问题?似乎我找到了原因。如果我从控制台调用cmake-B build-G Ninja
,一切都会按照预期工作,与您的示例完全相同,但是如果我从QtCreator生成它,行为会有所不同——正如我在问题中描述的那样。我会挖进去的。非常感谢。哇!如果在项目目录外使用build目录,即cmake-B..\build-G Ninja
,则存在问题,但如果在项目内使用build目录,则没有问题。这是一种记录在案的行为吗?这非常奇怪。>如果在项目目录之外使用build目录,即cmake-B..\build-G Ninja
,那么问题就出在这里,我无法重现:(它似乎在项目目录内部或外部处理相同的增量。