我试图说服cmake添加一个在Visual Studio上构建预编译头的自定义目标(注意:请不要建议我使用自定义构建步骤,我特别需要构建目标< / strong>构建预编译头文件。请注意,您不能简单地在配置阶段添加CMAKE_CXX_FLAGS _ $ {CMAKE_BUILD_TYPE},因为在用户可以更改构建配置的生成的.vcxproj中无法工作,因此我需要以某种方式告诉cmake在其构建中阶段为每个可能的配置输出正确的东西,即适当的配置CMAKE_CXX_FLAGS和CMAKE_CXX_FLAGS _ $&lt; CMAKE_BUILD_TYPE&gt;
我几乎已经有了这个解决方案,除了我要求帮助的一个问题:
# Adds a custom target which generates a precompiled header
function(add_precompiled_header outvar headerpath)
get_filename_component(header "${headerpath}" NAME)
set(pchpath ${CMAKE_CURRENT_BINARY_DIR}/${header}.dir/${CMAKE_CFG_INTDIR}/${header}.pch)
set(flags ${CMAKE_CXX_FLAGS})
separate_arguments(flags)
set(flags ${flags}
$<$<CONFIG:Debug>:${CMAKE_CXX_FLAGS_DEBUG}>
$<$<CONFIG:Release>:${CMAKE_CXX_FLAGS_RELEASE}>
$<$<CONFIG:RelWithDebInfo>:${CMAKE_CXX_FLAGS_RELWITHDEBINFO}>
$<$<CONFIG:MinSizeRel>:${CMAKE_CXX_FLAGS_MINSIZEREL}>
)
if(MSVC)
add_custom_target(${outvar}
COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/${header}.dir/${CMAKE_CFG_INTDIR}"
COMMAND ${CMAKE_CXX_COMPILER} /c ${flags} /Fp"${pchpath}" /Yc"${header}" /Tp"${CMAKE_CURRENT_SOURCE_DIR}/${headerpath}"
COMMENT "Precompiling header ${headerpath} ..."
SOURCES "${headerpath}"
)
endif()
endfunction()
这几乎适用于每个构建配置的正确标志已扩展到.vcxproj文件中各自的命令节的位置:
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">setlocal
"G:\Program Files\CMake\bin\cmake.exe" -E make_directory G:/boost.afio/cmake/afio.hpp.dir/$(Configuration)
if %errorlevel% neq 0 goto :cmEnd
"G:\Program Files\Microsoft Visual Studio 14.0\VC\bin\cl.exe" /c /DWIN32 /D_WINDOWS /W3 /GR /EHsc "/MD /O2 /Ob2 /D NDEBUG" /Fp"G:/boost.afio/cmake/afio.hpp.dir/$(Configuration)/afio.hpp.pch" /Yc"afio.hpp" /Tp"G:/boost.afio/include/boost/afio/afio.hpp"
if %errorlevel% neq 0 goto :cmEnd
:cmEnd
endlocal & call :cmErrorLevel %errorlevel% & goto :cmDone
:cmErrorLevel
exit /b %1
:cmDone
if %errorlevel% neq 0 goto :VCEnd
</Command>
问题是由于包含空格而导致的生成器$<$<CONFIG:Release>:${CMAKE_CXX_FLAGS_RELEASE}>
扩展为带引号的字符串"/MD /O2 /Ob2 /D NDEBUG"
,这当然会导致编译器大声抱怨。
因此我需要的是:
之一OR
非常感谢提前。
编辑:根据Tsyvarev的回答,我想出了这个:
# Add generator expressions to appendvar expanding at build time any remaining parameters
# if the build configuration is config
function(expand_at_build_if_config config appendvar)
set(ret ${${appendvar}})
set(items ${ARGV})
list(REMOVE_AT items 0 1)
separate_arguments(items)
foreach(item ${items})
list(APPEND ret $<$<CONFIG:${config}>:${item}>)
endforeach()
set(${appendvar} ${ret} PARENT_SCOPE)
endfunction()
这很好用。非常感谢Tsyvarev!
编辑2 :事实证明,至少对于MSVC,cmake对预编译的头文件生成没有文档支持。看一下https://github.com/ned14/boost-lite/blob/master/cmake/BoostLitePrecompiledHeader.cmake中的add_precompiled_header()
函数,您需要做的就是将/Yc
标志提供给OBJECT类型库,并且Visual Studio生成器做正确的事情,正确.vcxproj XML节和所有。
答案 0 :(得分:3)
按空格拆分 FLAGS ,并为每个标记追加相应的生成器表达式:
# Process Release flags.
set(FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE})
separate_arguments(FLAGS_RELEASE) # Flags are ready for iterate
foreach(FLAG_RELEASE ${FLAGS_RELEASE})
list(APPEND flags $<$<CONFIG:Release>:${FLAG_RELEASE}>)
endforeach(FLAGS_RELEASE ${FLAGS_RELEASE})
# Flags for other build types are processed in the same way.
# ...
# Now 'flags' variable may be used for COMMAND
答案 1 :(得分:1)
我已经给了@ Tsyvarev的答案一试,它确实运作得很好。
一般来说,您遇到的问题在CMake本身被视为错误或功能请求。您可能希望将支持添加到仍然打开的CMake Issue #14353。
当编译器选项的生成器表达式不能解决时,我只想使用response files添加一个简单的替代方法:
file(
WRITE "${CMAKE_CURRENT_BINARY_DIR}/Debug.flags"
"${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_DEBUG}"
)
file(
WRITE "${CMAKE_CURRENT_BINARY_DIR}/Release.flags"
"${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELEASE}"
)
file(
WRITE "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo.flags"
"${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}"
)
file(
WRITE "${CMAKE_CURRENT_BINARY_DIR}/MinSizeRel.flags"
"${CMAKE_CXX_FLAGS} ${CMAKE_CXX_FLAGS_MINSIZEREL}"
)
# Now 'flags' files may be used for COMMAND
add_custom_target(
${outvar}
COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/${header}.dir/${CMAKE_CFG_INTDIR}"
COMMAND ${CMAKE_CXX_COMPILER} /c @$<CONFIG>.flags /Fp"${pchpath}" /Yc"${header}" /Tp"${CMAKE_CURRENT_SOURCE_DIR}/${headerpath}"
COMMENT "Precompiling header ${headerpath} ..."
SOURCES "${headerpath}"
)
<强>参考强>