cmake 生成 header 导致双重构建
cmake generated header causes double build
一个非常简单的场景 - 我需要生成 header,包含它,如果生成的 header 在 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 ${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 "test.h"
int main()
{
return 0;
}
当我进行完全重建时,一切正常。但是当我更改 test.in
时, 运行 只是 cmake.exe --build . --target all
仅重新生成 test.h
,但 main.cpp
不会重新编译。但是当我再次 运行 cmake.exe --build . --target all
时(第二次),main.cpp
被重新编译并且 test_exe
被重新链接。
我做错了什么?
P.S。如果我明确使用 OBJECT_DEPENDS
,没有问题,重建工作正常,但文档说它不再需要 - https://cmake.org/cmake/help/v3.20/prop_sf/OBJECT_DEPENDS.html
更新:
我使用 Windows 10、CMake 3.19.2 和 Ninja 1.10.2
解法:
在你的项目目录中使用构建目录,那么就没有问题了。但是如果构建目录在我们项目目录之外,那就有问题了。
张贴为能够显示完整示例的答案
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
这适用于 windows CMake 3.19.2 和 Ninja 1.10.2,可以在初始构建后更改 test.in
中的 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
一个非常简单的场景 - 我需要生成 header,包含它,如果生成的 header 在 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 ${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 "test.h"
int main()
{
return 0;
}
当我进行完全重建时,一切正常。但是当我更改 test.in
时, 运行 只是 cmake.exe --build . --target all
仅重新生成 test.h
,但 main.cpp
不会重新编译。但是当我再次 运行 cmake.exe --build . --target all
时(第二次),main.cpp
被重新编译并且 test_exe
被重新链接。
我做错了什么?
P.S。如果我明确使用 OBJECT_DEPENDS
,没有问题,重建工作正常,但文档说它不再需要 - https://cmake.org/cmake/help/v3.20/prop_sf/OBJECT_DEPENDS.html
更新: 我使用 Windows 10、CMake 3.19.2 和 Ninja 1.10.2
解法: 在你的项目目录中使用构建目录,那么就没有问题了。但是如果构建目录在我们项目目录之外,那就有问题了。
张贴为能够显示完整示例的答案
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
这适用于 windows CMake 3.19.2 和 Ninja 1.10.2,可以在初始构建后更改 test.in
中的 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