我有个大项目。在根目录中,我创建了文件CMake\optionalsource.cmake
(在目录CMake
中是其他帮助程序文件),其中包含以下函数定义:
cmake_minimum_required(VERSION 3.5)
# cmake_parse_arguments needs cmake 3.5
##
# This function always adds sources to target, but when "WHEN" condition is not meet
# source is excluded from build process.
# This doesn't break build, but source is always visible for the project, what is
# very handy when working with muti-platform project with sources needed
# only for specific platform
#
# Usage:
# target_optional_sources(WHEN <condition>
# TARGET <target>
# <INTERFACE|PUBLIC|PRIVATE> [items2...]
# [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
##
function(target_optional_sources)
set(options OPTIONAL "")
set(oneValueArgs WHEN TARGET)
set(multiValueArgs PUBLIC PRIVATE INTERFACE)
cmake_parse_arguments(target_optional_sources
"${options}" "${oneValueArgs}" "${multiValueArgs}"
${ARGN})
# for debugging purposes
message("TARGET ${target_optional_sources_TARGET}")
message("PUBLIC ${target_optional_sources_PUBLIC}")
message("PRIVATE ${target_optional_sources_PRIVATE}")
message("INTERFACE ${target_optional_sources_INTERFACE}")
message("WHEN ${target_optional_sources_WHEN} ${${target_optional_sources_WHEN}}")
target_sources(${target_optional_sources_TARGET}
PUBLIC ${target_optional_sources_PUBLIC}
PRIVATE ${target_optional_sources_PRIVATE}
INTERFACE ${target_optional_sources_INTERFACE})
if (NOT ${target_optional_sources_WHEN})
set_source_files_properties(${target_optional_sources_PUBLIC}
PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties(${target_optional_sources_PRIVATE}
PROPERTIES HEADER_FILE_ONLY TRUE)
set_source_files_properties(${target_optional_sources_INTERFACE}
PROPERTIES HEADER_FILE_ONLY TRUE)
endif(NOT ${target_optional_sources_WHEN})
endfunction(target_optional_sources)
这包含在根CMakeLists.txt
中。
现在这个功能很简单。它是受this nice SO answer和this feature request for CMake激励的。
现在我遇到了一些奇怪的问题。 我的项目包含许多目标(libs / dlls / execs),我在这样的一个地方使用了此功能:
add_library(CommonLibrary STATIC
<list of mutliplatform sources>
)
message("=== function CommonLibrary ===")
target_optional_sources(WHEN APPLE
TARGET CommonLibrary
PUBLIC
macos/CFUtils.cpp
macos/CFUtils.h
MacMachineData.mm
MacMachineData.h
macos/MacAutoreleasePool.mm
macos/MacAutoreleasePool.h
)
在日志中,我可以看到:
1>=== function CommonLibrary ===
1>TARGET CommonLibrary
1>PUBLIC macos/CFUtils.cpp;macos/CFUtils.h;MacMachineData.mm;MacMachineData.h;macos/MacAutoreleasePool.mm;macos/MacAutoreleasePool.h
1>PRIVATE
1>INTERFACE
1>WHEN APPLE
但是下面我会看到以下错误消息:
1>CMake Error at SomeOtherLib1/CMakeLists.txt:34 (add_executable):
1> Cannot find source file:
1>
1> macos/CFUtils.cpp
1>
1> Tried extensions .c .C .c++ .cc .cpp .cxx .cu .m .M .mm .h .hh .h++ .hm
1> .hpp .hxx .in .txx
1>
1>
1>CMake Error at SomeOtherLib2/CMakeLists.txt:11 (add_executable):
1> Cannot find source file:
1>
1> macos/CFUtils.cpp
1>
1> Tried extensions .c .C .c++ .cc .cpp .cxx .cu .m .M .mm .h .hh .h++ .hm
1> .hpp .hxx .in .txx
1>
1>
1>CMake Error at UnitTests/CMakeLists.txt:11 (add_executable):
1> Cannot find source file:
1>
1> macos/CFUtils.cpp
1>
1> Tried extensions .c .C .c++ .cc .cpp .cxx .cu .m .M .mm .h .hh .h++ .hm
1> .hpp .hxx .in .txx
1>
macos/CFUtils.cpp
仅通过调用我的自定义函数来添加,那么其他CMakeLists.txt
文件如何可能受到成功的函数调用的影响?当我在函数调用中对文件重新排序时,错误消息将跟随此更改。
在Visual Studio下更奇怪的是,这些错误导致错误报告,但是项目文件已成功重新生成,并且一切正常。我不能忍受它,因为它会在Jenkins机器上导致构建问题。
这是CommonLibrary
与其他目标链接的方式,例如:
add_executable(TestApp
<Test app sources>
)
target_link_libraries(TestApp
PRIVATE
fmt::fmt-header-only
CommonLibrary
SomeOtherLibrary
)