Utils.cmake 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. # utils file for projects came from visual studio solution with cmake-converter.
  2. ################################################################################
  3. # Wrap each token of the command with condition
  4. ################################################################################
  5. cmake_policy(PUSH)
  6. cmake_policy(SET CMP0054 NEW)
  7. macro(prepare_commands)
  8. unset(TOKEN_ROLE)
  9. unset(COMMANDS)
  10. foreach(TOKEN ${ARG_COMMANDS})
  11. if("${TOKEN}" STREQUAL "COMMAND")
  12. set(TOKEN_ROLE "KEYWORD")
  13. elseif("${TOKEN_ROLE}" STREQUAL "KEYWORD")
  14. set(TOKEN_ROLE "CONDITION")
  15. elseif("${TOKEN_ROLE}" STREQUAL "CONDITION")
  16. set(TOKEN_ROLE "COMMAND")
  17. elseif("${TOKEN_ROLE}" STREQUAL "COMMAND")
  18. set(TOKEN_ROLE "ARG")
  19. endif()
  20. if("${TOKEN_ROLE}" STREQUAL "KEYWORD")
  21. list(APPEND COMMANDS "${TOKEN}")
  22. elseif("${TOKEN_ROLE}" STREQUAL "CONDITION")
  23. set(CONDITION ${TOKEN})
  24. elseif("${TOKEN_ROLE}" STREQUAL "COMMAND")
  25. list(APPEND COMMANDS "$<$<NOT:${CONDITION}>:${DUMMY}>$<${CONDITION}:${TOKEN}>")
  26. elseif("${TOKEN_ROLE}" STREQUAL "ARG")
  27. list(APPEND COMMANDS "$<${CONDITION}:${TOKEN}>")
  28. endif()
  29. endforeach()
  30. endmacro()
  31. cmake_policy(POP)
  32. ################################################################################
  33. # Transform all the tokens to absolute paths
  34. ################################################################################
  35. macro(prepare_output)
  36. unset(OUTPUT)
  37. foreach(TOKEN ${ARG_OUTPUT})
  38. if(IS_ABSOLUTE ${TOKEN})
  39. list(APPEND OUTPUT "${TOKEN}")
  40. else()
  41. list(APPEND OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/${TOKEN}")
  42. endif()
  43. endforeach()
  44. endmacro()
  45. ################################################################################
  46. # Parse add_custom_command_if args.
  47. #
  48. # Input:
  49. # PRE_BUILD - Pre build event option
  50. # PRE_LINK - Pre link event option
  51. # POST_BUILD - Post build event option
  52. # TARGET - Target
  53. # OUTPUT - List of output files
  54. # DEPENDS - List of files on which the command depends
  55. # COMMANDS - List of commands(COMMAND condition1 commannd1 args1 COMMAND
  56. # condition2 commannd2 args2 ...)
  57. # Output:
  58. # OUTPUT - Output files
  59. # DEPENDS - Files on which the command depends
  60. # COMMENT - Comment
  61. # PRE_BUILD - TRUE/FALSE
  62. # PRE_LINK - TRUE/FALSE
  63. # POST_BUILD - TRUE/FALSE
  64. # TARGET - Target name
  65. # COMMANDS - Prepared commands(every token is wrapped in CONDITION)
  66. # NAME - Unique name for custom target
  67. # STEP - PRE_BUILD/PRE_LINK/POST_BUILD
  68. ################################################################################
  69. function(add_custom_command_if_parse_arguments)
  70. cmake_parse_arguments("ARG" "PRE_BUILD;PRE_LINK;POST_BUILD" "TARGET;COMMENT" "DEPENDS;OUTPUT;COMMANDS" ${ARGN})
  71. if(WIN32)
  72. set(DUMMY "cd.")
  73. elseif(UNIX)
  74. set(DUMMY "true")
  75. endif()
  76. prepare_commands()
  77. prepare_output()
  78. set(DEPENDS "${ARG_DEPENDS}")
  79. set(COMMENT "${ARG_COMMENT}")
  80. set(PRE_BUILD "${ARG_PRE_BUILD}")
  81. set(PRE_LINK "${ARG_PRE_LINK}")
  82. set(POST_BUILD "${ARG_POST_BUILD}")
  83. set(TARGET "${ARG_TARGET}")
  84. if(PRE_BUILD)
  85. set(STEP "PRE_BUILD")
  86. elseif(PRE_LINK)
  87. set(STEP "PRE_LINK")
  88. elseif(POST_BUILD)
  89. set(STEP "POST_BUILD")
  90. endif()
  91. set(NAME "${TARGET}_${STEP}")
  92. set(OUTPUT "${OUTPUT}" PARENT_SCOPE)
  93. set(DEPENDS "${DEPENDS}" PARENT_SCOPE)
  94. set(COMMENT "${COMMENT}" PARENT_SCOPE)
  95. set(PRE_BUILD "${PRE_BUILD}" PARENT_SCOPE)
  96. set(PRE_LINK "${PRE_LINK}" PARENT_SCOPE)
  97. set(POST_BUILD "${POST_BUILD}" PARENT_SCOPE)
  98. set(TARGET "${TARGET}" PARENT_SCOPE)
  99. set(COMMANDS "${COMMANDS}" PARENT_SCOPE)
  100. set(STEP "${STEP}" PARENT_SCOPE)
  101. set(NAME "${NAME}" PARENT_SCOPE)
  102. endfunction()
  103. ################################################################################
  104. # Add conditional custom command
  105. #
  106. # Generating Files
  107. # The first signature is for adding a custom command to produce an output:
  108. # add_custom_command_if(
  109. # <OUTPUT output1 [output2 ...]>
  110. # <COMMANDS>
  111. # <COMMAND condition command1 [args1...]>
  112. # [COMMAND condition command2 [args2...]]
  113. # [DEPENDS [depends...]]
  114. # [COMMENT comment]
  115. #
  116. # Build Events
  117. # add_custom_command_if(
  118. # <TARGET target>
  119. # <PRE_BUILD | PRE_LINK | POST_BUILD>
  120. # <COMMAND condition command1 [args1...]>
  121. # [COMMAND condition command2 [args2...]]
  122. # [COMMENT comment]
  123. #
  124. # Input:
  125. # output - Output files the command is expected to produce
  126. # condition - Generator expression for wrapping the command
  127. # command - Command-line(s) to execute at build time.
  128. # args - Command`s args
  129. # depends - Files on which the command depends
  130. # comment - Display the given message before the commands are executed at
  131. # build time.
  132. # PRE_BUILD - Run before any other rules are executed within the target
  133. # PRE_LINK - Run after sources have been compiled but before linking the
  134. # binary
  135. # POST_BUILD - Run after all other rules within the target have been
  136. # executed
  137. ################################################################################
  138. function(add_custom_command_if)
  139. add_custom_command_if_parse_arguments(${ARGN})
  140. if(OUTPUT AND TARGET)
  141. message(FATAL_ERROR "Wrong syntax. A TARGET and OUTPUT can not both be specified.")
  142. endif()
  143. if(OUTPUT)
  144. add_custom_command(OUTPUT ${OUTPUT}
  145. ${COMMANDS}
  146. DEPENDS ${DEPENDS}
  147. WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
  148. COMMENT ${COMMENT})
  149. elseif(TARGET)
  150. if(PRE_BUILD AND NOT ${CMAKE_GENERATOR} MATCHES "Visual Studio")
  151. add_custom_target(
  152. ${NAME}
  153. ${COMMANDS}
  154. WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
  155. COMMENT ${COMMENT})
  156. add_dependencies(${TARGET} ${NAME})
  157. else()
  158. add_custom_command(
  159. TARGET ${TARGET}
  160. ${STEP}
  161. ${COMMANDS}
  162. WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
  163. COMMENT ${COMMENT})
  164. endif()
  165. else()
  166. message(FATAL_ERROR "Wrong syntax. A TARGET or OUTPUT must be specified.")
  167. endif()
  168. endfunction()
  169. ################################################################################
  170. # Use props file for a target and configs
  171. # use_props(<target> <configs...> <props_file>)
  172. # Inside <props_file> there are following variables:
  173. # PROPS_TARGET - <target>
  174. # PROPS_CONFIG - One of <configs...>
  175. # PROPS_CONFIG_U - Uppercase PROPS_CONFIG
  176. # Input:
  177. # target - Target to apply props file
  178. # configs - Build configurations to apply props file
  179. # props_file - CMake script
  180. ################################################################################
  181. macro(use_props TARGET CONFIGS PROPS_FILE)
  182. set(PROPS_TARGET "${TARGET}")
  183. foreach(PROPS_CONFIG ${CONFIGS})
  184. string(TOUPPER "${PROPS_CONFIG}" PROPS_CONFIG_U)
  185. get_filename_component(ABSOLUTE_PROPS_FILE "${PROPS_FILE}" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_LIST_DIR}")
  186. if(EXISTS "${ABSOLUTE_PROPS_FILE}")
  187. include("${ABSOLUTE_PROPS_FILE}")
  188. else()
  189. message(WARNING "Corresponding cmake file from props \"${ABSOLUTE_PROPS_FILE}\" doesn't exist")
  190. endif()
  191. endforeach()
  192. endmacro()
  193. ################################################################################
  194. # Add compile options to source file
  195. # source_file_compile_options(<source_file> [compile_options...])
  196. # Input:
  197. # source_file - Source file
  198. # compile_options - Options to add to COMPILE_FLAGS property
  199. ################################################################################
  200. function(source_file_compile_options SOURCE_FILE)
  201. if("${ARGC}" LESS_EQUAL "1")
  202. return()
  203. endif()
  204. get_source_file_property(COMPILE_OPTIONS "${SOURCE_FILE}" COMPILE_OPTIONS)
  205. if(COMPILE_OPTIONS)
  206. list(APPEND COMPILE_OPTIONS ${ARGN})
  207. else()
  208. set(COMPILE_OPTIONS "${ARGN}")
  209. endif()
  210. set_source_files_properties("${SOURCE_FILE}" PROPERTIES COMPILE_OPTIONS "${COMPILE_OPTIONS}")
  211. endfunction()
  212. ################################################################################
  213. # Default properties of visual studio projects
  214. ################################################################################
  215. set(DEFAULT_CXX_PROPS "${CMAKE_CURRENT_LIST_DIR}/DefaultCXX.cmake")