# Distributed under the OSI-approved BSD 3-Clause License. See accompanying # file Copyright.txt or https://cmake.org/licensing for details. #.rst: # WriteCompilerDetectionHeader # ---------------------------- # # This module provides the function write_compiler_detection_header(). # # The ``WRITE_COMPILER_DETECTION_HEADER`` function can be used to generate # a file suitable for preprocessor inclusion which contains macros to be # used in source code:: # # write_compiler_detection_header( # FILE # PREFIX # [OUTPUT_FILES_VAR OUTPUT_DIR ] # COMPILERS [...] # FEATURES [...] # [VERSION ] # [PROLOG ] # [EPILOG ] # [ALLOW_UNKNOWN_COMPILERS] # [ALLOW_UNKNOWN_COMPILER_VERSIONS] # ) # # The ``write_compiler_detection_header`` function generates the # file ```` with macros which all have the prefix ````. # # By default, all content is written directly to the ````. The # ``OUTPUT_FILES_VAR`` may be specified to cause the compiler-specific # content to be written to separate files. The separate files are then # available in the ```` and may be consumed by the caller # for installation for example. The ``OUTPUT_DIR`` specifies a relative # path from the main ```` to the compiler-specific files. For example: # # .. code-block:: cmake # # write_compiler_detection_header( # FILE climbingstats_compiler_detection.h # PREFIX ClimbingStats # OUTPUT_FILES_VAR support_files # OUTPUT_DIR compilers # COMPILERS GNU Clang MSVC Intel # FEATURES cxx_variadic_templates # ) # install(FILES # ${CMAKE_CURRENT_BINARY_DIR}/climbingstats_compiler_detection.h # DESTINATION include # ) # install(FILES # ${support_files} # DESTINATION include/compilers # ) # # # ``VERSION`` may be used to specify the API version to be generated. # Future versions of CMake may introduce alternative APIs. A given # API is selected by any ```` value greater than or equal # to the version of CMake that introduced the given API and less # than the version of CMake that introduced its succeeding API. # The value of the :variable:`CMAKE_MINIMUM_REQUIRED_VERSION` # variable is used if no explicit version is specified. # (As of CMake version |release| there is only one API version.) # # ``PROLOG`` may be specified as text content to write at the start of the # header. ``EPILOG`` may be specified as text content to write at the end # of the header # # At least one ```` and one ```` must be listed. Compilers # which are known to CMake, but not specified are detected and a preprocessor # ``#error`` is generated for them. A preprocessor macro matching # ``_COMPILER_IS_`` is generated for each compiler # known to CMake to contain the value ``0`` or ``1``. # # Possible compiler identifiers are documented with the # :variable:`CMAKE__COMPILER_ID` variable. # Available features in this version of CMake are listed in the # :prop_gbl:`CMAKE_C_KNOWN_FEATURES` and # :prop_gbl:`CMAKE_CXX_KNOWN_FEATURES` global properties. # The ``{c,cxx}_std_*`` meta-features are ignored if requested. # # See the :manual:`cmake-compile-features(7)` manual for information on # compile features. # # ``ALLOW_UNKNOWN_COMPILERS`` and ``ALLOW_UNKNOWN_COMPILER_VERSIONS`` cause # the module to generate conditions that treat unknown compilers as simply # lacking all features. Without these options the default behavior is to # generate a ``#error`` for unknown compilers. # # Feature Test Macros # =================== # # For each compiler, a preprocessor macro is generated matching # ``_COMPILER_IS_`` which has the content either ``0`` # or ``1``, depending on the compiler in use. Preprocessor macros for # compiler version components are generated matching # ``_COMPILER_VERSION_MAJOR`` ``_COMPILER_VERSION_MINOR`` # and ``_COMPILER_VERSION_PATCH`` containing decimal values # for the corresponding compiler version components, if defined. # # A preprocessor test is generated based on the compiler version # denoting whether each feature is enabled. A preprocessor macro # matching ``_COMPILER_``, where ```` is the # upper-case ```` name, is generated to contain the value # ``0`` or ``1`` depending on whether the compiler in use supports the # feature: # # .. code-block:: cmake # # write_compiler_detection_header( # FILE climbingstats_compiler_detection.h # PREFIX ClimbingStats # COMPILERS GNU Clang AppleClang MSVC Intel # FEATURES cxx_variadic_templates # ) # # .. code-block:: c++ # # #if ClimbingStats_COMPILER_CXX_VARIADIC_TEMPLATES # template # void someInterface(T t...) { /* ... */ } # #else # // Compatibility versions # template # void someInterface(T1 t1) { /* ... */ } # template # void someInterface(T1 t1, T2 t2) { /* ... */ } # template # void someInterface(T1 t1, T2 t2, T3 t3) { /* ... */ } # #endif # # Symbol Macros # ============= # # Some additional symbol-defines are created for particular features for # use as symbols which may be conditionally defined empty: # # .. code-block:: c++ # # class MyClass ClimbingStats_FINAL # { # ClimbingStats_CONSTEXPR int someInterface() { return 42; } # }; # # The ``ClimbingStats_FINAL`` macro will expand to ``final`` if the # compiler (and its flags) support the ``cxx_final`` feature, and the # ``ClimbingStats_CONSTEXPR`` macro will expand to ``constexpr`` # if ``cxx_constexpr`` is supported. # # The following features generate corresponding symbol defines: # # ========================== =================================== ================= # Feature Define Symbol # ========================== =================================== ================= # ``c_restrict`` ``_RESTRICT`` ``restrict`` # ``cxx_constexpr`` ``_CONSTEXPR`` ``constexpr`` # ``cxx_deleted_functions`` ``_DELETED_FUNCTION`` ``= delete`` # ``cxx_extern_templates`` ``_EXTERN_TEMPLATE`` ``extern`` # ``cxx_final`` ``_FINAL`` ``final`` # ``cxx_noexcept`` ``_NOEXCEPT`` ``noexcept`` # ``cxx_noexcept`` ``_NOEXCEPT_EXPR(X)`` ``noexcept(X)`` # ``cxx_override`` ``_OVERRIDE`` ``override`` # ========================== =================================== ================= # # Compatibility Implementation Macros # =================================== # # Some features are suitable for wrapping in a macro with a backward # compatibility implementation if the compiler does not support the feature. # # When the ``cxx_static_assert`` feature is not provided by the compiler, # a compatibility implementation is available via the # ``_STATIC_ASSERT(COND)`` and # ``_STATIC_ASSERT_MSG(COND, MSG)`` function-like macros. The macros # expand to ``static_assert`` where that compiler feature is available, and # to a compatibility implementation otherwise. In the first form, the # condition is stringified in the message field of ``static_assert``. In # the second form, the message ``MSG`` is passed to the message field of # ``static_assert``, or ignored if using the backward compatibility # implementation. # # The ``cxx_attribute_deprecated`` feature provides a macro definition # ``_DEPRECATED``, which expands to either the standard # ``[[deprecated]]`` attribute or a compiler-specific decorator such # as ``__attribute__((__deprecated__))`` used by GNU compilers. # # The ``cxx_alignas`` feature provides a macro definition # ``_ALIGNAS`` which expands to either the standard ``alignas`` # decorator or a compiler-specific decorator such as # ``__attribute__ ((__aligned__))`` used by GNU compilers. # # The ``cxx_alignof`` feature provides a macro definition # ``_ALIGNOF`` which expands to either the standard ``alignof`` # decorator or a compiler-specific decorator such as ``__alignof__`` # used by GNU compilers. # # ============================= ================================ ===================== # Feature Define Symbol # ============================= ================================ ===================== # ``cxx_alignas`` ``_ALIGNAS`` ``alignas`` # ``cxx_alignof`` ``_ALIGNOF`` ``alignof`` # ``cxx_nullptr`` ``_NULLPTR`` ``nullptr`` # ``cxx_static_assert`` ``_STATIC_ASSERT`` ``static_assert`` # ``cxx_static_assert`` ``_STATIC_ASSERT_MSG`` ``static_assert`` # ``cxx_attribute_deprecated`` ``_DEPRECATED`` ``[[deprecated]]`` # ``cxx_attribute_deprecated`` ``_DEPRECATED_MSG`` ``[[deprecated]]`` # ``cxx_thread_local`` ``_THREAD_LOCAL`` ``thread_local`` # ============================= ================================ ===================== # # A use-case which arises with such deprecation macros is the deprecation # of an entire library. In that case, all public API in the library may # be decorated with the ``_DEPRECATED`` macro. This results in # very noisy build output when building the library itself, so the macro # may be may be defined to empty in that case when building the deprecated # library: # # .. code-block:: cmake # # add_library(compat_support ${srcs}) # target_compile_definitions(compat_support # PRIVATE # CompatSupport_DEPRECATED= # ) include(${CMAKE_CURRENT_LIST_DIR}/CMakeCompilerIdDetection.cmake) function(_load_compiler_variables CompilerId lang) include("${CMAKE_ROOT}/Modules/Compiler/${CompilerId}-${lang}-FeatureTests.cmake" OPTIONAL) set(_cmake_oldestSupported_${CompilerId} ${_cmake_oldestSupported} PARENT_SCOPE) foreach(feature ${ARGN}) set(_cmake_feature_test_${CompilerId}_${feature} ${_cmake_feature_test_${feature}} PARENT_SCOPE) endforeach() include("${CMAKE_ROOT}/Modules/Compiler/${CompilerId}-${lang}-DetermineCompiler.cmake" OPTIONAL RESULT_VARIABLE determinedCompiler) if (NOT determinedCompiler) include("${CMAKE_ROOT}/Modules/Compiler/${CompilerId}-DetermineCompiler.cmake" OPTIONAL) endif() set(_compiler_id_version_compute_${CompilerId} ${_compiler_id_version_compute} PARENT_SCOPE) endfunction() macro(_simpledefine FEATURE_NAME FEATURE_TESTNAME FEATURE_STRING FEATURE_DEFAULT_STRING) if (feature STREQUAL "${FEATURE_NAME}") set(def_value "${prefix_arg}_${FEATURE_TESTNAME}") string(APPEND file_content " # if defined(${def_name}) && ${def_name} # define ${def_value} ${FEATURE_STRING} # else # define ${def_value} ${FEATURE_DEFAULT_STRING} # endif \n") endif() endmacro() function(write_compiler_detection_header file_keyword file_arg prefix_keyword prefix_arg ) if (NOT "x${file_keyword}" STREQUAL "xFILE") message(FATAL_ERROR "write_compiler_detection_header: FILE parameter missing.") endif() if (NOT "x${prefix_keyword}" STREQUAL "xPREFIX") message(FATAL_ERROR "write_compiler_detection_header: PREFIX parameter missing.") endif() set(options ALLOW_UNKNOWN_COMPILERS ALLOW_UNKNOWN_COMPILER_VERSIONS) set(oneValueArgs VERSION EPILOG PROLOG OUTPUT_FILES_VAR OUTPUT_DIR) set(multiValueArgs COMPILERS FEATURES) cmake_parse_arguments(_WCD "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) if (NOT _WCD_COMPILERS) message(FATAL_ERROR "Invalid arguments. write_compiler_detection_header requires at least one compiler.") endif() if (NOT _WCD_FEATURES) message(FATAL_ERROR "Invalid arguments. write_compiler_detection_header requires at least one feature.") endif() if(_WCD_UNPARSED_ARGUMENTS) message(FATAL_ERROR "Unparsed arguments: ${_WCD_UNPARSED_ARGUMENTS}") endif() if (prefix_arg STREQUAL "") message(FATAL_ERROR "A prefix must be specified") endif() string(MAKE_C_IDENTIFIER ${prefix_arg} cleaned_prefix) if (NOT prefix_arg STREQUAL cleaned_prefix) message(FATAL_ERROR "The prefix must be a valid C identifier.") endif() if(NOT _WCD_VERSION) set(_WCD_VERSION ${CMAKE_MINIMUM_REQUIRED_VERSION}) endif() set(_min_version 3.1.0) # Version which introduced this function if (_WCD_VERSION VERSION_LESS _min_version) set(err "VERSION compatibility for write_compiler_detection_header is set to ${_WCD_VERSION}, which is too low.") string(APPEND err " It must be set to at least ${_min_version}. ") string(APPEND err " Either set the VERSION parameter to the write_compiler_detection_header function, or update") string(APPEND err " your minimum required CMake version with the cmake_minimum_required command.") message(FATAL_ERROR "${err}") endif() if(_WCD_OUTPUT_FILES_VAR) if(NOT _WCD_OUTPUT_DIR) message(FATAL_ERROR "If OUTPUT_FILES_VAR is specified, then OUTPUT_DIR must also be specified.") endif() endif() if(_WCD_OUTPUT_DIR) if(NOT _WCD_OUTPUT_FILES_VAR) message(FATAL_ERROR "If OUTPUT_DIR is specified, then OUTPUT_FILES_VAR must also be specified.") endif() get_filename_component(main_file_dir ${file_arg} DIRECTORY) if (NOT IS_ABSOLUTE ${main_file_dir}) set(main_file_dir "${CMAKE_CURRENT_BINARY_DIR}/${main_file_dir}") endif() if (NOT IS_ABSOLUTE ${_WCD_OUTPUT_DIR}) set(_WCD_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/${_WCD_OUTPUT_DIR}") endif() get_filename_component(out_file_dir ${_WCD_OUTPUT_DIR} ABSOLUTE) string(FIND ${out_file_dir} ${main_file_dir} idx) if (NOT idx EQUAL 0) message(FATAL_ERROR "The compiler-specific output directory must be within the same directory as the main file.") endif() if (main_file_dir STREQUAL out_file_dir) unset(_WCD_OUTPUT_DIR) else() string(REPLACE "${main_file_dir}/" "" _WCD_OUTPUT_DIR "${out_file_dir}/") endif() endif() set(compilers GNU Clang AppleClang MSVC SunPro Intel ) set(_hex_compilers ADSP Borland Embarcadero SunPro) foreach(_comp ${_WCD_COMPILERS}) list(FIND compilers ${_comp} idx) if (idx EQUAL -1) message(FATAL_ERROR "Unsupported compiler ${_comp}.") endif() if (NOT _need_hex_conversion) list(FIND _hex_compilers ${_comp} idx) if (NOT idx EQUAL -1) set(_need_hex_conversion TRUE) endif() endif() endforeach() set(file_content " // This is a generated file. Do not edit! #ifndef ${prefix_arg}_COMPILER_DETECTION_H #define ${prefix_arg}_COMPILER_DETECTION_H ") if (_WCD_PROLOG) string(APPEND file_content "\n${_WCD_PROLOG}\n") endif() if (_need_hex_conversion) string(APPEND file_content " #define ${prefix_arg}_DEC(X) (X) #define ${prefix_arg}_HEX(X) ( \\ ((X)>>28 & 0xF) * 10000000 + \\ ((X)>>24 & 0xF) * 1000000 + \\ ((X)>>20 & 0xF) * 100000 + \\ ((X)>>16 & 0xF) * 10000 + \\ ((X)>>12 & 0xF) * 1000 + \\ ((X)>>8 & 0xF) * 100 + \\ ((X)>>4 & 0xF) * 10 + \\ ((X) & 0xF) \\ )\n") endif() foreach(feature ${_WCD_FEATURES}) if (feature MATCHES "^c_std_") # ignored elseif (feature MATCHES "^cxx_std_") # ignored elseif (feature MATCHES "^cxx_") list(APPEND _langs CXX) list(APPEND CXX_features ${feature}) elseif (feature MATCHES "^c_") list(APPEND _langs C) list(APPEND C_features ${feature}) else() message(FATAL_ERROR "Unsupported feature ${feature}.") endif() endforeach() list(REMOVE_DUPLICATES _langs) if(_WCD_OUTPUT_FILES_VAR) get_filename_component(main_file_name ${file_arg} NAME) set(compiler_file_content_ "#ifndef ${prefix_arg}_COMPILER_DETECTION_H # error This file may only be included from ${main_file_name} #endif\n") endif() foreach(_lang ${_langs}) set(target_compilers) foreach(compiler ${_WCD_COMPILERS}) _load_compiler_variables(${compiler} ${_lang} ${${_lang}_features}) if(_cmake_oldestSupported_${compiler}) list(APPEND target_compilers ${compiler}) endif() endforeach() get_property(known_features GLOBAL PROPERTY CMAKE_${_lang}_KNOWN_FEATURES) foreach(feature ${${_lang}_features}) list(FIND known_features ${feature} idx) if (idx EQUAL -1) message(FATAL_ERROR "Unsupported feature ${feature}.") endif() endforeach() if(_lang STREQUAL CXX) string(APPEND file_content "\n#ifdef __cplusplus\n") else() string(APPEND file_content "\n#ifndef __cplusplus\n") endif() compiler_id_detection(ID_CONTENT ${_lang} PREFIX ${prefix_arg}_ ID_DEFINE ) string(APPEND file_content "${ID_CONTENT}\n") set(pp_if "if") foreach(compiler ${target_compilers}) string(APPEND file_content "\n# ${pp_if} ${prefix_arg}_COMPILER_IS_${compiler}\n") if(_WCD_OUTPUT_FILES_VAR) set(compile_file_name "${_WCD_OUTPUT_DIR}${prefix_arg}_COMPILER_INFO_${compiler}_${_lang}.h") string(APPEND file_content "\n# include \"${compile_file_name}\"\n") endif() if(_WCD_OUTPUT_FILES_VAR) set(compiler_file_content compiler_file_content_${compiler}_${_lang}) else() set(compiler_file_content file_content) endif() if(NOT _WCD_ALLOW_UNKNOWN_COMPILER_VERSIONS) string(APPEND ${compiler_file_content} " # if !(${_cmake_oldestSupported_${compiler}}) # error Unsupported compiler version # endif\n") endif() set(PREFIX ${prefix_arg}_) if (_need_hex_conversion) set(MACRO_DEC ${prefix_arg}_DEC) set(MACRO_HEX ${prefix_arg}_HEX) else() set(MACRO_DEC) set(MACRO_HEX) endif() string(CONFIGURE "${_compiler_id_version_compute_${compiler}}" VERSION_BLOCK @ONLY) string(APPEND ${compiler_file_content} "${VERSION_BLOCK}\n") set(PREFIX) set(MACRO_DEC) set(MACRO_HEX) set(pp_if "elif") foreach(feature ${${_lang}_features}) string(TOUPPER ${feature} feature_upper) set(feature_PP "COMPILER_${feature_upper}") set(_define_item "\n# define ${prefix_arg}_${feature_PP} 0\n") if (_cmake_feature_test_${compiler}_${feature} STREQUAL "1") set(_define_item "\n# define ${prefix_arg}_${feature_PP} 1\n") elseif (_cmake_feature_test_${compiler}_${feature}) set(_define_item "\n# define ${prefix_arg}_${feature_PP} 0\n") set(_define_item "\n# if ${_cmake_feature_test_${compiler}_${feature}}\n# define ${prefix_arg}_${feature_PP} 1\n# else${_define_item}# endif\n") endif() string(APPEND ${compiler_file_content} "${_define_item}") endforeach() endforeach() if(pp_if STREQUAL "elif") if(_WCD_ALLOW_UNKNOWN_COMPILERS) string(APPEND file_content " # endif\n") else() string(APPEND file_content " # else # error Unsupported compiler # endif\n") endif() endif() foreach(feature ${${_lang}_features}) string(TOUPPER ${feature} feature_upper) set(feature_PP "COMPILER_${feature_upper}") set(def_name ${prefix_arg}_${feature_PP}) _simpledefine(c_restrict RESTRICT restrict "") _simpledefine(cxx_constexpr CONSTEXPR constexpr "") _simpledefine(cxx_final FINAL final "") _simpledefine(cxx_override OVERRIDE override "") if (feature STREQUAL cxx_static_assert) set(def_value "${prefix_arg}_STATIC_ASSERT(X)") set(def_value_msg "${prefix_arg}_STATIC_ASSERT_MSG(X, MSG)") set(def_fallback "enum { ${prefix_arg}_STATIC_ASSERT_JOIN(${prefix_arg}StaticAssertEnum, __LINE__) = sizeof(${prefix_arg}StaticAssert) }") string(APPEND file_content "# if defined(${def_name}) && ${def_name} # define ${def_value} static_assert(X, #X) # define ${def_value_msg} static_assert(X, MSG) # else # define ${prefix_arg}_STATIC_ASSERT_JOIN(X, Y) ${prefix_arg}_STATIC_ASSERT_JOIN_IMPL(X, Y) # define ${prefix_arg}_STATIC_ASSERT_JOIN_IMPL(X, Y) X##Y template struct ${prefix_arg}StaticAssert; template<> struct ${prefix_arg}StaticAssert{}; # define ${def_value} ${def_fallback} # define ${def_value_msg} ${def_fallback} # endif \n") endif() if (feature STREQUAL cxx_alignas) set(def_value "${prefix_arg}_ALIGNAS(X)") string(APPEND file_content " # if defined(${def_name}) && ${def_name} # define ${def_value} alignas(X) # elif ${prefix_arg}_COMPILER_IS_GNU || ${prefix_arg}_COMPILER_IS_Clang || ${prefix_arg}_COMPILER_IS_AppleClang # define ${def_value} __attribute__ ((__aligned__(X))) # elif ${prefix_arg}_COMPILER_IS_MSVC # define ${def_value} __declspec(align(X)) # else # define ${def_value} # endif \n") endif() if (feature STREQUAL cxx_alignof) set(def_value "${prefix_arg}_ALIGNOF(X)") string(APPEND file_content " # if defined(${def_name}) && ${def_name} # define ${def_value} alignof(X) # elif ${prefix_arg}_COMPILER_IS_GNU || ${prefix_arg}_COMPILER_IS_Clang || ${prefix_arg}_COMPILER_IS_AppleClang # define ${def_value} __alignof__(X) # elif ${prefix_arg}_COMPILER_IS_MSVC # define ${def_value} __alignof(X) # endif \n") endif() _simpledefine(cxx_deleted_functions DELETED_FUNCTION "= delete" "") _simpledefine(cxx_extern_templates EXTERN_TEMPLATE extern "") if (feature STREQUAL cxx_noexcept) set(def_value "${prefix_arg}_NOEXCEPT") string(APPEND file_content " # if defined(${def_name}) && ${def_name} # define ${def_value} noexcept # define ${def_value}_EXPR(X) noexcept(X) # else # define ${def_value} # define ${def_value}_EXPR(X) # endif \n") endif() _simpledefine(cxx_nullptr NULLPTR nullptr 0) if (feature STREQUAL cxx_thread_local) set(def_value "${prefix_arg}_THREAD_LOCAL") string(APPEND file_content " # if defined(${def_name}) && ${def_name} # define ${def_value} thread_local # elif ${prefix_arg}_COMPILER_IS_GNU || ${prefix_arg}_COMPILER_IS_Clang || ${prefix_arg}_COMPILER_IS_AppleClang # define ${def_value} __thread # elif ${prefix_arg}_COMPILER_IS_MSVC # define ${def_value} __declspec(thread) # else // ${def_value} not defined for this configuration. # endif \n") endif() if (feature STREQUAL cxx_attribute_deprecated) set(def_name ${prefix_arg}_${feature_PP}) set(def_value "${prefix_arg}_DEPRECATED") string(APPEND file_content " # ifndef ${def_value} # if defined(${def_name}) && ${def_name} # define ${def_value} [[deprecated]] # define ${def_value}_MSG(MSG) [[deprecated(MSG)]] # elif ${prefix_arg}_COMPILER_IS_GNU || ${prefix_arg}_COMPILER_IS_Clang # define ${def_value} __attribute__((__deprecated__)) # define ${def_value}_MSG(MSG) __attribute__((__deprecated__(MSG))) # elif ${prefix_arg}_COMPILER_IS_MSVC # define ${def_value} __declspec(deprecated) # define ${def_value}_MSG(MSG) __declspec(deprecated(MSG)) # else # define ${def_value} # define ${def_value}_MSG(MSG) # endif # endif \n") endif() endforeach() string(APPEND file_content "#endif\n") endforeach() if(_WCD_OUTPUT_FILES_VAR) foreach(compiler ${_WCD_COMPILERS}) foreach(_lang ${_langs}) if(compiler_file_content_${compiler}_${_lang}) set(CMAKE_CONFIGURABLE_FILE_CONTENT "${compiler_file_content_}") string(APPEND CMAKE_CONFIGURABLE_FILE_CONTENT "${compiler_file_content_${compiler}_${_lang}}") set(compile_file_name "${_WCD_OUTPUT_DIR}${prefix_arg}_COMPILER_INFO_${compiler}_${_lang}.h") set(full_path "${main_file_dir}/${compile_file_name}") list(APPEND ${_WCD_OUTPUT_FILES_VAR} ${full_path}) configure_file("${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in" "${full_path}" @ONLY ) endif() endforeach() endforeach() set(${_WCD_OUTPUT_FILES_VAR} ${${_WCD_OUTPUT_FILES_VAR}} PARENT_SCOPE) endif() if (_WCD_EPILOG) string(APPEND file_content "\n${_WCD_EPILOG}\n") endif() string(APPEND file_content "\n#endif") set(CMAKE_CONFIGURABLE_FILE_CONTENT ${file_content}) configure_file("${CMAKE_ROOT}/Modules/CMakeConfigurableFile.in" "${file_arg}" @ONLY ) endfunction()