Skip to content

Instantly share code, notes, and snippets.

@kkHAIKE
Created April 9, 2018 05:58
Show Gist options
  • Save kkHAIKE/3e000827da28e350c3a19365f6a3cb18 to your computer and use it in GitHub Desktop.
Save kkHAIKE/3e000827da28e350c3a19365f6a3cb18 to your computer and use it in GitHub Desktop.
# find_symbol_in_header_namespace(
# HEADER_OUT NAMESPACE_OUT
# "CODE" SNIPPET_IN
# "HEADERS" HEADERS_IN
# "NAMESPACES" NAMESPACES_IN
# "SUMMARY" SUMMARY_IN)
#
# Search for a header file that will allow ${SNIPPET_IN} to compile.
# Each header in the HEADERS_IN list is considered. If found, then
# attempts will be made to compile SNIPPET_IN after including that header.
# The first successful compilation terminates the search.
#
# The code SNIPPET_IN may contain the word NAMESPACE, which will be
# replaced with one of the entries in NAMESPACES_IN using a preprocessor
# macro until the snippet compiles or the list is exhausted.
#
# The snippet may prove compilable in several namespaces, so this macro
# returns two values *and* sets them as CACHE variables:
# HEADER_OUT - The name of the header file which allows the snippet to compile.
# NAMESPACE_OUT - The namespace (including "::") which allows the snippet to compile.
#
# Note that if ${HEADER_OUT} is already a non-empty string, the test is not run.
# Upon return, if a combination of header and namespace were identified,
# then cache variables for HEADER_OUT and NAMESPACE_OUT will be set.
#
# The SUMMARY_IN value is used for informational messages and in the
# descriptions of the cache variables.
#
# Example:
# find_symbol_in_header_namespace( HASH_FUN_H HASH_FUN_NAMESPACE
# CODE
# "int h = NAMESPACE hash<int>()(42);"
# HEADERS
# "functional"
# "tr1/functional"
# "ext/hash_fun.h"
# "ext/stl_hash_fun.h"
# "hash_fun.h"
# "stl_hash_fun.h"
# "stl/_hash_fun.h"
# NAMESPACES
# ""
# "std"
# "stdext"
# "__gnu_cxx"
# SUMMARY "hash")
# This example will set CACHE variables HASH_FUN_H and HASH_FUN_NAMESPACE
# to "ext/hash_fun.h" and "__gnu_cxx" (respectively) on OS X 10.8;
# to "functional" and "std" (respectively) on OS X 10.9;
# and so on for each platform where "hash" is provided by one of the HEADERS
# in one of the listed NAMESPACES.
function(find_symbol_in_header_namespace HEADER_OUT NAMESPACE_OUT)
# Require names for output variables
if (HEADER_OUT STREQUAL "" OR NAMESPACE_OUT STREQUAL "")
message(FATAL_ERROR "find_symbol_in_header_namespace not passed required HEADER_OUR or NAMESPACE_OUT")
return()
endif()
include(CMakeParseArguments)
cmake_parse_arguments(_FSIH "" "CODE;SUMMARY" "HEADERS;NAMESPACES" ${ARGN})
if (_FSIH_HEADERS STREQUAL "" OR _FSIH_NAMESPACES STREQUAL "" OR _FSIH_CODE STREQUAL "")
message(FATAL_ERROR "find_symbol_in_header_namespace not passed required arguments")
return()
endif()
include(CheckIncludeFileCXX)
# Now, only try to find the symbol if the header is *not* defined
# in the cache. Done in order to save time, which could be expensive
# as there could be many TRY_COMPILE calls.
if (NOT DEFINED "${HEADER_OUT}")
foreach(_inc ${_FSIH_HEADERS})
check_include_file_cxx("${_inc}" _have_header)
if (_have_header)
foreach(_ns ${_FSIH_NAMESPACES})
string(RANDOM LENGTH 10 _tmpf)
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/_cmFindSymbol${_tmpf}.cxx
"#include \"${_inc}\"\n#define NAMESPACE ::${_ns}\nint main() {\n ${_FSIH_CODE};\n return 0;\n}")
try_compile(_found_symbol_ns
${CMAKE_CURRENT_BINARY_DIR}/CMakeTmp
${CMAKE_CURRENT_BINARY_DIR}/_cmFindSymbol${_tmpf}.cxx
COMPILE_DEFINITIONS "-DHEADER=\"${_inc}\"" "-DNAMESPACE=${_ns}"
OUTPUT_VARIABLE _result
)
file(REMOVE ${CMAKE_CURRENT_BINARY_DIR}/_cmFindSymbol${_tmpf}.cxx)
#message("Tried ${_inc} with ${_ns} result ${_found_symbol_ns} ")
#message("Tried ${_inc} with ${_ns} result ${_found_symbol_ns} \"${_result}\"")
if (_found_symbol_ns)
set(${HEADER_OUT} "\"${_inc}\"" CACHE STRING "Name of header file containing ${_ns}${_FSIH_SUMMARY}" FORCE)
set(${NAMESPACE_OUT} ${_ns} CACHE STRING "Namespace containing symbol ${_FSIH_SUMMARY}" FORCE)
message(" Header <${_inc}> contains ${_ns}::${_FSIH_SUMMARY}")
break()
endif()
endforeach()
if (_found_symbol_ns)
break()
endif()
endif()
endforeach()
if (NOT _found_symbol_ns)
set(${HEADER_OUT} "")
set(${NAMESPACE_OUT} "")
endif()
endif()
endfunction()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment