haiUtil.cmake 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. #
  2. # SRT - Secure, Reliable, Transport
  3. # Copyright (c) 2018 Haivision Systems Inc.
  4. #
  5. # This Source Code Form is subject to the terms of the Mozilla Public
  6. # License, v. 2.0. If a copy of the MPL was not distributed with this
  7. # file, You can obtain one at http://mozilla.org/MPL/2.0/.
  8. #
  9. include(CheckCXXSourceCompiles)
  10. # Useful for combinging paths
  11. function(adddirname prefix lst out_lst)
  12. set(output)
  13. foreach(item ${lst})
  14. list(APPEND output "${prefix}/${item}")
  15. endforeach()
  16. set(${out_lst} ${${out_lst}} ${output} PARENT_SCOPE)
  17. endfunction()
  18. # Splits a version formed as "major.minor.patch" recorded in variable 'prefix'
  19. # and writes it into variables started with 'prefix' and ended with _MAJOR, _MINOR and _PATCH.
  20. MACRO(set_version_variables prefix value)
  21. string(REPLACE "." ";" VERSION_LIST ${value})
  22. list(GET VERSION_LIST 0 ${prefix}_MAJOR)
  23. list(GET VERSION_LIST 1 ${prefix}_MINOR)
  24. list(GET VERSION_LIST 2 ${prefix}_PATCH)
  25. set(${prefix}_DEFINESTR "")
  26. ENDMACRO(set_version_variables)
  27. # Sets given variable to 1, if the condition that follows it is satisfied.
  28. # Otherwise set it to 0.
  29. MACRO(set_if varname)
  30. IF(${ARGN})
  31. SET(${varname} 1)
  32. ELSE(${ARGN})
  33. SET(${varname} 0)
  34. ENDIF(${ARGN})
  35. ENDMACRO(set_if)
  36. FUNCTION(join_arguments outvar)
  37. set (output)
  38. foreach (i ${ARGN})
  39. set(output "${output} ${i}")
  40. endforeach()
  41. set (${outvar} ${output} PARENT_SCOPE)
  42. ENDFUNCTION()
  43. # The directory specifies the location of maffile and
  44. # all files specified in the list.
  45. MACRO(MafReadDir directory maffile)
  46. # ARGN contains the extra "section-variable" pairs
  47. # If empty, return nothing
  48. set (MAFREAD_TAGS
  49. SOURCES # source files
  50. PUBLIC_HEADERS # installable headers for include
  51. PROTECTED_HEADERS # installable headers used by other headers
  52. PRIVATE_HEADERS # non-installable headers
  53. SOURCES_WIN32_SHARED # windows specific SOURCES
  54. PRIVATE_HEADERS_WIN32_SHARED # windows specific PRIVATE_HEADERS
  55. OPTIONS
  56. )
  57. cmake_parse_arguments(MAFREAD_VAR "" "${MAFREAD_TAGS}" "" ${ARGN})
  58. # Arguments for these tags are variables to be filled
  59. # with the contents of particular section.
  60. # While reading the file, extract the section.
  61. # Section is recognized by either first uppercase character or space.
  62. # @c http://cmake.org/pipermail/cmake/2007-May/014222.html
  63. FILE(READ ${directory}/${maffile} MAFREAD_CONTENTS)
  64. STRING(REGEX REPLACE ";" "\\\\;" MAFREAD_CONTENTS "${MAFREAD_CONTENTS}")
  65. STRING(REGEX REPLACE "\n" ";" MAFREAD_CONTENTS "${MAFREAD_CONTENTS}")
  66. # Once correctly read, declare this file as dependency of the build file.
  67. # Normally you should use cmake_configure_depends(), but this is
  68. # available only since 3.0 version.
  69. configure_file(${directory}/${maffile} dummy_${maffile}.cmake.out)
  70. file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/dummy_${maffile}.cmake.out)
  71. #message("DEBUG: MAF FILE CONTENTS: ${MAFREAD_CONTENTS}")
  72. #message("DEBUG: PASSED VARIABLES:")
  73. #foreach(DEBUG_VAR ${MAFREAD_TAGS})
  74. # message("DEBUG: ${DEBUG_VAR}=${MAFREAD_VAR_${DEBUG_VAR}}")
  75. #endforeach()
  76. # The unnamed section becomes SOURCES
  77. set (MAFREAD_VARIABLE ${MAFREAD_VAR_SOURCES})
  78. set (MAFREAD_UNASSIGNED "")
  79. # Default section type. Another is 'flags'.
  80. set (MAFREAD_SECTION_TYPE file)
  81. FOREACH(MAFREAD_LINE ${MAFREAD_CONTENTS})
  82. # Test what this line is
  83. string(STRIP ${MAFREAD_LINE} MAFREAD_OLINE)
  84. string(SUBSTRING ${MAFREAD_OLINE} 0 1 MAFREAD_FIRST)
  85. #message("DEBUG: LINE='${MAFREAD_LINE}' FIRST='${MAFREAD_FIRST}'")
  86. # The 'continue' command is cmake 3.2 - very late discovery
  87. if (MAFREAD_FIRST STREQUAL "")
  88. #message("DEBUG: ... skipped: empty")
  89. elseif (MAFREAD_FIRST STREQUAL "#")
  90. #message("DEBUG: ... skipped: comment")
  91. else()
  92. # Will be skipped if the line was a comment/empty
  93. string(REGEX MATCH "[ A-Z-]" MAFREAD_SECMARK ${MAFREAD_FIRST})
  94. if (MAFREAD_SECMARK STREQUAL "")
  95. # This isn't a section, it's a list element.
  96. #message("DEBUG: ITEM: ${MAFREAD_OLINE} --> ${MAFREAD_VARIABLE}")
  97. if (${MAFREAD_SECTION_TYPE} STREQUAL file)
  98. get_filename_component(MAFREAD_OLINE ${directory}/${MAFREAD_OLINE} ABSOLUTE)
  99. endif()
  100. set (MAFREAD_CONDITION_OK 1)
  101. if (DEFINED MAFREAD_CONDITION_LIST)
  102. FOREACH(MFITEM IN ITEMS ${MAFREAD_CONDITION_LIST})
  103. separate_arguments(MFITEM)
  104. FOREACH(MFVAR IN ITEMS ${MFITEM})
  105. STRING(SUBSTRING ${MFVAR} 0 1 MFPREFIX)
  106. if (MFPREFIX STREQUAL "!")
  107. STRING(SUBSTRING ${MFVAR} 1 -1 MFVAR)
  108. if (${MFVAR})
  109. set (MFCONDITION_RESULT 0)
  110. else()
  111. set (MFCONDITION_RESULT 1)
  112. endif()
  113. else()
  114. if (${MFVAR})
  115. set (MFCONDITION_RESULT 1)
  116. else()
  117. set (MFCONDITION_RESULT 0)
  118. endif()
  119. endif()
  120. #message("CONDITION: ${MFPREFIX} ${MFVAR} -> ${MFCONDITION_RESULT}")
  121. MATH(EXPR MAFREAD_CONDITION_OK "${MAFREAD_CONDITION_OK} & (${MFCONDITION_RESULT})")
  122. ENDFOREACH()
  123. ENDFOREACH()
  124. endif()
  125. if (MAFREAD_CONDITION_OK)
  126. LIST(APPEND ${MAFREAD_VARIABLE} ${MAFREAD_OLINE})
  127. else()
  128. #message("... NOT ADDED ITEM: ${MAFREAD_OLINE}")
  129. endif()
  130. else()
  131. # It's a section
  132. # Check for conditionals (clear current conditions first)
  133. unset(MAFREAD_CONDITION_LIST)
  134. STRING(FIND ${MAFREAD_OLINE} " -" MAFREAD_HAVE_CONDITION)
  135. if (NOT MAFREAD_HAVE_CONDITION EQUAL -1)
  136. # Cut off conditional specification, and
  137. # grab the section name and condition list
  138. STRING(REPLACE " -" ";" MAFREAD_CONDITION_LIST ${MAFREAD_OLINE})
  139. #message("CONDITION READ: ${MAFREAD_CONDITION_LIST}")
  140. LIST(GET MAFREAD_CONDITION_LIST 0 MAFREAD_OLINE)
  141. LIST(REMOVE_AT MAFREAD_CONDITION_LIST 0)
  142. #message("EXTRACTING SECTION=${MAFREAD_OLINE} CONDITIONS=${MAFREAD_CONDITION_LIST}")
  143. endif()
  144. # change the running variable
  145. # Make it section name
  146. STRING(REPLACE " " "_" MAFREAD_SECNAME ${MAFREAD_OLINE})
  147. #message("MAF SECTION: ${MAFREAD_SECNAME}")
  148. # The cmake's version of 'if (MAFREAD_SECNAME[0] == '-')' - sigh...
  149. string(SUBSTRING ${MAFREAD_SECNAME} 0 1 MAFREAD_SECNAME0)
  150. if (${MAFREAD_SECNAME0} STREQUAL "-")
  151. set (MAFREAD_SECTION_TYPE option)
  152. string(SUBSTRING ${MAFREAD_SECNAME} 1 -1 MAFREAD_SECNAME)
  153. else()
  154. set (MAFREAD_SECTION_TYPE file)
  155. endif()
  156. set(MAFREAD_VARIABLE ${MAFREAD_VAR_${MAFREAD_SECNAME}})
  157. if (MAFREAD_VARIABLE STREQUAL "")
  158. set(MAFREAD_VARIABLE MAFREAD_UNASSIGNED)
  159. endif()
  160. #message("DEBUG: NEW SECTION: '${MAFREAD_SECNAME}' --> VARIABLE: '${MAFREAD_VARIABLE}'")
  161. endif()
  162. endif()
  163. ENDFOREACH()
  164. # Final debug report
  165. #set (ALL_VARS "")
  166. #message("DEBUG: extracted variables:")
  167. #foreach(DEBUG_VAR ${MAFREAD_TAGS})
  168. # list(APPEND ALL_VARS ${MAFREAD_VAR_${DEBUG_VAR}})
  169. #endforeach()
  170. #list(REMOVE_DUPLICATES ALL_VARS)
  171. #foreach(DEBUG_VAR ${ALL_VARS})
  172. # message("DEBUG: --> ${DEBUG_VAR} = ${${DEBUG_VAR}}")
  173. #endforeach()
  174. ENDMACRO(MafReadDir)
  175. # NOTE: This is historical only. Not in use.
  176. # It should be a similar interface to mafread.tcl like
  177. # the above MafRead macro.
  178. MACRO(GetMafHeaders directory outvar)
  179. EXECUTE_PROCESS(
  180. COMMAND ${CMAKE_MODULE_PATH}/mafread.tcl
  181. ${CMAKE_SOURCE_DIR}/${directory}/HEADERS.maf
  182. "PUBLIC HEADERS"
  183. "PROTECTED HEADERS"
  184. OUTPUT_STRIP_TRAILING_WHITESPACE
  185. OUTPUT_VARIABLE ${outvar}
  186. )
  187. SEPARATE_ARGUMENTS(${outvar})
  188. adddirname(${CMAKE_SOURCE_DIR}/${directory} "${${outvar}}" ${outvar})
  189. ENDMACRO(GetMafHeaders)
  190. function (getVarsWith _prefix _varResult)
  191. get_cmake_property(_vars VARIABLES)
  192. string (REGEX MATCHALL "(^|;)${_prefix}[A-Za-z0-9_]*" _matchedVars "${_vars}")
  193. set (${_varResult} ${_matchedVars} PARENT_SCOPE)
  194. endfunction()
  195. function (check_testcode_compiles testcode libraries _successful)
  196. set (save_required_libraries ${CMAKE_REQUIRED_LIBRARIES})
  197. set (CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES} ${libraries}")
  198. check_cxx_source_compiles("${testcode}" ${_successful})
  199. set (${_successful} ${${_successful}} PARENT_SCOPE)
  200. set (CMAKE_REQUIRED_LIBRARIES ${save_required_libraries})
  201. endfunction()
  202. function (test_requires_clock_gettime _enable _linklib)
  203. # This function tests if clock_gettime can be used
  204. # - at all
  205. # - with or without librt
  206. # Result will be:
  207. # - CLOCK_MONOTONIC is available, link with librt:
  208. # _enable = ON; _linklib = "-lrt".
  209. # - CLOCK_MONOTONIC is available, link without librt:
  210. # _enable = ON; _linklib = "".
  211. # - CLOCK_MONOTONIC is not available:
  212. # _enable = OFF; _linklib = "-".
  213. set (code "
  214. #include <time.h>
  215. int main() {
  216. timespec res\;
  217. int result = clock_gettime(CLOCK_MONOTONIC, &res)\;
  218. return result == 0\;
  219. }
  220. ")
  221. check_testcode_compiles(${code} "" HAVE_CLOCK_GETTIME_IN)
  222. if (HAVE_CLOCK_GETTIME_IN)
  223. message(STATUS "CLOCK_MONOTONIC: available, no extra libs needed")
  224. set (${_enable} ON PARENT_SCOPE)
  225. set (${_linklib} "" PARENT_SCOPE)
  226. return()
  227. endif()
  228. check_testcode_compiles(${code} "rt" HAVE_CLOCK_GETTIME_LIBRT)
  229. if (HAVE_CLOCK_GETTIME_LIBRT)
  230. message(STATUS "CLOCK_MONOTONIC: available, requires -lrt")
  231. set (${_enable} ON PARENT_SCOPE)
  232. set (${_linklib} "-lrt" PARENT_SCOPE)
  233. return()
  234. endif()
  235. set (${_enable} OFF PARENT_SCOPE)
  236. set (${_linklib} "-" PARENT_SCOPE)
  237. message(STATUS "CLOCK_MONOTONIC: not available on this system")
  238. endfunction()
  239. function (parse_compiler_type wct _type _suffix)
  240. if (wct STREQUAL "")
  241. set(${_type} "" PARENT_SCOPE)
  242. set(${_suffix} "" PARENT_SCOPE)
  243. else()
  244. string(REPLACE "-" ";" OUTLIST ${wct})
  245. list(LENGTH OUTLIST OUTLEN)
  246. list(GET OUTLIST 0 ITEM)
  247. set(${_type} ${ITEM} PARENT_SCOPE)
  248. if (OUTLEN LESS 2)
  249. set(_suffix "" PARENT_SCOPE)
  250. else()
  251. list(GET OUTLIST 1 ITEM)
  252. set(${_suffix} "-${ITEM}" PARENT_SCOPE)
  253. endif()
  254. endif()
  255. endfunction()