Skip to content

Instantly share code, notes, and snippets.

@likema
Last active October 22, 2019 13:35
Show Gist options
  • Save likema/dc4547af539f11d422653c2fa012c6bd to your computer and use it in GitHub Desktop.
Save likema/dc4547af539f11d422653c2fa012c6bd to your computer and use it in GitHub Desktop.
CMake macro to check if given C source file compiles and links into an executable
# - Check if given C source file compiles and links into an executable
# CHECK_C_COMPILES(<file> <var> [FAIL_REGEX <fail-regex>])
#
# <file> - source file to try to compile, must define 'main'
# <var> - variable to store whether the source code compiled
# Will be created as an internal cache variable.
# <fail-regex> - fail if test output matches this regex
#
# The following variables may be set before calling this macro to modify
# the way the check is run:
#
# CMAKE_REQUIRED_FLAGS = string of compile command line flags
# CMAKE_REQUIRED_DEFINITIONS = list of macros to define (-DFOO=bar)
# CMAKE_REQUIRED_INCLUDES = list of include directories
# CMAKE_REQUIRED_LIBRARIES = list of libraries to link
# CMAKE_REQUIRED_QUIET = execute quietly without messages
MACRO (CHECK_C_COMPILES SRC VAR)
IF (NOT DEFINED "${VAR}")
SET (_FAIL_REGEX)
SET (_key)
FOREACH (arg ${ARGN})
IF ("${arg}" MATCHES "^(FAIL_REGEX)$")
SET (_key "${arg}")
ELSEIF (_key)
LIST (APPEND _${_key} "${arg}")
ELSE ("${arg}" MATCHES "^(FAIL_REGEX)$")
MESSAGE (FATAL_ERROR "Unknown argument:\n ${arg}\n")
ENDIF ("${arg}" MATCHES "^(FAIL_REGEX)$")
ENDFOREACH (arg ${ARGN})
SET (MACRO_CHECK_FUNCTION_DEFINITIONS
"-D${VAR} ${CMAKE_REQUIRED_FLAGS}")
IF (CMAKE_REQUIRED_LIBRARIES)
SET (CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES
LINK_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
ELSE (CMAKE_REQUIRED_LIBRARIES)
SET (CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES)
ENDIF (CMAKE_REQUIRED_LIBRARIES)
IF (CMAKE_REQUIRED_INCLUDES)
SET (CHECK_C_SOURCE_COMPILES_ADD_INCLUDES
"-DINCLUDE_DIRECTORIES:STRING=${CMAKE_REQUIRED_INCLUDES}")
ELSE (CMAKE_REQUIRED_INCLUDES)
SET (CHECK_C_SOURCE_COMPILES_ADD_INCLUDES)
ENDIF (CMAKE_REQUIRED_INCLUDES)
IF (NOT CMAKE_REQUIRED_QUIET)
MESSAGE (STATUS "Performing Test ${VAR}")
ENDIF (NOT CMAKE_REQUIRED_QUIET)
TRY_COMPILE (${VAR}
${CMAKE_BINARY_DIR}
${SRC}
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS}
${CHECK_C_SOURCE_COMPILES_ADD_LIBRARIES}
CMAKE_FLAGS -DCOMPILE_DEFINITIONS:STRING=${MACRO_CHECK_FUNCTION_DEFINITIONS}
"${CHECK_C_SOURCE_COMPILES_ADD_INCLUDES}"
OUTPUT_VARIABLE OUTPUT)
FOREACH (_regex ${_FAIL_REGEX})
IF ("${OUTPUT}" MATCHES "${_regex}")
SET (${VAR} 0)
ENDIF ("${OUTPUT}" MATCHES "${_regex}")
ENDFOREACH (_regex ${_FAIL_REGEX})
IF (${VAR})
SET (${VAR} 1 CACHE INTERNAL "Test ${VAR}")
IF (NOT CMAKE_REQUIRED_QUIET)
MESSAGE (STATUS "Performing Test ${VAR} - Success")
ENDIF (NOT CMAKE_REQUIRED_QUIET)
FILE (APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"Performing C SOURCE FILE Test ${VAR} succeeded with the following output:\n"
"${OUTPUT}\n"
"Source file was:\n${SRC}\n")
ELSE (${VAR})
IF (NOT CMAKE_REQUIRED_QUIET)
MESSAGE (STATUS "Performing Test ${VAR} - Failed")
ENDIF (NOT CMAKE_REQUIRED_QUIET)
SET (${VAR} "" CACHE INTERNAL "Test ${VAR}")
FILE (APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Performing C SOURCE FILE Test ${VAR} failed with the following output:\n"
"${OUTPUT}\n"
"Source file was:\n${SRC}\n")
ENDIF (${VAR})
ENDIF (NOT DEFINED "${VAR}")
ENDMACRO (CHECK_C_COMPILES SRC VAR)
# vim: set ts=4 sw=4 sts=4 et:
@likema
Copy link
Author

likema commented Oct 22, 2019

Inspired by CHECK_C_SOURCE_COMPILES, which has the following drawbacks:

  • Only support source as string

  • When source string is to complicated, it may encounter syntax error:

    CMake Error at /usr/share/cmake-3.9/Modules/CheckCSourceCompiles.cmake:57 (file):
        Syntax error in cmake code at
        
          /usr/share/cmake-3.9/Modules/CheckCSourceCompiles.cmake:58
    
        when parsing string
    
    syntax error, unexpected cal_SYMBOL, expecting $end (4391)
    

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment