mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-06 05:40:54 -06:00
Since commit b1c3ae33ea (cmTarget: Short-circuit language computation if
context independent., 2014-04-09, v3.1.0-rc1~669^2~1) we've tried to
avoid repeating computation of the list of sources for a target for
every configuration in the case that a per-config source (or object
library) contributes zero sources. However, it is possible that an
entry contributes zero sources in the first configuration processed but
at least one source in other configurations.
Fixes: #25400
188 lines
7.3 KiB
CMake
188 lines
7.3 KiB
CMake
cmake_minimum_required(VERSION 3.0)
|
|
get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
|
|
|
if(NOT _isMultiConfig AND NOT CMAKE_BUILD_TYPE)
|
|
set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build" FORCE)
|
|
endif()
|
|
project(ConfigSources CXX)
|
|
|
|
if("${CMAKE_CXX_COMPILER_ID};${CMAKE_CXX_SIMULATE_ID}" STREQUAL "Intel;MSVC")
|
|
string(APPEND CMAKE_CXX_FLAGS_DEBUG " -Z7")
|
|
string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " -Z7")
|
|
endif()
|
|
|
|
# Source file(s) named with the configuration(s).
|
|
file(GENERATE
|
|
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/config_$<CONFIG>.cpp"
|
|
CONTENT [[
|
|
#if defined(_WIN32) && defined(OBJ_SHARED)
|
|
__declspec(dllexport)
|
|
#endif
|
|
void config_$<CONFIG>() {}
|
|
]]
|
|
)
|
|
|
|
# Custom command outputs named with the configuration(s).
|
|
add_custom_command(
|
|
OUTPUT "custom1_$<CONFIG>.cpp"
|
|
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/custom1.cpp.in" "custom1_$<CONFIG>.cpp"
|
|
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/custom1.cpp.in
|
|
VERBATIM
|
|
)
|
|
# Output path starts in a generator expression.
|
|
add_custom_command(
|
|
OUTPUT "$<1:custom2_$<CONFIG>.cpp>"
|
|
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/custom2.cpp.in" "custom2_$<CONFIG>.cpp"
|
|
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/custom2.cpp.in
|
|
VERBATIM
|
|
)
|
|
# Source file generated as a custom command's byproduct.
|
|
add_custom_command(
|
|
OUTPUT custom3.txt
|
|
BYPRODUCTS "$<1:custom3_$<CONFIG>.cpp>"
|
|
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/custom3.cpp.in" "custom3_$<CONFIG>.cpp"
|
|
COMMAND ${CMAKE_COMMAND} -E touch custom3.txt
|
|
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/custom3.cpp.in
|
|
VERBATIM
|
|
)
|
|
# Source file generated as a custom target's byproduct.
|
|
add_custom_target(custom4
|
|
BYPRODUCTS "custom4_$<CONFIG>.cpp"
|
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/custom4.cpp.in" "custom4_$<CONFIG>.cpp"
|
|
VERBATIM
|
|
)
|
|
# Source file generated by appended custom command.
|
|
add_custom_command(
|
|
OUTPUT "custom5_$<CONFIG>.cpp"
|
|
COMMAND ${CMAKE_COMMAND} -E echo custom5_$<CONFIG>.cpp
|
|
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/custom5.cpp.in
|
|
VERBATIM
|
|
)
|
|
add_custom_command(APPEND
|
|
OUTPUT "custom5_$<CONFIG>.cpp"
|
|
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/custom5.cpp.in" "custom5_$<CONFIG>.cpp.in"
|
|
VERBATIM
|
|
)
|
|
# Appending through any configuration's output affects all configurations.
|
|
if(CMAKE_CONFIGURATION_TYPES MATCHES ";([^;]+)$")
|
|
set(last_config "${CMAKE_MATCH_1}")
|
|
else()
|
|
set(last_config ${CMAKE_BUILD_TYPE})
|
|
endif()
|
|
add_custom_command(APPEND
|
|
OUTPUT "custom5_${last_config}.cpp"
|
|
COMMAND ${CMAKE_COMMAND} -E copy "custom5_$<CONFIG>.cpp.in" "custom5_$<CONFIG>.cpp"
|
|
VERBATIM
|
|
)
|
|
foreach(n RANGE 1 5)
|
|
foreach(other ${CMAKE_BUILD_TYPE} Release RelWithDebInfo MinSizeRel)
|
|
set_property(SOURCE custom${n}_${other}.cpp PROPERTY COMPILE_DEFINITIONS CUSTOM_CFG_OTHER)
|
|
endforeach()
|
|
set_property(SOURCE custom${n}_Debug.cpp PROPERTY COMPILE_DEFINITIONS CUSTOM_CFG_DEBUG)
|
|
endforeach()
|
|
add_library(Custom STATIC
|
|
custom1_$<CONFIG>.cpp
|
|
custom2_$<CONFIG>.cpp
|
|
custom3_$<CONFIG>.cpp custom3.txt
|
|
custom4_$<CONFIG>.cpp
|
|
custom5_$<CONFIG>.cpp
|
|
)
|
|
|
|
# Per-config sources via INTERFACE_SOURCES.
|
|
add_library(iface INTERFACE)
|
|
target_sources(iface INTERFACE
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/iface_src.cpp"
|
|
"$<$<CONFIG:Debug>:${CMAKE_CURRENT_SOURCE_DIR}/iface_debug_src.cpp>"
|
|
"$<$<NOT:$<CONFIG:Debug>>:${CMAKE_CURRENT_SOURCE_DIR}/iface_other_src.cpp>"
|
|
"$<$<CONFIG:NotAConfig>:${CMAKE_CURRENT_SOURCE_DIR}/does_not_exist.cpp>"
|
|
)
|
|
target_compile_definitions(iface INTERFACE
|
|
"$<$<CONFIG:Debug>:CFG_DEBUG>"
|
|
"$<$<NOT:$<CONFIG:Debug>>:CFG_OTHER>"
|
|
)
|
|
add_executable(ConfigSources
|
|
$<$<CONFIG:Debug>:main_debug.cpp>
|
|
$<$<NOT:$<CONFIG:Debug>>:main_other.cpp>
|
|
$<$<CONFIG:NotAConfig>:does_not_exist.cpp>
|
|
${CMAKE_CURRENT_BINARY_DIR}/config_$<CONFIG>.cpp
|
|
)
|
|
target_link_libraries(ConfigSources Custom iface)
|
|
|
|
# Per-config sources via LINK_LIBRARIES.
|
|
add_library(iface_debug INTERFACE)
|
|
target_sources(iface_debug INTERFACE
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/iface_src.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/iface_debug_src.cpp"
|
|
)
|
|
add_library(iface_other INTERFACE)
|
|
target_sources(iface_other INTERFACE
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/iface_src.cpp"
|
|
"${CMAKE_CURRENT_SOURCE_DIR}/iface_other_src.cpp"
|
|
)
|
|
add_executable(ConfigSourcesLink main.cpp)
|
|
target_compile_definitions(ConfigSourcesLink PRIVATE
|
|
"$<$<CONFIG:Debug>:CFG_DEBUG>"
|
|
"$<$<NOT:$<CONFIG:Debug>>:CFG_OTHER>"
|
|
)
|
|
target_link_libraries(ConfigSourcesLink PRIVATE
|
|
Custom
|
|
"$<$<CONFIG:Debug>:iface_debug>"
|
|
"$<$<NOT:$<CONFIG:Debug>>:iface_other>"
|
|
"$<$<CONFIG:NotAConfig>:iface_does_not_exist>"
|
|
)
|
|
|
|
# Per-config sources via INTERFACE_LINK_LIBRARIES.
|
|
add_library(ConfigSourcesIface INTERFACE)
|
|
target_link_libraries(ConfigSourcesIface INTERFACE
|
|
"$<$<CONFIG:Debug>:iface_debug>"
|
|
"$<$<NOT:$<CONFIG:Debug>>:iface_other>"
|
|
"$<$<CONFIG:NotAConfig>:iface_does_not_exist>"
|
|
)
|
|
add_executable(ConfigSourcesLinkIface main.cpp)
|
|
target_compile_definitions(ConfigSourcesLinkIface PRIVATE
|
|
"$<$<CONFIG:Debug>:CFG_DEBUG>"
|
|
"$<$<NOT:$<CONFIG:Debug>>:CFG_OTHER>"
|
|
)
|
|
target_link_libraries(ConfigSourcesLinkIface Custom ConfigSourcesIface)
|
|
|
|
# A target with sources in only one configuration that is not the
|
|
# first in CMAKE_CONFIGURATION_TYPES.
|
|
if(CMAKE_CONFIGURATION_TYPES MATCHES ";([^;]+)")
|
|
set(one_config "${CMAKE_MATCH_1}")
|
|
else()
|
|
set(one_config "${CMAKE_BUILD_TYPE}")
|
|
endif()
|
|
add_library(OneConfigOnly OBJECT "$<$<CONFIG:${one_config}>:${CMAKE_CURRENT_SOURCE_DIR}/iface_src.cpp>")
|
|
set_property(TARGET OneConfigOnly PROPERTY LINKER_LANGUAGE CXX)
|
|
add_executable(ConfigSourcesUseOne main_one_config.cpp)
|
|
target_compile_definitions(ConfigSourcesUseOne PRIVATE "$<$<CONFIG:${one_config}>:CFG_ONE>")
|
|
target_link_libraries(ConfigSourcesUseOne PRIVATE "$<$<CONFIG:${one_config}>:OneConfigOnly>")
|
|
|
|
add_library(OneConfigOnlyIface INTERFACE)
|
|
target_sources(OneConfigOnlyIface INTERFACE "$<$<CONFIG:${one_config}>:${CMAKE_CURRENT_SOURCE_DIR}/iface_src.cpp>")
|
|
add_executable(ConfigSourcesUseOneIface main_one_config.cpp)
|
|
target_compile_definitions(ConfigSourcesUseOneIface PRIVATE "$<$<CONFIG:${one_config}>:CFG_ONE>")
|
|
target_link_libraries(ConfigSourcesUseOneIface PRIVATE "$<$<CONFIG:${one_config}>:OneConfigOnlyIface>")
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Makes sure that each configuration uses the correct generated file.
|
|
add_library(ObjLibFromGeneratedSources OBJECT)
|
|
set_property(TARGET ObjLibFromGeneratedSources PROPERTY POSITION_INDEPENDENT_CODE 1)
|
|
target_compile_definitions(ObjLibFromGeneratedSources PRIVATE OBJ_SHARED)
|
|
target_sources(ObjLibFromGeneratedSources PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/config_$<CONFIG>.cpp)
|
|
add_library(SharedLibFromObjLibFromGeneratedSources SHARED shared.cpp)
|
|
target_link_libraries(SharedLibFromObjLibFromGeneratedSources PRIVATE ObjLibFromGeneratedSources)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Make sure that additional build-events do not confuse CMake when using generated files.
|
|
add_library(SharedLibFromGeneratedSources SHARED)
|
|
set_property(TARGET SharedLibFromGeneratedSources PROPERTY POSITION_INDEPENDENT_CODE 1)
|
|
target_sources(SharedLibFromGeneratedSources PRIVATE
|
|
shared.cpp
|
|
${CMAKE_CURRENT_BINARY_DIR}/config_$<CONFIG>.cpp
|
|
)
|
|
add_custom_command(TARGET SharedLibFromGeneratedSources POST_BUILD
|
|
COMMAND "${CMAKE_COMMAND}" "-E" "echo" "$<TARGET_FILE:SharedLibFromGeneratedSources>"
|
|
)
|