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