Merge topic 'target_compile_features'

9eaf3755 Export: Populate INTERFACE_COMPILE_FEATURES property.
8ed59fc2 Add target_compile_features command.
4e6ca504 cmTargetPropCommandBase: Change the interface to return bool.
5412dede cmTarget: Transitively evaluate compiler features.
baff4434 cmTarget: Allow populating COMPILE_FEATURES using generator expressions.
f97bf437 Features: Add cxx_auto_type.
03355d6b cmTarget: Add COMPILE_FEATURES target property.
faeddf64 project: Add infrastructure for recording CXX compiler features
913394af cmTarget: Add CXX_STANDARD and CXX_EXTENSION target properties.
8238a6cd Add some COMPILE_OPTIONS for specifying C++ dialect.
892243fc Tests: Require CMake 3.0 for the SystemInformation test.
59b5fdd3 Don't load Clang-CXX from AppleClang-CXX.
This commit is contained in:
Brad King 2014-04-15 10:32:11 -04:00 committed by CMake Topic Stage
commit b56a9ae7f1
118 changed files with 1209 additions and 21 deletions

View File

@ -0,0 +1,30 @@
target_compile_features
-----------------------
Add expected compiler features to a target.
::
target_compile_features(<target> <PRIVATE|PUBLIC|INTERFACE> <feature> [...])
Specify compiler features required when compiling a given target. If the
feature is not listed in the :variable:`CMAKE_CXX_COMPILE_FEATURES` variable,
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
automatically.
The ``INTERFACE``, ``PUBLIC`` and ``PRIVATE`` keywords are required to
specify the scope of the features. ``PRIVATE`` and ``PUBLIC`` items will
populate the :prop_tgt:`COMPILE_FEATURES` property of ``<target>``.
``PUBLIC`` and ``INTERFACE`` items will populate the
:prop_tgt:`INTERFACE_COMPILE_FEATURES` property of ``<target>``. Repeated
calls for the same ``<target>`` append items.
The named ``<target>`` must have been created by a command such as
:command:`add_executable` or :command:`add_library` and must not be
an ``IMPORTED`` target.
Arguments to ``target_compile_features`` may use "generator expressions"
with the syntax ``$<...>``.
See the :manual:`cmake-generator-expressions(7)` manual for available
expressions.

View File

@ -91,6 +91,7 @@ These commands may be used freely in CMake projects.
/command/source_group /command/source_group
/command/string /command/string
/command/target_compile_definitions /command/target_compile_definitions
/command/target_compile_features
/command/target_compile_options /command/target_compile_options
/command/target_include_directories /command/target_include_directories
/command/target_link_libraries /command/target_link_libraries

View File

@ -98,6 +98,7 @@ Properties on Targets
/prop_tgt/COMPATIBLE_INTERFACE_STRING /prop_tgt/COMPATIBLE_INTERFACE_STRING
/prop_tgt/COMPILE_DEFINITIONS_CONFIG /prop_tgt/COMPILE_DEFINITIONS_CONFIG
/prop_tgt/COMPILE_DEFINITIONS /prop_tgt/COMPILE_DEFINITIONS
/prop_tgt/COMPILE_FEATURES
/prop_tgt/COMPILE_FLAGS /prop_tgt/COMPILE_FLAGS
/prop_tgt/COMPILE_OPTIONS /prop_tgt/COMPILE_OPTIONS
/prop_tgt/COMPILE_PDB_NAME /prop_tgt/COMPILE_PDB_NAME
@ -106,6 +107,8 @@ Properties on Targets
/prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG /prop_tgt/COMPILE_PDB_OUTPUT_DIRECTORY_CONFIG
/prop_tgt/CONFIG_OUTPUT_NAME /prop_tgt/CONFIG_OUTPUT_NAME
/prop_tgt/CONFIG_POSTFIX /prop_tgt/CONFIG_POSTFIX
/prop_tgt/CXX_STANDARD
/prop_tgt/CXX_EXTENSIONS
/prop_tgt/DEBUG_POSTFIX /prop_tgt/DEBUG_POSTFIX
/prop_tgt/DEFINE_SYMBOL /prop_tgt/DEFINE_SYMBOL
/prop_tgt/EchoString /prop_tgt/EchoString
@ -148,6 +151,7 @@ Properties on Targets
/prop_tgt/INSTALL_RPATH_USE_LINK_PATH /prop_tgt/INSTALL_RPATH_USE_LINK_PATH
/prop_tgt/INTERFACE_AUTOUIC_OPTIONS /prop_tgt/INTERFACE_AUTOUIC_OPTIONS
/prop_tgt/INTERFACE_COMPILE_DEFINITIONS /prop_tgt/INTERFACE_COMPILE_DEFINITIONS
/prop_tgt/INTERFACE_COMPILE_FEATURES
/prop_tgt/INTERFACE_COMPILE_OPTIONS /prop_tgt/INTERFACE_COMPILE_OPTIONS
/prop_tgt/INTERFACE_INCLUDE_DIRECTORIES /prop_tgt/INTERFACE_INCLUDE_DIRECTORIES
/prop_tgt/INTERFACE_LINK_LIBRARIES /prop_tgt/INTERFACE_LINK_LIBRARIES

View File

@ -257,6 +257,10 @@ Variables for Languages
:maxdepth: 1 :maxdepth: 1
/variable/CMAKE_COMPILER_IS_GNULANG /variable/CMAKE_COMPILER_IS_GNULANG
/variable/CMAKE_CXX_COMPILE_FEATURES
/variable/CMAKE_CXX_KNOWN_FEATURES
/variable/CMAKE_CXX_STANDARD
/variable/CMAKE_CXX_EXTENSIONS
/variable/CMAKE_Fortran_MODDIR_DEFAULT /variable/CMAKE_Fortran_MODDIR_DEFAULT
/variable/CMAKE_Fortran_MODDIR_FLAG /variable/CMAKE_Fortran_MODDIR_FLAG
/variable/CMAKE_Fortran_MODOUT_FLAG /variable/CMAKE_Fortran_MODOUT_FLAG

View File

@ -0,0 +1,11 @@
COMPILE_FEATURES
----------------
Compiler features enabled for this target.
The list of features in this property are a subset of the features listed
in the :variable:`CMAKE_CXX_COMPILE_FEATURES` variable.
Contents of ``COMPILE_FEATURES`` may use "generator expressions" with the
syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)` manual for
available expressions.

View File

@ -0,0 +1,8 @@
CXX_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=gnu++11`` instead of ``-std=c++11`` to the compile line.

View File

@ -0,0 +1,14 @@
CXX_STANDARD
------------
The C++ standard whose features are required to build this target.
This property specifies the C++ standard whose features are required
to build this target. For some compilers, this results in adding a
flag such as ``-std=c++11`` to the compile line.
Supported values are ``98`` and ``11``.
This property is initialized by the value of
the :variable:`CMAKE_CXX_STANDARD` variable if it is set when a target
is created.

View File

@ -0,0 +1,14 @@
INTERFACE_COMPILE_FEATURES
--------------------------
List of public compile requirements for a library.
Targets may populate this property to publish the compiler features
required to compile against the headers for the target. Consuming
targets can add entries to their own :prop_tgt:`COMPILE_FEATURES`
property such as ``$<TARGET_PROPERTY:foo,INTERFACE_COMPILE_FEATURES>``
to require the features specified in the interface of ``foo``.
Contents of ``INTERFACE_COMPILE_FEATURES`` may use "generator expressions"
with the syntax ``$<...>``. See the :manual:`cmake-generator-expressions(7)`
manual for available expressions.

View File

@ -0,0 +1,18 @@
target-language-features
------------------------
* New :prop_tgt:`CXX_STANDARD` and :prop_tgt:`CXX_EXTENSIONS` target
properties may specify values which CMake uses to compute required
compile options such as ``-std=c++11`` or ``-std=gnu++11``. The
:variable:`CMAKE_CXX_STANDARD` and :variable:`CMAKE_CXX_EXTENSIONS`
variables may be set to initialize the target properties.
* New :prop_tgt:`COMPILE_FEATURES` target property may contain a list
of features required to compile a target. CMake uses this
information to ensure that the compiler in use is capable of building
the target, and to add any necessary compile flags to support language
features.
* New :command:`target_compile_features` command allows populating the
:prop_tgt:`COMPILE_FEATURES` target property, just like any other
build variable.

View File

@ -0,0 +1,8 @@
CMAKE_CXX_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 :variable:`CMAKE_CXX_KNOWN_FEATURES`
variable.

View File

@ -0,0 +1,8 @@
CMAKE_CXX_EXTENSIONS
--------------------
Default value for ``CXX_EXTENSIONS`` property of targets.
This variable is used to initialize the :prop_tgt:`CXX_EXTENSIONS`
property on all targets. See that target property for additional
information.

View File

@ -0,0 +1,18 @@
CMAKE_CXX_KNOWN_FEATURES
------------------------
List of C++ features known to this version of CMake.
The features listed in this variable 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_CXX_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:
``cxx_auto_type``
Automatic type deduction, as defined in N1984_.
.. _N1984: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1984.pdf

View File

@ -0,0 +1,8 @@
CMAKE_CXX_STANDARD
------------------
Default value for ``CXX_STANDARD`` property of targets.
This variable is used to initialize the :prop_tgt:`CXX_STANDARD`
property on all targets. See that target property for additional
information.

View File

@ -7,7 +7,7 @@ This variable can be populated with a list of properties to generate
debug output for when evaluating target properties. Currently it can debug output for when evaluating target properties. Currently it can
only be used when evaluating the :prop_tgt:`INCLUDE_DIRECTORIES`, only be used when evaluating the :prop_tgt:`INCLUDE_DIRECTORIES`,
:prop_tgt:`COMPILE_DEFINITIONS`, :prop_tgt:`COMPILE_OPTIONS`, :prop_tgt:`COMPILE_DEFINITIONS`, :prop_tgt:`COMPILE_OPTIONS`,
:prop_tgt:`AUTOUIC_OPTIONS`, :prop_tgt:`SOURCES`, :prop_tgt:`AUTOUIC_OPTIONS`, :prop_tgt:`SOURCES`, :prop_tgt:`COMPILE_FEATURES`,
:prop_tgt:`POSITION_INDEPENDENT_CODE` target properties and any other property :prop_tgt:`POSITION_INDEPENDENT_CODE` target properties and any other property
listed in :prop_tgt:`COMPATIBLE_INTERFACE_STRING` and other ``COMPATIBLE_INTERFACE_`` listed in :prop_tgt:`COMPATIBLE_INTERFACE_STRING` and other ``COMPATIBLE_INTERFACE_``
properties. It outputs an origin for each entry in the target property. properties. It outputs an origin for each entry in the target property.

View File

@ -2,6 +2,9 @@ set(CMAKE_CXX_COMPILER "@CMAKE_CXX_COMPILER@")
set(CMAKE_CXX_COMPILER_ARG1 "@CMAKE_CXX_COMPILER_ARG1@") set(CMAKE_CXX_COMPILER_ARG1 "@CMAKE_CXX_COMPILER_ARG1@")
set(CMAKE_CXX_COMPILER_ID "@CMAKE_CXX_COMPILER_ID@") set(CMAKE_CXX_COMPILER_ID "@CMAKE_CXX_COMPILER_ID@")
set(CMAKE_CXX_COMPILER_VERSION "@CMAKE_CXX_COMPILER_VERSION@") set(CMAKE_CXX_COMPILER_VERSION "@CMAKE_CXX_COMPILER_VERSION@")
set(CMAKE_CXX_COMPILE_FEATURES "@CMAKE_CXX_COMPILE_FEATURES@")
set(CMAKE_CXX11_COMPILE_FEATURES "@CMAKE_CXX11_COMPILE_FEATURES@")
set(CMAKE_CXX_PLATFORM_ID "@CMAKE_CXX_PLATFORM_ID@") set(CMAKE_CXX_PLATFORM_ID "@CMAKE_CXX_PLATFORM_ID@")
set(CMAKE_CXX_SIMULATE_ID "@CMAKE_CXX_SIMULATE_ID@") set(CMAKE_CXX_SIMULATE_ID "@CMAKE_CXX_SIMULATE_ID@")
set(CMAKE_CXX_SIMULATE_VERSION "@CMAKE_CXX_SIMULATE_VERSION@") set(CMAKE_CXX_SIMULATE_VERSION "@CMAKE_CXX_SIMULATE_VERSION@")

View File

@ -0,0 +1,43 @@
#=============================================================================
# Copyright 2013 Stephen Kelly <steveire@gmail.com>
#
# Distributed under the OSI-approved BSD License (the "License");
# see accompanying file Copyright.txt for details.
#
# This software is distributed WITHOUT ANY WARRANTY; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the License for more information.
#=============================================================================
# (To distribute this file outside of CMake, substitute the full
# License text for the above reference.)
function(cmake_determine_compile_features lang)
if(lang STREQUAL CXX AND COMMAND cmake_record_cxx_compile_features)
message(STATUS "Detecting ${lang} compile features")
set(CMAKE_CXX11_COMPILE_FEATURES)
include("${CMAKE_ROOT}/Modules/Internal/FeatureTesting.cmake")
cmake_record_cxx_compile_features()
if(NOT _result EQUAL 0)
message(STATUS "Detecting ${lang} compile features - failed")
return()
endif()
if(NOT CMAKE_CXX_COMPILE_FEATURES)
set(CMAKE_CXX_COMPILE_FEATURES
${CMAKE_CXX11_COMPILE_FEATURES}
)
endif()
set(CMAKE_CXX_COMPILE_FEATURES ${CMAKE_CXX_COMPILE_FEATURES} PARENT_SCOPE)
set(CMAKE_CXX11_COMPILE_FEATURES ${CMAKE_CXX11_COMPILE_FEATURES} PARENT_SCOPE)
message(STATUS "Detecting ${lang} compile features - done")
endif()
endfunction()

View File

@ -66,6 +66,9 @@ else()
# Try to identify the ABI and configure it into CMakeCXXCompiler.cmake # Try to identify the ABI and configure it into CMakeCXXCompiler.cmake
include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerABI.cmake) include(${CMAKE_ROOT}/Modules/CMakeDetermineCompilerABI.cmake)
CMAKE_DETERMINE_COMPILER_ABI(CXX ${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp) CMAKE_DETERMINE_COMPILER_ABI(CXX ${CMAKE_ROOT}/Modules/CMakeCXXCompilerABI.cpp)
# Try to identify the compiler features
include(${CMAKE_ROOT}/Modules/CMakeDetermineCompileFeatures.cmake)
CMAKE_DETERMINE_COMPILE_FEATURES(CXX)
# Re-configure to save learned information. # Re-configure to save learned information.
configure_file( configure_file(

View File

@ -1 +1,6 @@
include(Compiler/Clang-CXX) include(Compiler/Clang)
__compiler_clang(CXX)
if(NOT CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC")
set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden")
endif()

View File

@ -4,3 +4,21 @@ __compiler_clang(CXX)
if(NOT CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC") if(NOT CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC")
set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden") set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden")
endif() endif()
cmake_policy(GET CMP0025 appleClangPolicy)
if(NOT appleClangPolicy STREQUAL NEW)
return()
endif()
if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 2.1)
set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "-std=c++98")
set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "-std=gnu++98")
endif()
if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 3.1)
set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-std=c++11")
set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-std=gnu++11")
elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 2.1)
set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-std=c++0x")
set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-std=gnu++0x")
endif()

View File

@ -0,0 +1,8 @@
# Reference: http://gcc.gnu.org/projects/cxx0x.html
set(_oldestSupported "(__GNUC__ * 100 + __GNUC_MINOR__) >= 408")
# TODO: Should be supported by GNU 4.4
set(GNU44_CXX11 "${_oldestSupported} && __cplusplus >= 201103L")
set(_cmake_feature_test_cxx_auto_type "${GNU44_CXX11}")
set(_oldestSupported)

View File

@ -10,3 +10,28 @@ else()
set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden") set(CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN "-fvisibility-inlines-hidden")
endif() endif()
endif() endif()
if(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.3)
set(CMAKE_CXX98_STANDARD_COMPILE_OPTION "-std=c++98")
set(CMAKE_CXX98_EXTENSION_COMPILE_OPTION "-std=gnu++98")
endif()
if (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.7)
set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-std=c++11")
set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-std=gnu++11")
elseif(NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.3)
set(CMAKE_CXX11_STANDARD_COMPILE_OPTION "-std=c++0x")
set(CMAKE_CXX11_EXTENSION_COMPILE_OPTION "-std=gnu++0x")
endif()
macro(cmake_record_cxx_compile_features)
macro(_get_gcc_features std_version list)
record_compiler_features(CXX "-std=${std_version}" ${list})
endmacro()
if (UNIX AND NOT APPLE AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8)
_get_gcc_features(c++11 CMAKE_CXX11_COMPILE_FEATURES)
else()
set(_result 0)
endif()
endmacro()

View File

@ -0,0 +1,57 @@
macro(record_compiler_features lang compile_flags feature_list)
include("${CMAKE_ROOT}/Modules/Compiler/${CMAKE_${lang}_COMPILER_ID}-${lang}-FeatureTests.cmake" OPTIONAL)
string(TOLOWER ${lang} lang_lc)
file(REMOVE "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.bin")
file(WRITE "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.${lang_lc}" "
extern const char features[] = {\"\"\n")
foreach(feature ${CMAKE_${lang}_KNOWN_FEATURES})
if (_cmake_feature_test_${feature})
if (${_cmake_feature_test_${feature}} STREQUAL 1)
set(_feature_condition "\"1\" ")
else()
set(_feature_condition "#if ${_cmake_feature_test_${feature}}\n\"1\"\n#else\n\"0\"\n#endif\n")
endif()
file(APPEND "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.${lang_lc}" "\"${lang}_FEATURE:\"\n${_feature_condition}\"${feature}\\n\"\n")
endif()
endforeach()
file(APPEND "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.${lang_lc}"
"\n};\n\nint main(int, char **) { return 0; }\n")
try_compile(CMAKE_${lang}_FEATURE_TEST
${CMAKE_BINARY_DIR} "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.${lang_lc}"
COMPILE_DEFINITIONS "${compile_flags}"
OUTPUT_VARIABLE _output
COPY_FILE "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.bin"
COPY_FILE_ERROR _copy_error
)
if(CMAKE_${lang}_FEATURE_TEST AND NOT _copy_error)
set(_result 0)
else()
set(_result 255)
endif()
unset(CMAKE_${lang}_FEATURE_TEST CACHE)
if (_result EQUAL 0)
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
"\n\nDetecting ${lang} [${compile_flags}] compiler features compiled with the following output:\n${_output}\n\n")
if(EXISTS "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.bin")
file(STRINGS "${CMAKE_BINARY_DIR}/CMakeFiles/feature_tests.bin"
features REGEX "${lang}_FEATURE:.*")
foreach(info ${features})
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log
" Feature record: ${info}\n")
string(REPLACE "${lang}_FEATURE:" "" info ${info})
string(SUBSTRING ${info} 0 1 has_feature)
if(has_feature)
string(REGEX REPLACE "^1" "" feature ${info})
list(APPEND ${feature_list} ${feature})
endif()
endforeach()
endif()
else()
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Detecting ${lang} [${compile_flags}] compiler features failed to compile with the following output:\n${_output}\n${_copy_error}\n\n")
endif()
endmacro()

View File

@ -346,6 +346,7 @@ foreach(command_file
cmSourceGroupCommand cmSourceGroupCommand
cmSubdirDependsCommand cmSubdirDependsCommand
cmTargetCompileDefinitionsCommand cmTargetCompileDefinitionsCommand
cmTargetCompileFeaturesCommand
cmTargetCompileOptionsCommand cmTargetCompileOptionsCommand
cmTargetIncludeDirectoriesCommand cmTargetIncludeDirectoriesCommand
cmTargetSourcesCommand cmTargetSourcesCommand

View File

@ -85,6 +85,9 @@ bool cmExportBuildFileGenerator::GenerateMainFile(std::ostream& os)
this->PopulateInterfaceProperty("INTERFACE_AUTOUIC_OPTIONS", te, this->PopulateInterfaceProperty("INTERFACE_AUTOUIC_OPTIONS", te,
cmGeneratorExpression::BuildInterface, cmGeneratorExpression::BuildInterface,
properties, missingTargets); properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_COMPILE_FEATURES", te,
cmGeneratorExpression::BuildInterface,
properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE", this->PopulateInterfaceProperty("INTERFACE_POSITION_INDEPENDENT_CODE",
te, properties); te, properties);
const bool newCMP0022Behavior = const bool newCMP0022Behavior =

View File

@ -149,6 +149,10 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
te, te,
cmGeneratorExpression::InstallInterface, cmGeneratorExpression::InstallInterface,
properties, missingTargets); properties, missingTargets);
this->PopulateInterfaceProperty("INTERFACE_COMPILE_FEATURES",
te,
cmGeneratorExpression::InstallInterface,
properties, missingTargets);
const bool newCMP0022Behavior = const bool newCMP0022Behavior =
te->GetPolicyStatusCMP0022() != cmPolicies::WARN te->GetPolicyStatusCMP0022() != cmPolicies::WARN

View File

@ -26,7 +26,8 @@
SELECT(F, EvaluatingCompileDefinitions, COMPILE_DEFINITIONS) \ SELECT(F, EvaluatingCompileDefinitions, COMPILE_DEFINITIONS) \
SELECT(F, EvaluatingCompileOptions, COMPILE_OPTIONS) \ SELECT(F, EvaluatingCompileOptions, COMPILE_OPTIONS) \
SELECT(F, EvaluatingAutoUicOptions, AUTOUIC_OPTIONS) \ SELECT(F, EvaluatingAutoUicOptions, AUTOUIC_OPTIONS) \
SELECT(F, EvaluatingSources, SOURCES) SELECT(F, EvaluatingSources, SOURCES) \
SELECT(F, EvaluatingCompileFeatures, COMPILE_FEATURES)
#define CM_FOR_EACH_TRANSITIVE_PROPERTY(F) \ #define CM_FOR_EACH_TRANSITIVE_PROPERTY(F) \
CM_FOR_EACH_TRANSITIVE_PROPERTY_IMPL(F, CM_SELECT_BOTH) CM_FOR_EACH_TRANSITIVE_PROPERTY_IMPL(F, CM_SELECT_BOTH)

View File

@ -1460,6 +1460,17 @@ void cmLocalGenerator::AddCompileOptions(
this->AppendFlagEscape(flags, *i); this->AppendFlagEscape(flags, *i);
} }
} }
std::vector<std::string> features;
target->GetCompileFeatures(features, config);
for(std::vector<std::string>::const_iterator it = features.begin();
it != features.end(); ++it)
{
if (!this->Makefile->AddRequiredTargetFeature(target, *it))
{
return;
}
}
this->AddCompilerRequirementFlag(flags, target, lang);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -2131,6 +2142,34 @@ void cmLocalGenerator::AddSharedFlags(std::string& flags,
} }
} }
//----------------------------------------------------------------------------
void cmLocalGenerator::
AddCompilerRequirementFlag(std::string &flags, cmTarget* target,
const std::string& lang)
{
if (lang.empty())
{
return;
}
std::string stdProp = lang + "_STANDARD";
const char *standard = target->GetProperty(stdProp);
if (!standard)
{
return;
}
std::string extProp = lang + "_EXTENSIONS";
bool ext = target->GetPropertyAsBool(extProp);
std::string type = ext ? "EXTENSION" : "STANDARD";
std::string compile_option =
"CMAKE_" + lang + std::string(standard)
+ "_" + type + "_COMPILE_OPTION";
if (const char *opt = target->GetMakefile()->GetDefinition(compile_option))
{
this->AppendFlags(flags, opt);
}
}
static void AddVisibilityCompileOption(std::string &flags, cmTarget* target, static void AddVisibilityCompileOption(std::string &flags, cmTarget* target,
cmLocalGenerator *lg, cmLocalGenerator *lg,
const std::string& lang) const std::string& lang)

View File

@ -149,6 +149,8 @@ public:
const std::string& lang); const std::string& lang);
void AddConfigVariableFlags(std::string& flags, const std::string& var, void AddConfigVariableFlags(std::string& flags, const std::string& var,
const std::string& config); const std::string& config);
void AddCompilerRequirementFlag(std::string &flags, cmTarget* target,
const std::string& lang);
///! Append flags to a string. ///! Append flags to a string.
virtual void AppendFlags(std::string& flags, const char* newFlags); virtual void AppendFlags(std::string& flags, const char* newFlags);
virtual void AppendFlagEscape(std::string& flags, virtual void AppendFlagEscape(std::string& flags,

View File

@ -41,6 +41,9 @@
#include <ctype.h> // for isspace #include <ctype.h> // for isspace
#include <assert.h> #include <assert.h>
#define FOR_EACH_CXX_FEATURE(F) \
F(cxx_auto_type)
class cmMakefile::Internals class cmMakefile::Internals
{ {
public: public:
@ -2451,6 +2454,12 @@ const char* cmMakefile::GetDefinition(const std::string& name) const
{ {
this->Internal->VarUsageStack.top().insert(name); this->Internal->VarUsageStack.top().insert(name);
} }
if (name == "CMAKE_CXX_KNOWN_FEATURES")
{
#define STRING_LIST_ELEMENT(F) ";" #F
return FOR_EACH_CXX_FEATURE(STRING_LIST_ELEMENT) + 1;
#undef STRING_LIST_ELEMENT
}
const char* def = this->Internal->VarStack.top().Get(name); const char* def = this->Internal->VarStack.top().Get(name);
if(!def) if(!def)
{ {
@ -4494,3 +4503,127 @@ void cmMakefile::RecordPolicies(cmPolicies::PolicyMap& pm)
pm[pid] = this->GetPolicyStatus(pid); pm[pid] = this->GetPolicyStatus(pid);
} }
} }
#define FEATURE_STRING(F) , #F
static const char * const CXX_FEATURES[] = {
0
FOR_EACH_CXX_FEATURE(FEATURE_STRING)
};
static const char * const CXX_STANDARDS[] = {
"98"
, "11"
};
//----------------------------------------------------------------------------
bool cmMakefile::
AddRequiredTargetFeature(cmTarget *target, const std::string& feature,
std::string *error) const
{
if (cmGeneratorExpression::Find(feature) != std::string::npos)
{
target->AppendProperty("COMPILE_FEATURES", feature.c_str());
return true;
}
bool isCxxFeature = std::find_if(cmArrayBegin(CXX_FEATURES) + 1,
cmArrayEnd(CXX_FEATURES), cmStrCmp(feature))
!= cmArrayEnd(CXX_FEATURES);
if (!isCxxFeature)
{
cmOStringStream e;
if (error)
{
e << "specified";
}
else
{
e << "Specified";
}
e << " unknown feature \"" << feature << "\" for "
"target \"" << target->GetName() << "\".";
if (error)
{
*error = e.str();
}
else
{
this->IssueMessage(cmake::FATAL_ERROR, e.str());
}
return false;
}
std::string lang = "CXX";
const char* featuresKnown =
this->GetDefinition("CMAKE_" + lang + "_COMPILE_FEATURES");
if (!featuresKnown || !*featuresKnown)
{
// We know of no features for the compiler at all.
return true;
}
std::vector<std::string> availableFeatures;
cmSystemTools::ExpandListArgument(featuresKnown, availableFeatures);
if (std::find(availableFeatures.begin(),
availableFeatures.end(),
feature) == availableFeatures.end())
{
cmOStringStream e;
e << "The compiler feature \"" << feature
<< "\" is not known to compiler\n\""
<< this->GetDefinition("CMAKE_" + lang + "_COMPILER_ID")
<< "\"\nversion "
<< this->GetDefinition("CMAKE_" + lang + "_COMPILER_VERSION") << ".";
this->IssueMessage(cmake::FATAL_ERROR, e.str());
return false;
}
target->AppendProperty("COMPILE_FEATURES", feature.c_str());
bool needCxx11 = false;
if (const char *propCxx11 =
this->GetDefinition("CMAKE_CXX11_COMPILE_FEATURES"))
{
std::vector<std::string> props;
cmSystemTools::ExpandListArgument(propCxx11, props);
needCxx11 = std::find(props.begin(), props.end(), feature) != props.end();
}
const char *existingCxxStandard = target->GetProperty("CXX_STANDARD");
if (existingCxxStandard)
{
if (std::find_if(cmArrayBegin(CXX_STANDARDS), cmArrayEnd(CXX_STANDARDS),
cmStrCmp(existingCxxStandard)) == cmArrayEnd(CXX_STANDARDS))
{
cmOStringStream e;
e << "The CXX_STANDARD property on target \"" << target->GetName()
<< "\" contained an invalid value: \"" << existingCxxStandard << "\".";
this->IssueMessage(cmake::FATAL_ERROR, e.str());
return false;
}
}
const char * const *existingCxxIt = existingCxxStandard
? std::find_if(cmArrayBegin(CXX_STANDARDS),
cmArrayEnd(CXX_STANDARDS),
cmStrCmp(existingCxxStandard))
: cmArrayEnd(CXX_STANDARDS);
bool setCxx11 = needCxx11 && !existingCxxStandard;
if (needCxx11 && existingCxxStandard && existingCxxIt <
std::find_if(cmArrayBegin(CXX_STANDARDS),
cmArrayEnd(CXX_STANDARDS),
cmStrCmp("11")))
{
setCxx11 = true;
}
if (setCxx11)
{
target->SetProperty("CXX_STANDARD", "11");
}
return true;
}

View File

@ -885,6 +885,10 @@ public:
bool PolicyOptionalWarningEnabled(std::string const& var); bool PolicyOptionalWarningEnabled(std::string const& var);
bool AddRequiredTargetFeature(cmTarget *target,
const std::string& feature,
std::string *error = 0) const;
protected: protected:
// add link libraries and directories to the target // add link libraries and directories to the target
void AddGlobalLinkInformation(const std::string& name, cmTarget& target); void AddGlobalLinkInformation(const std::string& name, cmTarget& target);

View File

@ -153,6 +153,7 @@ public:
}; };
std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries; std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries;
std::vector<TargetPropertyEntry*> CompileOptionsEntries; std::vector<TargetPropertyEntry*> CompileOptionsEntries;
std::vector<TargetPropertyEntry*> CompileFeaturesEntries;
std::vector<TargetPropertyEntry*> CompileDefinitionsEntries; std::vector<TargetPropertyEntry*> CompileDefinitionsEntries;
std::vector<TargetPropertyEntry*> SourceEntries; std::vector<TargetPropertyEntry*> SourceEntries;
std::vector<cmValueWithOrigin> LinkImplementationPropertyEntries; std::vector<cmValueWithOrigin> LinkImplementationPropertyEntries;
@ -165,11 +166,14 @@ public:
CachedLinkInterfaceCompileDefinitionsEntries; CachedLinkInterfaceCompileDefinitionsEntries;
mutable std::map<std::string, std::vector<TargetPropertyEntry*> > mutable std::map<std::string, std::vector<TargetPropertyEntry*> >
CachedLinkInterfaceSourcesEntries; CachedLinkInterfaceSourcesEntries;
mutable std::map<std::string, std::vector<TargetPropertyEntry*> >
CachedLinkInterfaceCompileFeaturesEntries;
mutable std::map<std::string, bool> CacheLinkInterfaceIncludeDirectoriesDone; mutable std::map<std::string, bool> CacheLinkInterfaceIncludeDirectoriesDone;
mutable std::map<std::string, bool> CacheLinkInterfaceCompileDefinitionsDone; mutable std::map<std::string, bool> CacheLinkInterfaceCompileDefinitionsDone;
mutable std::map<std::string, bool> CacheLinkInterfaceCompileOptionsDone; mutable std::map<std::string, bool> CacheLinkInterfaceCompileOptionsDone;
mutable std::map<std::string, bool> CacheLinkInterfaceSourcesDone; mutable std::map<std::string, bool> CacheLinkInterfaceSourcesDone;
mutable std::map<std::string, bool> CacheLinkInterfaceCompileFeaturesDone;
}; };
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -204,6 +208,7 @@ cmTargetInternals::~cmTargetInternals()
{ {
deleteAndClear(this->CachedLinkInterfaceIncludeDirectoriesEntries); deleteAndClear(this->CachedLinkInterfaceIncludeDirectoriesEntries);
deleteAndClear(this->CachedLinkInterfaceCompileOptionsEntries); deleteAndClear(this->CachedLinkInterfaceCompileOptionsEntries);
deleteAndClear(this->CachedLinkInterfaceCompileFeaturesEntries);
deleteAndClear(this->CachedLinkInterfaceCompileDefinitionsEntries); deleteAndClear(this->CachedLinkInterfaceCompileDefinitionsEntries);
deleteAndClear(this->CachedLinkInterfaceSourcesEntries); deleteAndClear(this->CachedLinkInterfaceSourcesEntries);
} }
@ -227,6 +232,7 @@ cmTarget::cmTarget()
this->BuildInterfaceIncludesAppended = false; this->BuildInterfaceIncludesAppended = false;
this->DebugIncludesDone = false; this->DebugIncludesDone = false;
this->DebugCompileOptionsDone = false; this->DebugCompileOptionsDone = false;
this->DebugCompileFeaturesDone = false;
this->DebugCompileDefinitionsDone = false; this->DebugCompileDefinitionsDone = false;
this->DebugSourcesDone = false; this->DebugSourcesDone = false;
this->LinkImplementationLanguageIsContextDependent = true; this->LinkImplementationLanguageIsContextDependent = true;
@ -308,6 +314,8 @@ void cmTarget::SetMakefile(cmMakefile* mf)
this->SetPropertyDefault("MACOSX_BUNDLE", 0); this->SetPropertyDefault("MACOSX_BUNDLE", 0);
this->SetPropertyDefault("MACOSX_RPATH", 0); this->SetPropertyDefault("MACOSX_RPATH", 0);
this->SetPropertyDefault("NO_SYSTEM_FROM_IMPORTED", 0); this->SetPropertyDefault("NO_SYSTEM_FROM_IMPORTED", 0);
this->SetPropertyDefault("CXX_STANDARD", 0);
this->SetPropertyDefault("CXX_EXTENSIONS", 0);
} }
// Collect the set of configuration types. // Collect the set of configuration types.
@ -1803,6 +1811,17 @@ void cmTarget::SetProperty(const std::string& prop, const char* value)
new cmTargetInternals::TargetPropertyEntry(cge)); new cmTargetInternals::TargetPropertyEntry(cge));
return; return;
} }
if(prop == "COMPILE_FEATURES")
{
cmListFileBacktrace lfbt;
this->Makefile->GetBacktrace(lfbt);
cmGeneratorExpression ge(lfbt);
deleteAndClear(this->Internal->CompileFeaturesEntries);
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(value);
this->Internal->CompileFeaturesEntries.push_back(
new cmTargetInternals::TargetPropertyEntry(cge));
return;
}
if(prop == "COMPILE_DEFINITIONS") if(prop == "COMPILE_DEFINITIONS")
{ {
cmListFileBacktrace lfbt; cmListFileBacktrace lfbt;
@ -1893,6 +1912,15 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value,
new cmTargetInternals::TargetPropertyEntry(ge.Parse(value))); new cmTargetInternals::TargetPropertyEntry(ge.Parse(value)));
return; return;
} }
if(prop == "COMPILE_FEATURES")
{
cmListFileBacktrace lfbt;
this->Makefile->GetBacktrace(lfbt);
cmGeneratorExpression ge(lfbt);
this->Internal->CompileFeaturesEntries.push_back(
new cmTargetInternals::TargetPropertyEntry(ge.Parse(value)));
return;
}
if(prop == "COMPILE_DEFINITIONS") if(prop == "COMPILE_DEFINITIONS")
{ {
cmListFileBacktrace lfbt; cmListFileBacktrace lfbt;
@ -2676,6 +2704,118 @@ void cmTarget::GetCompileDefinitions(std::vector<std::string> &list,
} }
} }
//----------------------------------------------------------------------------
static void processCompileFeatures(cmTarget const* tgt,
const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries,
std::vector<std::string> &options,
std::set<std::string> &uniqueOptions,
cmGeneratorExpressionDAGChecker *dagChecker,
const std::string& config, bool debugOptions)
{
processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
dagChecker, config, debugOptions, "features");
}
//----------------------------------------------------------------------------
void cmTarget::GetCompileFeatures(std::vector<std::string> &result,
const std::string& config) const
{
std::set<std::string> uniqueFeatures;
cmListFileBacktrace lfbt;
cmGeneratorExpressionDAGChecker dagChecker(lfbt,
this->GetName(),
"COMPILE_FEATURES",
0, 0);
std::vector<std::string> debugProperties;
const char *debugProp =
this->Makefile->GetDefinition("CMAKE_DEBUG_TARGET_PROPERTIES");
if (debugProp)
{
cmSystemTools::ExpandListArgument(debugProp, debugProperties);
}
bool debugFeatures = !this->DebugCompileFeaturesDone
&& std::find(debugProperties.begin(),
debugProperties.end(),
"COMPILE_FEATURES")
!= debugProperties.end();
if (this->Makefile->IsGeneratingBuildSystem())
{
this->DebugCompileFeaturesDone = true;
}
processCompileFeatures(this,
this->Internal->CompileFeaturesEntries,
result,
uniqueFeatures,
&dagChecker,
config,
debugFeatures);
if (!this->Internal->CacheLinkInterfaceCompileFeaturesDone[config])
{
for (std::vector<cmValueWithOrigin>::const_iterator
it = this->Internal->LinkImplementationPropertyEntries.begin(),
end = this->Internal->LinkImplementationPropertyEntries.end();
it != end; ++it)
{
if (!cmGeneratorExpression::IsValidTargetName(it->Value)
&& cmGeneratorExpression::Find(it->Value) == std::string::npos)
{
continue;
}
{
cmGeneratorExpression ge(lfbt);
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge =
ge.Parse(it->Value);
std::string targetResult = cge->Evaluate(this->Makefile, config,
false, this, 0, 0);
if (!this->Makefile->FindTargetToUse(targetResult))
{
continue;
}
}
std::string featureGenex = "$<TARGET_PROPERTY:" +
it->Value + ",INTERFACE_COMPILE_FEATURES>";
if (cmGeneratorExpression::Find(it->Value) != std::string::npos)
{
// Because it->Value is a generator expression, ensure that it
// evaluates to the non-empty string before being used in the
// TARGET_PROPERTY expression.
featureGenex = "$<$<BOOL:" + it->Value + ">:" + featureGenex + ">";
}
cmGeneratorExpression ge(it->Backtrace);
cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(
featureGenex);
this->Internal
->CachedLinkInterfaceCompileFeaturesEntries[config].push_back(
new cmTargetInternals::TargetPropertyEntry(cge,
it->Value));
}
}
processCompileFeatures(this,
this->Internal->CachedLinkInterfaceCompileFeaturesEntries[config],
result,
uniqueFeatures,
&dagChecker,
config,
debugFeatures);
if (!this->Makefile->IsGeneratingBuildSystem())
{
deleteAndClear(this->Internal->CachedLinkInterfaceCompileFeaturesEntries);
}
else
{
this->Internal->CacheLinkInterfaceCompileFeaturesDone[config] = true;
}
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmTarget::MaybeInvalidatePropertyCache(const std::string& prop) void cmTarget::MaybeInvalidatePropertyCache(const std::string& prop)
{ {
@ -3190,6 +3330,24 @@ const char *cmTarget::GetProperty(const std::string& prop,
} }
return output.c_str(); return output.c_str();
} }
if(prop == "COMPILE_FEATURES")
{
static std::string output;
output = "";
std::string sep;
typedef cmTargetInternals::TargetPropertyEntry
TargetPropertyEntry;
for (std::vector<TargetPropertyEntry*>::const_iterator
it = this->Internal->CompileFeaturesEntries.begin(),
end = this->Internal->CompileFeaturesEntries.end();
it != end; ++it)
{
output += sep;
output += (*it)->ge->GetInput();
sep = ";";
}
return output.c_str();
}
if(prop == "COMPILE_DEFINITIONS") if(prop == "COMPILE_DEFINITIONS")
{ {
static std::string output; static std::string output;
@ -6987,6 +7145,7 @@ cmTargetInternalPointer::~cmTargetInternalPointer()
{ {
deleteAndClear(this->Pointer->IncludeDirectoriesEntries); deleteAndClear(this->Pointer->IncludeDirectoriesEntries);
deleteAndClear(this->Pointer->CompileOptionsEntries); deleteAndClear(this->Pointer->CompileOptionsEntries);
deleteAndClear(this->Pointer->CompileFeaturesEntries);
deleteAndClear(this->Pointer->CompileDefinitionsEntries); deleteAndClear(this->Pointer->CompileDefinitionsEntries);
deleteAndClear(this->Pointer->SourceEntries); deleteAndClear(this->Pointer->SourceEntries);
delete this->Pointer; delete this->Pointer;

View File

@ -549,6 +549,8 @@ public:
const std::string& config) const; const std::string& config) const;
void GetAutoUicOptions(std::vector<std::string> &result, void GetAutoUicOptions(std::vector<std::string> &result,
const std::string& config) const; const std::string& config) const;
void GetCompileFeatures(std::vector<std::string> &features,
const std::string& config) const;
bool IsNullImpliedByLinkLibraries(const std::string &p) const; bool IsNullImpliedByLinkLibraries(const std::string &p) const;
bool IsLinkInterfaceDependentBoolProperty(const std::string &p, bool IsLinkInterfaceDependentBoolProperty(const std::string &p,
@ -715,6 +717,7 @@ private:
mutable bool DebugCompileOptionsDone; mutable bool DebugCompileOptionsDone;
mutable bool DebugCompileDefinitionsDone; mutable bool DebugCompileDefinitionsDone;
mutable bool DebugSourcesDone; mutable bool DebugSourcesDone;
mutable bool DebugCompileFeaturesDone;
mutable std::set<std::string> LinkImplicitNullProperties; mutable std::set<std::string> LinkImplicitNullProperties;
bool BuildInterfaceIncludesAppended; bool BuildInterfaceIncludesAppended;

View File

@ -58,9 +58,10 @@ std::string cmTargetCompileDefinitionsCommand
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmTargetCompileDefinitionsCommand bool cmTargetCompileDefinitionsCommand
::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content, ::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content,
bool, bool) bool, bool)
{ {
tgt->AppendProperty("COMPILE_DEFINITIONS", this->Join(content).c_str()); tgt->AppendProperty("COMPILE_DEFINITIONS", this->Join(content).c_str());
return true;
} }

View File

@ -44,7 +44,7 @@ private:
virtual void HandleImportedTarget(const std::string &tgt); virtual void HandleImportedTarget(const std::string &tgt);
virtual void HandleMissingTarget(const std::string &name); virtual void HandleMissingTarget(const std::string &name);
virtual void HandleDirectContent(cmTarget *tgt, virtual bool HandleDirectContent(cmTarget *tgt,
const std::vector<std::string> &content, const std::vector<std::string> &content,
bool prepend, bool system); bool prepend, bool system);
virtual std::string Join(const std::vector<std::string> &content); virtual std::string Join(const std::vector<std::string> &content);

View File

@ -0,0 +1,70 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2013 Stephen Kelly <steveire@gmail.com>
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#include "cmTargetCompileFeaturesCommand.h"
bool cmTargetCompileFeaturesCommand::InitialPass(
std::vector<std::string> const& args,
cmExecutionStatus &)
{
return this->HandleArguments(args, "COMPILE_FEATURES", NO_FLAGS);
}
void cmTargetCompileFeaturesCommand
::HandleImportedTarget(const std::string &tgt)
{
cmOStringStream e;
e << "Cannot specify compile features for imported target \""
<< tgt << "\".";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
}
void cmTargetCompileFeaturesCommand
::HandleMissingTarget(const std::string &name)
{
cmOStringStream e;
e << "Cannot specify compile features for target \"" << name << "\" "
"which is not built by this project.";
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
}
//----------------------------------------------------------------------------
std::string cmTargetCompileFeaturesCommand
::Join(const std::vector<std::string> &content)
{
std::string defs;
std::string sep;
for(std::vector<std::string>::const_iterator it = content.begin();
it != content.end(); ++it)
{
defs += sep + *it;
sep = ";";
}
return defs;
}
//----------------------------------------------------------------------------
bool cmTargetCompileFeaturesCommand
::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content,
bool, bool)
{
for(std::vector<std::string>::const_iterator it = content.begin();
it != content.end(); ++it)
{
std::string error;
if(!this->Makefile->AddRequiredTargetFeature(tgt, *it, &error))
{
this->SetError(error);
return false;
}
}
return true;
}

View File

@ -0,0 +1,41 @@
/*============================================================================
CMake - Cross Platform Makefile Generator
Copyright 2013 Stephen Kelly <steveire@gmail.com>
Distributed under the OSI-approved BSD License (the "License");
see accompanying file Copyright.txt for details.
This software is distributed WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
#ifndef cmTargetCompileFeaturesCommand_h
#define cmTargetCompileFeaturesCommand_h
#include "cmTargetPropCommandBase.h"
class cmTargetCompileFeaturesCommand : public cmTargetPropCommandBase
{
virtual cmCommand* Clone()
{
return new cmTargetCompileFeaturesCommand;
}
virtual bool InitialPass(std::vector<std::string> const& args,
cmExecutionStatus &status);
virtual std::string GetName() const { return "target_compile_features";}
cmTypeMacro(cmTargetCompileFeaturesCommand, cmTargetPropCommandBase);
private:
virtual void HandleImportedTarget(const std::string &tgt);
virtual void HandleMissingTarget(const std::string &name);
virtual bool HandleDirectContent(cmTarget *tgt,
const std::vector<std::string> &content,
bool prepend, bool system);
virtual std::string Join(const std::vector<std::string> &content);
};
#endif

View File

@ -51,7 +51,7 @@ std::string cmTargetCompileOptionsCommand
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmTargetCompileOptionsCommand bool cmTargetCompileOptionsCommand
::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content, ::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content,
bool, bool) bool, bool)
{ {
@ -59,4 +59,5 @@ void cmTargetCompileOptionsCommand
this->Makefile->GetBacktrace(lfbt); this->Makefile->GetBacktrace(lfbt);
cmValueWithOrigin entry(this->Join(content), lfbt); cmValueWithOrigin entry(this->Join(content), lfbt);
tgt->InsertCompileOption(entry); tgt->InsertCompileOption(entry);
return true;
} }

View File

@ -44,7 +44,7 @@ private:
virtual void HandleImportedTarget(const std::string &tgt); virtual void HandleImportedTarget(const std::string &tgt);
virtual void HandleMissingTarget(const std::string &name); virtual void HandleMissingTarget(const std::string &name);
virtual void HandleDirectContent(cmTarget *tgt, virtual bool HandleDirectContent(cmTarget *tgt,
const std::vector<std::string> &content, const std::vector<std::string> &content,
bool prepend, bool system); bool prepend, bool system);
virtual std::string Join(const std::vector<std::string> &content); virtual std::string Join(const std::vector<std::string> &content);

View File

@ -66,7 +66,7 @@ std::string cmTargetIncludeDirectoriesCommand
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmTargetIncludeDirectoriesCommand bool cmTargetIncludeDirectoriesCommand
::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content, ::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content,
bool prepend, bool system) bool prepend, bool system)
{ {
@ -78,6 +78,7 @@ void cmTargetIncludeDirectoriesCommand
{ {
tgt->AddSystemIncludeDirectories(content); tgt->AddSystemIncludeDirectories(content);
} }
return true;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------

View File

@ -45,7 +45,7 @@ private:
virtual void HandleImportedTarget(const std::string &tgt); virtual void HandleImportedTarget(const std::string &tgt);
virtual void HandleMissingTarget(const std::string &name); virtual void HandleMissingTarget(const std::string &name);
virtual void HandleDirectContent(cmTarget *tgt, virtual bool HandleDirectContent(cmTarget *tgt,
const std::vector<std::string> &content, const std::vector<std::string> &content,
bool prepend, bool system); bool prepend, bool system);
virtual void HandleInterfaceContent(cmTarget *tgt, virtual void HandleInterfaceContent(cmTarget *tgt,

View File

@ -132,29 +132,31 @@ bool cmTargetPropCommandBase
|| args[i] == "PRIVATE" || args[i] == "PRIVATE"
|| args[i] == "INTERFACE" ) || args[i] == "INTERFACE" )
{ {
this->PopulateTargetProperies(scope, content, prepend, system); return this->PopulateTargetProperies(scope, content, prepend, system);
return true;
} }
content.push_back(args[i]); content.push_back(args[i]);
} }
this->PopulateTargetProperies(scope, content, prepend, system); return this->PopulateTargetProperies(scope, content, prepend, system);
return true;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmTargetPropCommandBase bool cmTargetPropCommandBase
::PopulateTargetProperies(const std::string &scope, ::PopulateTargetProperies(const std::string &scope,
const std::vector<std::string> &content, const std::vector<std::string> &content,
bool prepend, bool system) bool prepend, bool system)
{ {
if (scope == "PRIVATE" || scope == "PUBLIC") if (scope == "PRIVATE" || scope == "PUBLIC")
{ {
this->HandleDirectContent(this->Target, content, prepend, system); if (!this->HandleDirectContent(this->Target, content, prepend, system))
{
return false;
}
} }
if (scope == "INTERFACE" || scope == "PUBLIC") if (scope == "INTERFACE" || scope == "PUBLIC")
{ {
this->HandleInterfaceContent(this->Target, content, prepend, system); this->HandleInterfaceContent(this->Target, content, prepend, system);
} }
return true;
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------

View File

@ -44,7 +44,7 @@ private:
virtual void HandleImportedTarget(const std::string &tgt) = 0; virtual void HandleImportedTarget(const std::string &tgt) = 0;
virtual void HandleMissingTarget(const std::string &name) = 0; virtual void HandleMissingTarget(const std::string &name) = 0;
virtual void HandleDirectContent(cmTarget *tgt, virtual bool HandleDirectContent(cmTarget *tgt,
const std::vector<std::string> &content, const std::vector<std::string> &content,
bool prepend, bool system) = 0; bool prepend, bool system) = 0;
@ -52,7 +52,7 @@ private:
bool ProcessContentArgs(std::vector<std::string> const& args, bool ProcessContentArgs(std::vector<std::string> const& args,
unsigned int &argIndex, bool prepend, bool system); unsigned int &argIndex, bool prepend, bool system);
void PopulateTargetProperies(const std::string &scope, bool PopulateTargetProperies(const std::string &scope,
const std::vector<std::string> &content, const std::vector<std::string> &content,
bool prepend, bool system); bool prepend, bool system);
}; };

View File

@ -56,9 +56,10 @@ std::string cmTargetSourcesCommand
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
void cmTargetSourcesCommand bool cmTargetSourcesCommand
::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content, ::HandleDirectContent(cmTarget *tgt, const std::vector<std::string> &content,
bool, bool) bool, bool)
{ {
tgt->AppendProperty("SOURCES", this->Join(content).c_str()); tgt->AppendProperty("SOURCES", this->Join(content).c_str());
return true;
} }

View File

@ -45,7 +45,7 @@ private:
virtual void HandleImportedTarget(const std::string &tgt); virtual void HandleImportedTarget(const std::string &tgt);
virtual void HandleMissingTarget(const std::string &name); virtual void HandleMissingTarget(const std::string &name);
virtual void HandleDirectContent(cmTarget *tgt, virtual bool HandleDirectContent(cmTarget *tgt,
const std::vector<std::string> &content, const std::vector<std::string> &content,
bool prepend, bool system); bool prepend, bool system);

View File

@ -0,0 +1,17 @@
cmake_minimum_required(VERSION 3.0)
project(target_compile_features)
set(CMAKE_VERBOSE_MAKEFILE ON)
add_executable(target_compile_features main.cpp)
target_compile_features(target_compile_features
PRIVATE cxx_auto_type
)
add_library(lib_auto_type lib_auto_type.cpp)
target_compile_features(lib_auto_type
PUBLIC cxx_auto_type
)
add_executable(lib_user lib_user.cpp)
target_link_libraries(lib_user lib_auto_type)

View File

@ -0,0 +1,5 @@
int main(int, char **)
{
return 0;
}

View File

@ -0,0 +1,6 @@
int getAutoTypeImpl()
{
auto i = 0;
return i;
}

View File

@ -0,0 +1,8 @@
int getAutoTypeImpl();
int getAutoType()
{
auto i = getAutoTypeImpl();
return i;
}

View File

@ -0,0 +1,7 @@
#include "lib_auto_type.h"
int main(int argc, char **argv)
{
return getAutoType();
}

View File

@ -0,0 +1,6 @@
int main(int, char **)
{
auto i = 0;
return i;
}

View File

@ -197,6 +197,11 @@ if(BUILD_TESTING)
ADD_TEST_MACRO(TarTest TarTest) ADD_TEST_MACRO(TarTest TarTest)
ADD_TEST_MACRO(SystemInformation SystemInformation) ADD_TEST_MACRO(SystemInformation SystemInformation)
ADD_TEST_MACRO(MathTest MathTest) ADD_TEST_MACRO(MathTest MathTest)
if(CMAKE_CXX_COMPILER_ID STREQUAL GNU
AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8)
ADD_TEST_MACRO(CompileFeatures CompileFeatures)
ADD_TEST_MACRO(CMakeCommands.target_compile_features target_compile_features)
endif()
# assume no resources building to test # assume no resources building to test
set(TEST_RESOURCES FALSE) set(TEST_RESOURCES FALSE)
# for windows and cygwin assume we have resources # for windows and cygwin assume we have resources
@ -283,6 +288,19 @@ if(BUILD_TESTING)
ADD_TEST_MACRO(ConfigSources ConfigSources) ADD_TEST_MACRO(ConfigSources ConfigSources)
endif() endif()
ADD_TEST_MACRO(SourcesProperty SourcesProperty) ADD_TEST_MACRO(SourcesProperty SourcesProperty)
if(CMAKE_CXX_COMPILER_ID STREQUAL GNU
AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.6)
set(runCxxDialectTest 1)
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL Clang
AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 2.9)
if(NOT APPLE OR POLICY CMP0025)
set(runCxxDialectTest 1)
endif()
endif()
if(runCxxDialectTest)
ADD_TEST_MACRO(CxxDialect CxxDialect)
endif()
set_tests_properties(EmptyLibrary PROPERTIES set_tests_properties(EmptyLibrary PROPERTIES
PASS_REGULAR_EXPRESSION "CMake Error: CMake can not determine linker language for target: test") PASS_REGULAR_EXPRESSION "CMake Error: CMake can not determine linker language for target: test")
ADD_TEST_MACRO(CrossCompile CrossCompile) ADD_TEST_MACRO(CrossCompile CrossCompile)

View File

@ -0,0 +1,36 @@
cmake_minimum_required(VERSION 3.0)
project(CompileFeatures)
macro(run_test feature)
if (";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ${feature})
add_library(test_${feature} OBJECT ${feature}.cpp)
set_property(TARGET test_${feature}
PROPERTY COMPILE_FEATURES "${feature}"
)
else()
message("Not supported: ${feature}")
endif()
endmacro()
foreach(feature ${CMAKE_CXX_KNOWN_FEATURES})
run_test(${feature})
endforeach()
add_executable(CompileFeatures main.cpp)
set_property(TARGET CompileFeatures
PROPERTY COMPILE_FEATURES "cxx_auto_type"
)
add_executable(GenexCompileFeatures main.cpp)
set_property(TARGET GenexCompileFeatures
PROPERTY COMPILE_FEATURES "$<1:cxx_auto_type>;$<0:not_a_feature>"
)
add_library(iface INTERFACE)
set_property(TARGET iface
PROPERTY INTERFACE_COMPILE_FEATURES "cxx_auto_type"
)
add_executable(IfaceCompileFeatures main.cpp)
target_link_libraries(IfaceCompileFeatures iface)

View File

@ -0,0 +1,5 @@
void someFunc()
{
auto x = 3.14;
}

View File

@ -0,0 +1,6 @@
int main(int,char**)
{
auto value = 0;
return value;
}

View File

@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 2.8.12)
cmake_policy(SET CMP0025 NEW)
project(CxxDialect)
add_executable(use_typeof use_typeof.cxx)
set_property(TARGET use_typeof PROPERTY CXX_STANDARD 98)
set_property(TARGET use_typeof PROPERTY CXX_EXTENSIONS ON)
add_executable(use_constexpr use_constexpr.cxx)
set_property(TARGET use_constexpr PROPERTY CXX_STANDARD 11)
add_executable(CxxDialect use_constexpr_and_typeof.cxx)
set_property(TARGET CxxDialect PROPERTY CXX_STANDARD 11)
set_property(TARGET CxxDialect PROPERTY CXX_EXTENSIONS ON)

View File

@ -0,0 +1,10 @@
constexpr int foo()
{
return 0;
}
int main(int argc, char**)
{
return foo();
}

View File

@ -0,0 +1,11 @@
constexpr int foo()
{
return 0;
}
int main(int argc, char**)
{
typeof(argc) ret = foo();
return ret;
}

View File

@ -0,0 +1,6 @@
int main(int argc, char**)
{
typeof(argc) ret = 0;
return ret;
}

View File

@ -23,7 +23,10 @@ set_property(TARGET sharedlib PROPERTY INTERFACE_COMPILE_DEFINITIONS "SHAREDLIB_
add_library(sharediface INTERFACE) add_library(sharediface INTERFACE)
target_link_libraries(sharediface INTERFACE sharedlib) target_link_libraries(sharediface INTERFACE sharedlib)
install(TARGETS headeronly sharediface add_library(use_auto_type INTERFACE)
target_compile_features(use_auto_type INTERFACE cxx_auto_type)
install(TARGETS headeronly sharediface use_auto_type
EXPORT expInterface EXPORT expInterface
) )
install(TARGETS sharedlib install(TARGETS sharedlib

View File

@ -1,4 +1,5 @@
cmake_minimum_required (VERSION 2.7.20090711) cmake_minimum_required (VERSION 2.7.20090711)
cmake_policy(SET CMP0025 NEW)
project(Import C CXX) project(Import C CXX)
# Import everything in a subdirectory. # Import everything in a subdirectory.

View File

@ -40,6 +40,23 @@ macro(do_try_compile prefix)
if(NOT ${prefix}IFACE_TRY_COMPILE) if(NOT ${prefix}IFACE_TRY_COMPILE)
message(SEND_ERROR "${prefix} try_compile with IMPORTED INTERFACE target failed!\n\n${OUTPUT}") message(SEND_ERROR "${prefix} try_compile with IMPORTED INTERFACE target failed!\n\n${OUTPUT}")
endif() endif()
if (";${CMAKE_CXX_COMPILE_FEATURES};" MATCHES ";cxx_auto_type;")
set(CMAKE_REQUIRED_LIBRARIES ${prefix}::use_auto_type)
check_cxx_source_compiles(
"
int main(int,char**)
{
auto value = 0;
return value;
}
" ${prefix}IMPORTED_IFACE_CONSTEXPR)
if(NOT ${prefix}IMPORTED_IFACE_CONSTEXPR)
message(SEND_ERROR "${prefix} try_compile with IMPORTED INTERFACE target failed!\n\n${OUTPUT}")
endif()
endif()
endmacro() endmacro()
do_try_compile(bld) do_try_compile(bld)

View File

@ -53,6 +53,7 @@ add_RunCMake_test(ObjectLibrary)
add_RunCMake_test(TargetObjects) add_RunCMake_test(TargetObjects)
add_RunCMake_test(TargetSources) add_RunCMake_test(TargetSources)
add_RunCMake_test(find_dependency) add_RunCMake_test(find_dependency)
add_RunCMake_test(CompileFeatures)
if(NOT WIN32) if(NOT WIN32)
add_RunCMake_test(PositionIndependentCode) add_RunCMake_test(PositionIndependentCode)
set(SKIP_VISIBILITY 0) set(SKIP_VISIBILITY 0)
@ -124,6 +125,10 @@ endif()
add_RunCMake_test(File_Generate) add_RunCMake_test(File_Generate)
add_RunCMake_test(ExportWithoutLanguage) add_RunCMake_test(ExportWithoutLanguage)
add_RunCMake_test(target_link_libraries) add_RunCMake_test(target_link_libraries)
if (CMAKE_CXX_COMPILER_ID STREQUAL GNU AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.8)
add_RunCMake_test(target_compile_features)
endif()
add_RunCMake_test(CheckModules) add_RunCMake_test(CheckModules)
add_RunCMake_test(CommandLine) add_RunCMake_test(CommandLine)

View File

@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 3.0)
project(${RunCMake_TEST} CXX)
include(${RunCMake_TEST}.cmake)

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,2 @@
CMake Error in CMakeLists.txt:
Specified unknown feature "not_a_feature" for target "somelib".

View File

@ -0,0 +1,3 @@
add_library(somelib STATIC empty.cpp)
set_property(TARGET somelib PROPERTY COMPILE_FEATURES "not_a_feature")

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,2 @@
CMake Error in CMakeLists.txt:
Specified unknown feature "not_a_feature" for target "somelib".

View File

@ -0,0 +1,3 @@
add_library(somelib STATIC empty.cpp)
set_property(TARGET somelib PROPERTY COMPILE_FEATURES "$<1:not_a_feature>")

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,2 @@
CMake Error in CMakeLists.txt:
Specified unknown feature "not_a_feature" for target "somelib".

View File

@ -0,0 +1,6 @@
add_library(iface INTERFACE)
set_property(TARGET iface PROPERTY INTERFACE_COMPILE_FEATURES "not_a_feature")
add_library(somelib STATIC empty.cpp)
target_link_libraries(somelib iface)

View File

@ -0,0 +1,11 @@
CMake Debug Log at NotAFeature_OriginDebug.cmake:4 \(set_property\):
Used compile features for target somelib:
\* not_a_feature
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
CMake Error in CMakeLists.txt:
Specified unknown feature "not_a_feature" for target "somelib".

View File

@ -0,0 +1,4 @@
set(CMAKE_DEBUG_TARGET_PROPERTIES COMPILE_FEATURES)
add_library(somelib STATIC empty.cpp)
set_property(TARGET somelib PROPERTY COMPILE_FEATURES "not_a_feature")

View File

@ -0,0 +1,11 @@
CMake Debug Log at NotAFeature_OriginDebugGenex.cmake:4 \(set_property\):
Used compile features for target somelib:
\* not_a_feature
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
CMake Error in CMakeLists.txt:
Specified unknown feature "not_a_feature" for target "somelib".

View File

@ -0,0 +1,4 @@
set(CMAKE_DEBUG_TARGET_PROPERTIES COMPILE_FEATURES)
add_library(somelib STATIC empty.cpp)
set_property(TARGET somelib PROPERTY COMPILE_FEATURES "$<1:not_a_feature>")

View File

@ -0,0 +1,11 @@
CMake Debug Log at NotAFeature_OriginDebugTransitive.cmake:6 \(target_link_libraries\):
Used compile features for target somelib:
\* not_a_feature
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)
CMake Error in CMakeLists.txt:
Specified unknown feature "not_a_feature" for target "somelib".

View File

@ -0,0 +1,6 @@
set(CMAKE_DEBUG_TARGET_PROPERTIES COMPILE_FEATURES)
add_library(iface INTERFACE)
set_property(TARGET iface PROPERTY INTERFACE_COMPILE_FEATURES "not_a_feature")
add_library(somelib STATIC empty.cpp)
target_link_libraries(somelib iface)

View File

@ -0,0 +1,5 @@
CMake Error at NotAFeature_OriginDebug_target_compile_features.cmake:4 \(target_compile_features\):
target_compile_features specified unknown feature "not_a_feature" for
target "somelib".
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)

View File

@ -0,0 +1,4 @@
set(CMAKE_DEBUG_TARGET_PROPERTIES COMPILE_FEATURES)
add_library(somelib STATIC empty.cpp)
target_compile_features(somelib PRIVATE not_a_feature)

View File

@ -0,0 +1,9 @@
include(RunCMake)
run_cmake(NotAFeature)
run_cmake(NotAFeatureGenex)
run_cmake(NotAFeatureTransitive)
run_cmake(NotAFeature_OriginDebug)
run_cmake(NotAFeature_OriginDebugGenex)
run_cmake(NotAFeature_OriginDebugTransitive)
run_cmake(NotAFeature_OriginDebug_target_compile_features)

View File

@ -0,0 +1,7 @@
#ifdef _WIN32
__declspec(dllexport)
#endif
int empty()
{
return 0;
}

View File

@ -0,0 +1,3 @@
cmake_minimum_required(VERSION 3.0)
project(${RunCMake_TEST} CXX)
include(${RunCMake_TEST}.cmake)

View File

@ -0,0 +1,11 @@
include(RunCMake)
run_cmake(not_enough_args)
run_cmake(alias_target)
run_cmake(utility_target)
run_cmake(invalid_args)
run_cmake(invalid_args_on_interface)
run_cmake(imported_target)
run_cmake(no_target)
run_cmake(not_a_cxx_feature)
run_cmake(no_matching_cxx_feature)

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,4 @@
CMake Error at alias_target.cmake:4 \(target_compile_features\):
target_compile_features can not be used on an ALIAS target.
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)

View File

@ -0,0 +1,4 @@
add_executable(main empty.cpp)
add_executable(Alias::Main ALIAS main)
target_compile_features(Alias::Main PRIVATE cxx_delegating_constructors)

View File

@ -0,0 +1,7 @@
#ifdef _WIN32
__declspec(dllexport)
#endif
int empty()
{
return 0;
}

View File

@ -0,0 +1,4 @@
CMake Error at imported_target.cmake:3 \(target_compile_features\):
Cannot specify compile features for imported target "main".
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)

View File

@ -0,0 +1,3 @@
add_library(main INTERFACE IMPORTED)
target_compile_features(main INTERFACE cxx_delegating_constructors)

View File

@ -0,0 +1 @@
1

View File

@ -0,0 +1,4 @@
CMake Error at invalid_args.cmake:3 \(target_compile_features\):
target_compile_features called with invalid arguments
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)

View File

@ -0,0 +1,3 @@
add_executable(main empty.cpp)
target_compile_features(main INVALID cxx_delegating_constructors)

View File

@ -0,0 +1,5 @@
CMake Error at invalid_args_on_interface.cmake:3 \(target_compile_features\):
target_compile_features may only be set INTERFACE properties on INTERFACE
targets
Call Stack \(most recent call first\):
CMakeLists.txt:3 \(include\)

Some files were not shown because too many files have changed in this diff Show More