CMakeLists.txt 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. cmake_minimum_required(VERSION 3.0)
  2. get_property(_isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
  3. if(NOT _isMultiConfig AND NOT CMAKE_BUILD_TYPE)
  4. set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build" FORCE)
  5. endif()
  6. project(ConfigSources CXX)
  7. if("${CMAKE_CXX_COMPILER_ID};${CMAKE_CXX_SIMULATE_ID}" STREQUAL "Intel;MSVC")
  8. string(APPEND CMAKE_CXX_FLAGS_DEBUG " -Z7")
  9. string(APPEND CMAKE_CXX_FLAGS_RELWITHDEBINFO " -Z7")
  10. endif()
  11. # Source file(s) named with the configuration(s).
  12. file(GENERATE
  13. OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/config_$<CONFIG>.cpp"
  14. CONTENT [[
  15. #if defined(_WIN32) && defined(OBJ_SHARED)
  16. __declspec(dllexport)
  17. #endif
  18. void config_$<CONFIG>() {}
  19. ]]
  20. )
  21. # Custom command outputs named with the configuration(s).
  22. add_custom_command(
  23. OUTPUT "custom1_$<CONFIG>.cpp"
  24. COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/custom1.cpp.in" "custom1_$<CONFIG>.cpp"
  25. DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/custom1.cpp.in
  26. VERBATIM
  27. )
  28. # Output path starts in a generator expression.
  29. add_custom_command(
  30. OUTPUT "$<1:custom2_$<CONFIG>.cpp>"
  31. COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/custom2.cpp.in" "custom2_$<CONFIG>.cpp"
  32. DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/custom2.cpp.in
  33. VERBATIM
  34. )
  35. # Source file generated as a custom command's byproduct.
  36. add_custom_command(
  37. OUTPUT custom3.txt
  38. BYPRODUCTS "$<1:custom3_$<CONFIG>.cpp>"
  39. COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/custom3.cpp.in" "custom3_$<CONFIG>.cpp"
  40. COMMAND ${CMAKE_COMMAND} -E touch custom3.txt
  41. DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/custom3.cpp.in
  42. VERBATIM
  43. )
  44. # Source file generated as a custom target's byproduct.
  45. add_custom_target(custom4
  46. BYPRODUCTS "custom4_$<CONFIG>.cpp"
  47. COMMAND ${CMAKE_COMMAND} -E copy_if_different "${CMAKE_CURRENT_SOURCE_DIR}/custom4.cpp.in" "custom4_$<CONFIG>.cpp"
  48. VERBATIM
  49. )
  50. # Source file generated by appended custom command.
  51. add_custom_command(
  52. OUTPUT "custom5_$<CONFIG>.cpp"
  53. COMMAND ${CMAKE_COMMAND} -E echo custom5_$<CONFIG>.cpp
  54. DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/custom5.cpp.in
  55. VERBATIM
  56. )
  57. add_custom_command(APPEND
  58. OUTPUT "custom5_$<CONFIG>.cpp"
  59. COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_CURRENT_SOURCE_DIR}/custom5.cpp.in" "custom5_$<CONFIG>.cpp.in"
  60. VERBATIM
  61. )
  62. # Appending through any configuration's output affects all configurations.
  63. if(CMAKE_CONFIGURATION_TYPES MATCHES ";([^;]+)$")
  64. set(last_config "${CMAKE_MATCH_1}")
  65. else()
  66. set(last_config ${CMAKE_BUILD_TYPE})
  67. endif()
  68. add_custom_command(APPEND
  69. OUTPUT "custom5_${last_config}.cpp"
  70. COMMAND ${CMAKE_COMMAND} -E copy "custom5_$<CONFIG>.cpp.in" "custom5_$<CONFIG>.cpp"
  71. VERBATIM
  72. )
  73. foreach(n RANGE 1 5)
  74. set_property(SOURCE custom${n}_Debug.cpp PROPERTY COMPILE_DEFINITIONS CUSTOM_CFG_DEBUG)
  75. foreach(other Release RelWithDebInfo MinSizeRel)
  76. set_property(SOURCE custom${n}_${other}.cpp PROPERTY COMPILE_DEFINITIONS CUSTOM_CFG_OTHER)
  77. endforeach()
  78. endforeach()
  79. add_library(Custom STATIC
  80. custom1_$<CONFIG>.cpp
  81. custom2_$<CONFIG>.cpp
  82. custom3_$<CONFIG>.cpp custom3.txt
  83. custom4_$<CONFIG>.cpp
  84. custom5_$<CONFIG>.cpp
  85. )
  86. # Per-config sources via INTERFACE_SOURCES.
  87. add_library(iface INTERFACE)
  88. target_sources(iface INTERFACE
  89. "${CMAKE_CURRENT_SOURCE_DIR}/iface_src.cpp"
  90. "$<$<CONFIG:Debug>:${CMAKE_CURRENT_SOURCE_DIR}/iface_debug_src.cpp>"
  91. "$<$<NOT:$<CONFIG:Debug>>:${CMAKE_CURRENT_SOURCE_DIR}/iface_other_src.cpp>"
  92. "$<$<CONFIG:NotAConfig>:${CMAKE_CURRENT_SOURCE_DIR}/does_not_exist.cpp>"
  93. )
  94. target_compile_definitions(iface INTERFACE
  95. "$<$<CONFIG:Debug>:CFG_DEBUG>"
  96. "$<$<NOT:$<CONFIG:Debug>>:CFG_OTHER>"
  97. )
  98. add_executable(ConfigSources
  99. $<$<CONFIG:Debug>:main_debug.cpp>
  100. $<$<NOT:$<CONFIG:Debug>>:main_other.cpp>
  101. $<$<CONFIG:NotAConfig>:does_not_exist.cpp>
  102. ${CMAKE_CURRENT_BINARY_DIR}/config_$<CONFIG>.cpp
  103. )
  104. target_link_libraries(ConfigSources Custom iface)
  105. # Per-config sources via LINK_LIBRARIES.
  106. add_library(iface_debug INTERFACE)
  107. target_sources(iface_debug INTERFACE
  108. "${CMAKE_CURRENT_SOURCE_DIR}/iface_src.cpp"
  109. "${CMAKE_CURRENT_SOURCE_DIR}/iface_debug_src.cpp"
  110. )
  111. add_library(iface_other INTERFACE)
  112. target_sources(iface_other INTERFACE
  113. "${CMAKE_CURRENT_SOURCE_DIR}/iface_src.cpp"
  114. "${CMAKE_CURRENT_SOURCE_DIR}/iface_other_src.cpp"
  115. )
  116. add_executable(ConfigSourcesLink main.cpp)
  117. target_compile_definitions(ConfigSourcesLink PRIVATE
  118. "$<$<CONFIG:Debug>:CFG_DEBUG>"
  119. "$<$<NOT:$<CONFIG:Debug>>:CFG_OTHER>"
  120. )
  121. target_link_libraries(ConfigSourcesLink PRIVATE
  122. Custom
  123. "$<$<CONFIG:Debug>:iface_debug>"
  124. "$<$<NOT:$<CONFIG:Debug>>:iface_other>"
  125. "$<$<CONFIG:NotAConfig>:iface_does_not_exist>"
  126. )
  127. # Per-config sources via INTERFACE_LINK_LIBRARIES.
  128. add_library(ConfigSourcesIface INTERFACE)
  129. target_link_libraries(ConfigSourcesIface INTERFACE
  130. "$<$<CONFIG:Debug>:iface_debug>"
  131. "$<$<NOT:$<CONFIG:Debug>>:iface_other>"
  132. "$<$<CONFIG:NotAConfig>:iface_does_not_exist>"
  133. )
  134. add_executable(ConfigSourcesLinkIface main.cpp)
  135. target_compile_definitions(ConfigSourcesLinkIface PRIVATE
  136. "$<$<CONFIG:Debug>:CFG_DEBUG>"
  137. "$<$<NOT:$<CONFIG:Debug>>:CFG_OTHER>"
  138. )
  139. target_link_libraries(ConfigSourcesLinkIface Custom ConfigSourcesIface)
  140. # A target with sources in only one configuration that is not the
  141. # first in CMAKE_CONFIGURATION_TYPES.
  142. if(CMAKE_CONFIGURATION_TYPES MATCHES ";([^;]+)")
  143. set(one_config "${CMAKE_MATCH_1}")
  144. else()
  145. set(one_config "${CMAKE_BUILD_TYPE}")
  146. endif()
  147. add_library(OneConfigOnly OBJECT "$<$<CONFIG:${one_config}>:${CMAKE_CURRENT_SOURCE_DIR}/iface_src.cpp>")
  148. set_property(TARGET OneConfigOnly PROPERTY LINKER_LANGUAGE CXX)
  149. # ---------------------------------------------------------------------------
  150. # Makes sure that each configuration uses the correct generated file.
  151. add_library(ObjLibFromGeneratedSources OBJECT)
  152. set_property(TARGET ObjLibFromGeneratedSources PROPERTY POSITION_INDEPENDENT_CODE 1)
  153. target_compile_definitions(ObjLibFromGeneratedSources PRIVATE OBJ_SHARED)
  154. target_sources(ObjLibFromGeneratedSources PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/config_$<CONFIG>.cpp)
  155. add_library(SharedLibFromObjLibFromGeneratedSources SHARED shared.cpp)
  156. target_link_libraries(SharedLibFromObjLibFromGeneratedSources PRIVATE ObjLibFromGeneratedSources)
  157. # ---------------------------------------------------------------------------
  158. # Make sure that additional build-events do not confuse CMake when using generated files.
  159. add_library(SharedLibFromGeneratedSources SHARED)
  160. set_property(TARGET SharedLibFromGeneratedSources PROPERTY POSITION_INDEPENDENT_CODE 1)
  161. target_sources(SharedLibFromGeneratedSources PRIVATE
  162. shared.cpp
  163. ${CMAKE_CURRENT_BINARY_DIR}/config_$<CONFIG>.cpp
  164. )
  165. add_custom_command(TARGET SharedLibFromGeneratedSources POST_BUILD
  166. COMMAND "${CMAKE_COMMAND}" "-E" "echo" "$<TARGET_FILE:SharedLibFromGeneratedSources>"
  167. )