summaryrefslogtreecommitdiff
path: root/Tests/ConfigSources/CMakeLists.txt
blob: 38475f86dcd8530da5b7e08f3bde34045f66a5bb (plain)
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
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)


# ---------------------------------------------------------------------------
# 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>"
  )