1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
|
cmake_minimum_required(VERSION 3.10)
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>"
)
|