1 2function(check_compile RESULT FILE FLAG TYPE) 3 4 string(REGEX REPLACE "[^a-zA-Z0-9_][^a-zA-Z0-9_]*" "-" cachevar "${TYPE}-${FLAG}") 5 set(cahevar "CHECK_COMPILE_${cahevar}") 6 7 if(DEFINED ${cachevar}) 8 if(${cachevar}) 9 set(${RESULT} "${FLAG}" PARENT_SCOPE) 10 else() 11 set(${RESULT} "" PARENT_SCOPE) 12 endif() 13 return() 14 endif() 15 16 # CMake already has a check_cxx_compiler_flag macro in CheckCXXCompilerFlag, but 17 # it prints the result variable in the output (which is ugly!) and also uses it 18 # as a key to cache checks - so it would need to be unique for each flag. 19 # Unfortunately it also naively pastes the variable name inside a regexp so 20 # if we tried to use the flag itself in the variable name it will fail for -std=c++11. 21 # But we can at least use the expressions for warnings from that macro (and more): 22 set(fail_regexps 23 "warning:" # general 24 "unrecognized .*option" # GNU 25 "unknown .*option" # Clang 26 "ignoring unknown option" # MSVC 27 "warning D9002" # MSVC, any lang 28 "option.*not supported" # Intel 29 "invalid argument .*option" # Intel 30 "ignoring option .*argument required" # Intel 31 "command line warning" # Intel 32 "[Uu]nknown option" # HP 33 "[Ww]arning: [Oo]ption" # SunPro 34 "command option .* is not recognized" # XL 35 "not supported in this configuration; ignored" # AIX 36 "File with unknown suffix passed to linker" # PGI 37 "WARNING: unknown flag:" # Open64 38 ) 39 40 # Set the flags to check 41 set(old_CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") 42 set(old_CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}") 43 set(old_CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") 44 set(old_CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}") 45 if("${TYPE}" STREQUAL "linker flag") 46 set(CMAKE_EXE_LINKER_FLAGS "${old_CMAKE_EXE_LINKER_FLAGS} ${FLAG}") 47 set(CMAKE_SHARED_LINKER_FLAGS "${old_CMAKE_SHARED_LINKER_FLAGS} ${FLAG}") 48 set(CMAKE_MODULE_LINKER_FLAGS "${old_CMAKE_MODULE_LINKER_FLAGS} ${FLAG}") 49 elseif("${TYPE}" STREQUAL "compiler flag") 50 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${FLAG}") 51 endif() 52 53 # Check if we can compile and link a simple file with the new flags 54 try_compile( 55 check_compiler_flag ${CMAKE_BINARY_DIR} ${FILE} 56 CMAKE_FLAGS "-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}" 57 "-DCMAKE_EXE_LINKER_FLAGS=${CMAKE_EXE_LINKER_FLAGS}" 58 "-DCMAKE_SHARED_LINKER_FLAGS=${CMAKE_SHARED_LINKER_FLAGS}" 59 "-DCMAKE_MODULE_LINKER_FLAGS=${CMAKE_MODULE_LINKER_FLAGS}" 60 "-DLINK_LIBRARIES=${ARGV4}" 61 OUTPUT_VARIABLE ERRORLOG 62 ) 63 64 # Restore the old flags 65 set(CMAKE_CXX_FLAGS "${old_CMAKE_CXX_FLAGS}") 66 set(CMAKE_EXE_LINKER_FLAGS "${old_CMAKE_EXE_LINKER_FLAGS}") 67 set(CMAKE_SHARED_LINKER_FLAGS "${old_CMAKE_SHARED_LINKER_FLAGS}") 68 set(CMAKE_MODULE_LINKER_FLAGS "${old_CMAKE_MODULE_LINKER_FLAGS}") 69 70 set(errormsg "unsupported") 71 if(${ARGC} GREATER 4) 72 set(errormsg "${ARGV5}") 73 endif() 74 75 if(NOT check_compiler_flag) 76 message(STATUS "Checking ${TYPE}: ${FLAG} - ${errormsg}") 77 set(${RESULT} "" PARENT_SCOPE) 78 set("${cachevar}" 0 CACHE INTERNAL "...") 79 else() 80 81 set(has_warning 0) 82 foreach(expr IN LISTS fail_regexps) 83 if("${ERRORLOG}" MATCHES "${expr}") 84 set(has_warning 1) 85 endif() 86 endforeach() 87 88 if(has_warning) 89 message(STATUS "Checking ${TYPE}: ${FLAG} - ${errormsg} (warning)") 90 set(${RESULT} "" PARENT_SCOPE) 91 set("${cachevar}" 0 CACHE INTERNAL "...") 92 else() 93 message(STATUS "Checking ${TYPE}: ${FLAG}") 94 set(${RESULT} "${FLAG}" PARENT_SCOPE) 95 set("${cachevar}" 1 CACHE INTERNAL "...") 96 endif() 97 98 endif() 99 100endfunction(check_compile) 101 102function(check_flag RESULT FLAG TYPE) 103 set(compile_test_file "${CMAKE_CURRENT_BINARY_DIR}/compile_flag_test.cpp") 104 file(WRITE ${compile_test_file} "__attribute__((const)) int main(){ return 0; }\n") 105 check_compile(result "${compile_test_file}" "${FLAG}" "${TYPE} flag") 106 set(${RESULT} "${result}" PARENT_SCOPE) 107endfunction(check_flag) 108 109function(check_compiler_flag RESULT FLAG) 110 check_flag(result "${FLAG}" compiler) 111 set(${RESULT} "${result}" PARENT_SCOPE) 112endfunction(check_compiler_flag) 113 114function(check_linker_flag RESULT FLAG) 115 check_flag(result "${FLAG}" linker) 116 set(${RESULT} "${result}" PARENT_SCOPE) 117endfunction(check_linker_flag) 118 119function(add_cxxflag FLAG) 120 121 check_compiler_flag(RESULT "${FLAG}") 122 123 set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${RESULT}" PARENT_SCOPE) 124 125 if("${RESULT}" STREQUAL "") 126 set(FLAG_FOUND 0 PARENT_SCOPE) 127 else() 128 set(FLAG_FOUND 1 PARENT_SCOPE) 129 endif() 130 131endfunction(add_cxxflag) 132 133function(add_ldflag FLAG) 134 135 check_linker_flag(RESULT "${FLAG}") 136 137 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${RESULT}" PARENT_SCOPE) 138 set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${RESULT}" PARENT_SCOPE) 139 set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${RESULT}" PARENT_SCOPE) 140 141 if("${RESULT}" STREQUAL "") 142 set(FLAG_FOUND 0 PARENT_SCOPE) 143 else() 144 set(FLAG_FOUND 1 PARENT_SCOPE) 145 endif() 146 147endfunction(add_ldflag) 148 149function(try_link_library LIBRARY_NAME LIBRARY_FILE ERROR_VAR) 150 # See if we can link a simple program with the library using the configured c++ compiler 151 set(link_test_file "${CMAKE_CURRENT_BINARY_DIR}/link_test.cpp") 152 file(WRITE ${link_test_file} "int main(){}\n") 153 if(CMAKE_THREAD_LIBS_INIT) 154 list(APPEND LIBRARY_FILE "${CMAKE_THREAD_LIBS_INIT}") 155 endif() 156 try_compile( 157 CHECK_${LIBRARY_NAME}_LINK "${CMAKE_BINARY_DIR}" "${link_test_file}" 158 CMAKE_FLAGS "-DLINK_LIBRARIES=${LIBRARY_FILE}" 159 "-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}" 160 "-DCMAKE_EXE_LINKER_FLAGS=${CMAKE_EXE_LINKER_FLAGS}" 161 "-DCMAKE_SHARED_LINKER_FLAGS=${CMAKE_SHARED_LINKER_FLAGS}" 162 "-DCMAKE_MODULE_LINKER_FLAGS=${CMAKE_MODULE_LINKER_FLAGS}" 163 OUTPUT_VARIABLE ERRORLOG 164 ) 165 set(${ERROR_VAR} "${ERRORLOG}" PARENT_SCOPE) 166endfunction(try_link_library) 167 168############################################################################## 169# Check that a a library actually works for the current configuration 170function(check_link_library LIBRARY_NAME LIBRARY_VARIABLE) 171 172 set(lib_current "${${LIBRARY_VARIABLE}}") 173 set(found_var "ARX_CLL_${LIBRARY_NAME}_FOUND") 174 set(working_var "ARX_CLL_${LIBRARY_NAME}_WORKING") 175 176 if(CHECK_${LIBRARY_NAME}_LINK) 177 set(lib_found "${${found_var}}") 178 set(lib_working "${${working_var}}") 179 if((lib_current STREQUAL lib_found) OR (lib_current STREQUAL lib_working)) 180 set("${LIBRARY_VARIABLE}" "${lib_working}" PARENT_SCOPE) 181 return() 182 endif() 183 endif() 184 185 set("${found_var}" "${lib_current}" CACHE INTERNAL "...") 186 187 if(NOT lib_current STREQUAL "") 188 message(STATUS "Checking ${LIBRARY_NAME}: ${lib_current}") 189 endif() 190 191 # Check if we can link to the full path found by find_package 192 try_link_library(${LIBRARY_NAME} "${lib_current}" ERRORLOG1) 193 194 if(CHECK_${LIBRARY_NAME}_LINK) 195 set("${working_var}" "${lib_current}" CACHE INTERNAL "...") 196 return() 197 endif() 198 199 # Check if the linker is smarter than cmake and try to link with only the library name 200 string(REGEX REPLACE "(^|;)[^;]*/lib([^;/]*)\\.so" "\\1-l\\2" 201 LIBRARY_FILE "${lib_current}") 202 203 if(NOT LIBRARY_FILE STREQUAL lib_current) 204 205 try_link_library(${LIBRARY_NAME} "${LIBRARY_FILE}" ERRORLOG2) 206 207 if(CHECK_${LIBRARY_NAME}_LINK) 208 message(STATUS " -> using ${LIBRARY_FILE} instead") 209 set("${LIBRARY_VARIABLE}" "${LIBRARY_FILE}" PARENT_SCOPE) 210 set("${working_var}" "${LIBRARY_FILE}" CACHE INTERNAL "...") 211 return() 212 endif() 213 214 endif() 215 216 # Force cmake to search again, as the cached library doesn't work 217 unset(FIND_PACKAGE_MESSAGE_DETAILS_${ARGV2} CACHE) 218 unset(FIND_PACKAGE_MESSAGE_DETAILS_${LIBRARY_NAME} CACHE) 219 220 message(FATAL_ERROR "\n${ERRORLOG1}\n\n${ERRORLOG2}\n\n" 221 "!! No suitable version of ${LIBRARY_NAME} found.\n" 222 " Maybe you don't have the right (32 vs.64 bit) architecture installed?\n\n" 223 " Tried ${lib_current} and ${LIBRARY_FILE}\n" 224 " Using compiler ${CMAKE_CXX_COMPILER} ${CMAKE_CXX_FLAGS}\n\n\n") 225 226endfunction(check_link_library) 227 228function(force_recheck_library LIBRARY_NAME) 229 unset(FIND_PACKAGE_MESSAGE_DETAILS_${ARGV1} CACHE) 230 unset(FIND_PACKAGE_MESSAGE_DETAILS_${LIBRARY_NAME} CACHE) 231 unset(CHECK_${LIBRARY_NAME}_LINK CACHE) 232endfunction() 233