Commit e0890d03 authored by Stephen Kelly's avatar Stephen Kelly
Browse files

Features: Extend concept to C language.

Add properties and variables corresponding to CXX equivalents.

Add features for c_function_prototypes (C90), c_restrict (C99),
c_variadic_macros (C99) and c_static_assert (C11). This feature
set can be extended later.

Add a <PREFIX>_RESTRICT symbol define to WriteCompilerDetectionHeader
to conditionally represent the c_restrict feature.
parent 775458de
...@@ -8,7 +8,8 @@ Add expected compiler features to a target. ...@@ -8,7 +8,8 @@ Add expected compiler features to a target.
target_compile_features(<target> <PRIVATE|PUBLIC|INTERFACE> <feature> [...]) target_compile_features(<target> <PRIVATE|PUBLIC|INTERFACE> <feature> [...])
Specify compiler features required when compiling a given target. If the Specify compiler features required when compiling a given target. If the
feature is not listed in the :variable:`CMAKE_CXX_COMPILE_FEATURES` variable, feature is not listed in the :variable:`CMAKE_C_COMPILE_FEATURES` variable
or :variable:`CMAKE_CXX_COMPILE_FEATURES` variable,
then an error will be reported by CMake. If the use of the feature requires then an error will be reported by CMake. If the use of the feature requires
an additional compiler flag, such as ``-std=c++11``, the flag will be added an additional compiler flag, such as ``-std=c++11``, the flag will be added
automatically. automatically.
......
...@@ -16,6 +16,7 @@ Properties of Global Scope ...@@ -16,6 +16,7 @@ Properties of Global Scope
/prop_gbl/ALLOW_DUPLICATE_CUSTOM_TARGETS /prop_gbl/ALLOW_DUPLICATE_CUSTOM_TARGETS
/prop_gbl/AUTOGEN_TARGETS_FOLDER /prop_gbl/AUTOGEN_TARGETS_FOLDER
/prop_gbl/AUTOMOC_TARGETS_FOLDER /prop_gbl/AUTOMOC_TARGETS_FOLDER
/prop_gbl/CMAKE_C_KNOWN_FEATURES
/prop_gbl/CMAKE_CXX_KNOWN_FEATURES /prop_gbl/CMAKE_CXX_KNOWN_FEATURES
/prop_gbl/DEBUG_CONFIGURATIONS /prop_gbl/DEBUG_CONFIGURATIONS
/prop_gbl/DISABLED_FEATURES /prop_gbl/DISABLED_FEATURES
...@@ -93,6 +94,9 @@ Properties on Targets ...@@ -93,6 +94,9 @@ Properties on Targets
/prop_tgt/BUILD_WITH_INSTALL_RPATH /prop_tgt/BUILD_WITH_INSTALL_RPATH
/prop_tgt/BUNDLE_EXTENSION /prop_tgt/BUNDLE_EXTENSION
/prop_tgt/BUNDLE /prop_tgt/BUNDLE
/prop_tgt/C_EXTENSIONS
/prop_tgt/C_STANDARD
/prop_tgt/C_STANDARD_REQUIRED
/prop_tgt/COMPATIBLE_INTERFACE_BOOL /prop_tgt/COMPATIBLE_INTERFACE_BOOL
/prop_tgt/COMPATIBLE_INTERFACE_NUMBER_MAX /prop_tgt/COMPATIBLE_INTERFACE_NUMBER_MAX
/prop_tgt/COMPATIBLE_INTERFACE_NUMBER_MIN /prop_tgt/COMPATIBLE_INTERFACE_NUMBER_MIN
......
...@@ -260,6 +260,10 @@ Variables for Languages ...@@ -260,6 +260,10 @@ Variables for Languages
:maxdepth: 1 :maxdepth: 1
/variable/CMAKE_COMPILER_IS_GNULANG /variable/CMAKE_COMPILER_IS_GNULANG
/variable/CMAKE_C_COMPILE_FEATURES
/variable/CMAKE_C_EXTENSIONS
/variable/CMAKE_C_STANDARD
/variable/CMAKE_C_STANDARD_REQUIRED
/variable/CMAKE_CXX_COMPILE_FEATURES /variable/CMAKE_CXX_COMPILE_FEATURES
/variable/CMAKE_CXX_EXTENSIONS /variable/CMAKE_CXX_EXTENSIONS
/variable/CMAKE_CXX_STANDARD /variable/CMAKE_CXX_STANDARD
......
CMAKE_C_KNOWN_FEATURES
----------------------
List of C features known to this version of CMake.
The features listed in this global property may be known to be available to the
C compiler. If the feature is available with the C compiler, it will
be listed in the :variable:`CMAKE_C_COMPILE_FEATURES` variable.
The features listed here may be used with the :command:`target_compile_features`
command.
The features known to this version of CMake are:
``c_function_prototypes``
Function prototypes, as defined in ``ISO/IEC 9899:1990``.
``c_restrict``
``restrict`` keyword, as defined in ``ISO/IEC 9899:1999``.
``c_static_assert``
Static assert, as defined in ``ISO/IEC 9899:2011``.
``c_variadic_macros``
Variadic macros, as defined in ``ISO/IEC 9899:1999``.
C_EXTENSIONS
------------
Boolean specifying whether compiler specific extensions are requested.
This property specifies whether compiler specific extensions should be
used. For some compilers, this results in adding a flag such
as ``-std=gnu11`` instead of ``-std=c11`` to the compile line.
C_STANDARD
----------
The C standard whose features are requested to build this target.
This property specifies the C standard whose features are requested
to build this target. For some compilers, this results in adding a
flag such as ``-std=c11`` to the compile line.
Supported values are ``90``, ``99`` and ``11``.
If the value requested does not result in a compile flag being added for
the compiler in use, a previous standard flag will be added instead. This
means that using:
.. code-block:: cmake
set_property(TARGET tgt PROPERTY C_STANDARD 11)
with a compiler which does not support ``-std=c11`` or an equivalent
flag will not result in an error or warning, but will instead add the
``-std=c99`` or ``-std=c90`` flag if supported. This "decay" behavior may
be controlled with the :prop_tgt:`C_STANDARD_REQUIRED` target property.
This property is initialized by the value of
the :variable:`CMAKE_C_STANDARD` variable if it is set when a target
is created.
C_STANDARD_REQUIRED
-------------------
Boolean describing whether the value of :prop_tgt:`C_STANDARD` is a requirement.
If this property is set to ``ON``, then the value of the
:prop_tgt:`C_STANDARD` target property is treated as a requirement. If this
property is ``OFF`` or unset, the :prop_tgt:`C_STANDARD` target property is
treated as optional and may "decay" to a previous standard if the requested is
not available.
This property is initialized by the value of
the :variable:`CMAKE_C_STANDARD_REQUIRED` variable if it is set when a
target is created.
...@@ -7,6 +7,12 @@ target-language-features ...@@ -7,6 +7,12 @@ target-language-features
:variable:`CMAKE_CXX_STANDARD` and :variable:`CMAKE_CXX_EXTENSIONS` :variable:`CMAKE_CXX_STANDARD` and :variable:`CMAKE_CXX_EXTENSIONS`
variables may be set to initialize the target properties. variables may be set to initialize the target properties.
* New :prop_tgt:`C_STANDARD` and :prop_tgt:`C_EXTENSIONS` target
properties may specify values which CMake uses to compute required
compile options such as ``-std=c11`` or ``-std=gnu11``. The
:variable:`CMAKE_C_STANDARD` and :variable:`CMAKE_C_EXTENSIONS`
variables may be set to initialize the target properties.
* New :prop_tgt:`COMPILE_FEATURES` target property may contain a list * New :prop_tgt:`COMPILE_FEATURES` target property may contain a list
of features required to compile a target. CMake uses this of features required to compile a target. CMake uses this
information to ensure that the compiler in use is capable of building information to ensure that the compiler in use is capable of building
......
CMAKE_C_COMPILE_FEATURES
------------------------
List of features known to the C compiler
These features are known to be available for use with the C compiler. This
list is a subset of the features listed in the :prop_gbl:`CMAKE_C_KNOWN_FEATURES`
global property.
CMAKE_C_EXTENSIONS
------------------
Default value for ``C_EXTENSIONS`` property of targets.
This variable is used to initialize the :prop_tgt:`C_EXTENSIONS`
property on all targets. See that target property for additional
information.
CMAKE_C_STANDARD
----------------
Default value for ``C_STANDARD`` property of targets.
This variable is used to initialize the :prop_tgt:`C_STANDARD`
property on all targets. See that target property for additional
information.
CMAKE_C_STANDARD_REQUIRED
-------------------------
Default value for ``C_STANDARD_REQUIRED`` property of targets.
This variable is used to initialize the :prop_tgt:`C_STANDARD_REQUIRED`
property on all targets. See that target property for additional
information.
...@@ -2,6 +2,11 @@ set(CMAKE_C_COMPILER "@CMAKE_C_COMPILER@") ...@@ -2,6 +2,11 @@ set(CMAKE_C_COMPILER "@CMAKE_C_COMPILER@")
set(CMAKE_C_COMPILER_ARG1 "@CMAKE_C_COMPILER_ARG1@") set(CMAKE_C_COMPILER_ARG1 "@CMAKE_C_COMPILER_ARG1@")
set(CMAKE_C_COMPILER_ID "@CMAKE_C_COMPILER_ID@") set(CMAKE_C_COMPILER_ID "@CMAKE_C_COMPILER_ID@")
set(CMAKE_C_COMPILER_VERSION "@CMAKE_C_COMPILER_VERSION@") set(CMAKE_C_COMPILER_VERSION "@CMAKE_C_COMPILER_VERSION@")
set(CMAKE_C_COMPILE_FEATURES "@CMAKE_C_COMPILE_FEATURES@")
set(CMAKE_C90_COMPILE_FEATURES "@CMAKE_C90_COMPILE_FEATURES@")
set(CMAKE_C99_COMPILE_FEATURES "@CMAKE_C99_COMPILE_FEATURES@")
set(CMAKE_C11_COMPILE_FEATURES "@CMAKE_C11_COMPILE_FEATURES@")
set(CMAKE_C_PLATFORM_ID "@CMAKE_C_PLATFORM_ID@") set(CMAKE_C_PLATFORM_ID "@CMAKE_C_PLATFORM_ID@")
set(CMAKE_C_SIMULATE_ID "@CMAKE_C_SIMULATE_ID@") set(CMAKE_C_SIMULATE_ID "@CMAKE_C_SIMULATE_ID@")
set(CMAKE_C_SIMULATE_VERSION "@CMAKE_C_SIMULATE_VERSION@") set(CMAKE_C_SIMULATE_VERSION "@CMAKE_C_SIMULATE_VERSION@")
......
...@@ -14,7 +14,45 @@ ...@@ -14,7 +14,45 @@
function(cmake_determine_compile_features lang) function(cmake_determine_compile_features lang)
if(lang STREQUAL CXX AND COMMAND cmake_record_cxx_compile_features) if(lang STREQUAL C AND COMMAND cmake_record_c_compile_features)
message(STATUS "Detecting ${lang} compile features")
set(CMAKE_C90_COMPILE_FEATURES)
set(CMAKE_C99_COMPILE_FEATURES)
set(CMAKE_C11_COMPILE_FEATURES)
include("${CMAKE_ROOT}/Modules/Internal/FeatureTesting.cmake")
cmake_record_c_compile_features()
if(NOT _result EQUAL 0)
message(STATUS "Detecting ${lang} compile features - failed")
return()
endif()
if (CMAKE_C99_COMPILE_FEATURES AND CMAKE_C11_COMPILE_FEATURES)
list(REMOVE_ITEM CMAKE_C11_COMPILE_FEATURES ${CMAKE_C99_COMPILE_FEATURES})
endif()
if (CMAKE_C90_COMPILE_FEATURES AND CMAKE_C99_COMPILE_FEATURES)
list(REMOVE_ITEM CMAKE_C99_COMPILE_FEATURES ${CMAKE_C90_COMPILE_FEATURES})
endif()
if(NOT CMAKE_C_COMPILE_FEATURES)
set(CMAKE_C_COMPILE_FEATURES
${CMAKE_C90_COMPILE_FEATURES}
${CMAKE_C99_COMPILE_FEATURES}
${CMAKE_C11_COMPILE_FEATURES}
)
endif()
set(CMAKE_C_COMPILE_FEATURES ${CMAKE_C_COMPILE_FEATURES} PARENT_SCOPE)
set(CMAKE_C90_COMPILE_FEATURES ${CMAKE_C90_COMPILE_FEATURES} PARENT_SCOPE)
set(CMAKE_C99_COMPILE_FEATURES ${CMAKE_C99_COMPILE_FEATURES} PARENT_SCOPE)
set(CMAKE_C11_COMPILE_FEATURES ${CMAKE_C11_COMPILE_FEATURES} PARENT_SCOPE)
message(STATUS "Detecting ${lang} compile features - done")
elseif(lang STREQUAL CXX AND COMMAND cmake_record_cxx_compile_features)
message(STATUS "Detecting ${lang} compile features") message(STATUS "Detecting ${lang} compile features")
set(CMAKE_CXX98_COMPILE_FEATURES) set(CMAKE_CXX98_COMPILE_FEATURES)
......
...@@ -73,6 +73,9 @@ else() ...@@ -73,6 +73,9 @@ else()
# Try to identify the ABI and configure it into CMakeCCompiler.cmake # Try to identify the ABI and configure it into CMakeCCompiler.cmake
include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerABI.cmake) include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerABI.cmake)
CMAKE_DETERMINE_COMPILER_ABI(C ${CMAKE_ROOT}/Modules/CMakeCCompilerABI.c) CMAKE_DETERMINE_COMPILER_ABI(C ${CMAKE_ROOT}/Modules/CMakeCCompilerABI.c)
# Try to identify the compiler features
include(${CMAKE_ROOT}/Modules/CMakeDetermineCompileFeatures.cmake)
CMAKE_DETERMINE_COMPILE_FEATURES(C)
# Re-configure to save learned information. # Re-configure to save learned information.
configure_file( configure_file(
......
set(_cmake_oldestSupported "(__GNUC__ * 100 + __GNUC_MINOR__) >= 407")
set(GNU46_C11 "${_cmake_oldestSupported} && __STDC_VERSION__ >= 201112L")
set(_cmake_feature_test_c_static_assert "${GNU46_C11}")
# Since 4.4 at least:
set(GNU44_C99 "${_cmake_oldestSupported} && __STDC_VERSION__ >= 199901L")
set(_cmake_feature_test_c_restrict "${GNU44_C99}")
set(_cmake_feature_test_c_variadic_macros "${GNU44_C99}")
set(GNU_C90 "${_cmake_oldestSupported} && !defined(__STDC_VERSION__)")
set(_cmake_feature_test_c_function_prototypes "${GNU_C90}")
include(Compiler/GNU) include(Compiler/GNU)
__compiler_gnu(C) __compiler_gnu(C)
if (NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.7)
set(CMAKE_C90_STANDARD_COMPILE_OPTION "-std=c90")
set(CMAKE_C90_EXTENSION_COMPILE_OPTION "-std=gnu90")
set(CMAKE_C99_STANDARD_COMPILE_OPTION "-std=c99")
set(CMAKE_C99_EXTENSION_COMPILE_OPTION "-std=gnu99")
set(CMAKE_C11_STANDARD_COMPILE_OPTION "-std=c11")
set(CMAKE_C11_EXTENSION_COMPILE_OPTION "-std=gnu11")
endif()
# This may change in a future GNU version.
set(CMAKE_C_STANDARD_DEFAULT 90)
macro(cmake_record_c_compile_features)
macro(_get_gcc_features std_version list)
record_compiler_features(C "-std=${std_version}" ${list})
endmacro()
if (UNIX AND NOT APPLE AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS 4.7)
_get_gcc_features(c90 CMAKE_C90_COMPILE_FEATURES)
if (_result EQUAL 0)
_get_gcc_features(c99 CMAKE_C99_COMPILE_FEATURES)
endif()
if (_result EQUAL 0)
_get_gcc_features(c11 CMAKE_C11_COMPILE_FEATURES)
endif()
else()
set(_result 0)
endif()
endmacro()
...@@ -43,7 +43,8 @@ ...@@ -43,7 +43,8 @@
# Possible compiler identifiers are documented with the # Possible compiler identifiers are documented with the
# :variable:`CMAKE_<LANG>_COMPILER_ID` variable. # :variable:`CMAKE_<LANG>_COMPILER_ID` variable.
# Available features in this version of CMake are listed in the # Available features in this version of CMake are listed in the
# :prop_gbl:`CMAKE_CXX_KNOWN_FEATURES` global property. # :prop_gbl:`CMAKE_C_KNOWN_FEATURES` and
# :prop_gbl:`CMAKE_CXX_KNOWN_FEATURES` global properties.
# #
# Feature Test Macros # Feature Test Macros
# =================== # ===================
...@@ -102,6 +103,7 @@ ...@@ -102,6 +103,7 @@
# ========================== =================================== ================= # ========================== =================================== =================
# Feature Define Symbol # Feature Define Symbol
# ========================== =================================== ================= # ========================== =================================== =================
# ``c_restrict`` ``<PREFIX>_RESTRICT`` ``restrict``
# ``cxx_constexpr`` ``<PREFIX>_CONSTEXPR`` ``constexpr`` # ``cxx_constexpr`` ``<PREFIX>_CONSTEXPR`` ``constexpr``
# ``cxx_deleted_functions`` ``<PREFIX>_DELETED_FUNCTION`` ``= delete`` # ``cxx_deleted_functions`` ``<PREFIX>_DELETED_FUNCTION`` ``= delete``
# ``cxx_extern_templates`` ``<PREFIX>_EXTERN_TEMPLATE`` ``extern`` # ``cxx_extern_templates`` ``<PREFIX>_EXTERN_TEMPLATE`` ``extern``
...@@ -221,6 +223,9 @@ function(write_compiler_detection_header ...@@ -221,6 +223,9 @@ function(write_compiler_detection_header
if (feature MATCHES "^cxx_") if (feature MATCHES "^cxx_")
list(APPEND _langs CXX) list(APPEND _langs CXX)
list(APPEND CXX_features ${feature}) list(APPEND CXX_features ${feature})
elseif (feature MATCHES "^c_")
list(APPEND _langs C)
list(APPEND C_features ${feature})
else() else()
message(FATAL_ERROR "Unsupported feature ${feature}.") message(FATAL_ERROR "Unsupported feature ${feature}.")
endif() endif()
...@@ -239,6 +244,8 @@ function(write_compiler_detection_header ...@@ -239,6 +244,8 @@ function(write_compiler_detection_header
if(_lang STREQUAL CXX) if(_lang STREQUAL CXX)
set(file_content "${file_content}\n#ifdef __cplusplus\n") set(file_content "${file_content}\n#ifdef __cplusplus\n")
else()
set(file_content "${file_content}\n#ifndef __cplusplus\n")
endif() endif()
compiler_id_detection(ID_CONTENT ${_lang} PREFIX ${prefix_arg}_ compiler_id_detection(ID_CONTENT ${_lang} PREFIX ${prefix_arg}_
...@@ -279,6 +286,16 @@ function(write_compiler_detection_header ...@@ -279,6 +286,16 @@ function(write_compiler_detection_header
string(TOUPPER ${feature} feature_upper) string(TOUPPER ${feature} feature_upper)
set(feature_PP "COMPILER_${feature_upper}") set(feature_PP "COMPILER_${feature_upper}")
set(def_name ${prefix_arg}_${feature_PP}) set(def_name ${prefix_arg}_${feature_PP})
if (feature STREQUAL c_restrict)
set(def_value "${prefix_arg}_RESTRICT")
set(file_content "${file_content}
# if ${def_name}
# define ${def_value} restrict
# else
# define ${def_value}
# endif
\n")
endif()
if (feature STREQUAL cxx_constexpr) if (feature STREQUAL cxx_constexpr)
set(def_value "${prefix_arg}_DECL_${feature_upper}") set(def_value "${prefix_arg}_DECL_${feature_upper}")
set(file_content "${file_content} set(file_content "${file_content}
...@@ -382,9 +399,8 @@ function(write_compiler_detection_header ...@@ -382,9 +399,8 @@ function(write_compiler_detection_header
\n") \n")
endif() endif()
endforeach() endforeach()
if(_lang STREQUAL CXX)
set(file_content "${file_content}#endif\n") set(file_content "${file_content}#endif\n")
endif()
endforeach() endforeach()
......
...@@ -2201,6 +2201,10 @@ AddCompilerRequirementFlag(std::string &flags, cmTarget* target, ...@@ -2201,6 +2201,10 @@ AddCompilerRequirementFlag(std::string &flags, cmTarget* target,
// Maintain sorted order, most recent first. // Maintain sorted order, most recent first.
langStdMap["CXX"].push_back("11"); langStdMap["CXX"].push_back("11");
langStdMap["CXX"].push_back("98"); langStdMap["CXX"].push_back("98");
langStdMap["C"].push_back("11");
langStdMap["C"].push_back("99");
langStdMap["C"].push_back("90");
} }
std::string standard(standardProp); std::string standard(standardProp);
......
...@@ -4973,6 +4973,10 @@ void cmMakefile::RecordPolicies(cmPolicies::PolicyMap& pm) ...@@ -4973,6 +4973,10 @@ void cmMakefile::RecordPolicies(cmPolicies::PolicyMap& pm)
} }
#define FEATURE_STRING(F) , #F #define FEATURE_STRING(F) , #F
static const char * const C_FEATURES[] = {
0
FOR_EACH_C_FEATURE(FEATURE_STRING)
};
static const char * const CXX_FEATURES[] = { static const char * const CXX_FEATURES[] = {
0 0
...@@ -4980,6 +4984,11 @@ static const char * const CXX_FEATURES[] = { ...@@ -4980,6 +4984,11 @@ static const char * const CXX_FEATURES[] = {
}; };
#undef FEATURE_STRING #undef FEATURE_STRING
static const char * const C_STANDARDS[] = {
"90"
, "99"
, "11"
};
static const char * const CXX_STANDARDS[] = { static const char * const CXX_STANDARDS[] = {
"98" "98"
, "11" , "11"
...@@ -4995,10 +5004,13 @@ AddRequiredTargetFeature(cmTarget *target, const std::string& feature, ...@@ -4995,10 +5004,13 @@ AddRequiredTargetFeature(cmTarget *target, const std::string& feature,
target->AppendProperty("COMPILE_FEATURES", feature.c_str()); target->AppendProperty("COMPILE_FEATURES", feature.c_str());
return true; return true;
} }
bool isCFeature = std::find_if(cmArrayBegin(C_FEATURES) + 1,
cmArrayEnd(C_FEATURES), cmStrCmp(feature))
!= cmArrayEnd(C_FEATURES);
bool isCxxFeature = std::find_if(cmArrayBegin(CXX_FEATURES) + 1, bool isCxxFeature = std::find_if(cmArrayBegin(CXX_FEATURES) + 1,
cmArrayEnd(CXX_FEATURES), cmStrCmp(feature)) cmArrayEnd(CXX_FEATURES), cmStrCmp(feature))
!= cmArrayEnd(CXX_FEATURES); != cmArrayEnd(CXX_FEATURES);
if (!isCxxFeature) if (!isCFeature && !isCxxFeature)
{ {
cmOStringStream e; cmOStringStream e;
if (error) if (error)
...@@ -5022,7 +5034,7 @@ AddRequiredTargetFeature(cmTarget *target, const std::string& feature, ...@@ -5022,7 +5034,7 @@ AddRequiredTargetFeature(cmTarget *target, const std::string& feature,
return false; return false;
} }
std::string lang = "CXX"; std::string lang = isCFeature ? "C" : "CXX";
const char* featuresKnown = const char* featuresKnown =
this->GetDefinition("CMAKE_" + lang + "_COMPILE_FEATURES"); this->GetDefinition("CMAKE_" + lang + "_COMPILE_FEATURES");
...@@ -5071,6 +5083,16 @@ AddRequiredTargetFeature(cmTarget *target, const std::string& feature, ...@@ -5071,6 +5083,16 @@ AddRequiredTargetFeature(cmTarget *target, const std::string& feature,
target->AppendProperty("COMPILE_FEATURES", feature.c_str()); target->AppendProperty("COMPILE_FEATURES", feature.c_str());
return isCFeature
? this->AddRequiredTargetCFeature(target, feature)
: this->AddRequiredTargetCxxFeature(target, feature);
}
//----------------------------------------------------------------------------
bool cmMakefile::
AddRequiredTargetCxxFeature(cmTarget *target,
const std::string& feature) const
{
bool needCxx98 = false; bool needCxx98 = false;
bool needCxx11 = false; bool needCxx11 = false;
...@@ -5136,3 +5158,93 @@ AddRequiredTargetFeature(cmTarget *target, const std::string& feature, ...@@ -5136,3 +5158,93 @@ AddRequiredTargetFeature(cmTarget *target, const std::string& feature,
} }
return true; return true;
} }
//----------------------------------------------------------------------------
bool cmMakefile::
AddRequiredTargetCFeature(cmTarget *target, const std::string& feature) const
{
bool needC90 = false;
bool needC99 = false;
bool needC11 = false;
if (const char *propC90 =
this->GetDefinition("CMAKE_C90_COMPILE_FEATURES"))
{
std::vector<std::string> props;
cmSystemTools::ExpandListArgument(propC90, props);
needC90 = std::find(props.begin(), props.end(), feature) != props.end();
}
if (const char *propC99 =
this->GetDefinition("CMAKE_C99_COMPILE_FEATURES"))
{
std::vector<std::string> props;
cmSystemTools::ExpandListArgument(propC99, props);
needC99 = std::find(props.begin(), props.end(), feature) != props.end();
}
if (const char *propC11 =
this->GetDefinition("CMAKE_C11_COMPILE_FEATURES"))
{
std::vector<std::string> props;
cmSystemTools::ExpandListArgument(propC11, props);
needC11 = std::find(props.begin(), props.end(), feature) != props.end();
}
const char *existingCStandard = target->GetProperty("C_STANDARD");
if (existingCStandard)
{
if (std::find_if(cmArrayBegin(C_STANDARDS), cmArrayEnd(C_STANDARDS),
cmStrCmp(existingCStandard)) == cmArrayEnd(C_STANDARDS))
{
cmOStringStream e;
e << "The C_STANDARD property on target \"" << target->GetName()
<< "\" contained an invalid value: \"" << existingCStandard << "\".";
this->IssueMessage(cmake::FATAL_ERROR, e.str().c_str());
return false;
}
}
const char * const *existingCIt = existingCStandard
? std::find_if(cmArrayBegin(C_STANDARDS),
cmArrayEnd(C_STANDARDS),
cmStrCmp(existingCStandard))
: cmArrayEnd(C_STANDARDS);
bool setC90 = needC90 && !existingCStandard;
bool setC99 = needC99 && !existingCStandard;
bool setC11 = needC11 && !existingCStandard;
if (needC11 && existingCStandard && existingCIt <
std::find_if(cmArrayBegin(C_STANDARDS),
cmArrayEnd(C_STANDARDS),
cmStrCmp("11")))
{
setC11 = true;
}
else if(needC99 && existingCStandard && existingCIt <