[Cmake-commits] CMake branch, next, updated. v2.8.12-4417-g16e8226
Stephen Kelly
steveire at gmail.com
Thu Oct 24 02:58:51 EDT 2013
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "CMake".
The branch, next has been updated
via 16e8226d78bf4a270b8bf06b365e5da5cf582e44 (commit)
via 8b9875e048cdb80d3e849785726d9f7f1eaaccf1 (commit)
via eeee85bf9d76366c25bd55ed25c18f3210602a7b (commit)
from 91f1b17e360a7d23ae701b4b8834aa8e0f73038e (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=16e8226d78bf4a270b8bf06b365e5da5cf582e44
commit 16e8226d78bf4a270b8bf06b365e5da5cf582e44
Merge: 91f1b17 8b9875e
Author: Stephen Kelly <steveire at gmail.com>
AuthorDate: Thu Oct 24 02:58:48 2013 -0400
Commit: CMake Topic Stage <kwrobot at kitware.com>
CommitDate: Thu Oct 24 02:58:48 2013 -0400
Merge topic 'target_compiler_features' into next
8b9875e Add the WriteCompilerDetectionHeader module.
eeee85b Transitively evaluate compiler features.
http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=8b9875e048cdb80d3e849785726d9f7f1eaaccf1
commit 8b9875e048cdb80d3e849785726d9f7f1eaaccf1
Author: Stephen Kelly <steveire at gmail.com>
AuthorDate: Mon Oct 21 16:59:40 2013 +0200
Commit: Stephen Kelly <steveire at gmail.com>
CommitDate: Thu Oct 24 08:58:22 2013 +0200
Add the WriteCompilerDetectionHeader module.
Provide a function to write a portable header to detect compiler
features.
diff --git a/Modules/Compiler/Clang-features.cmake b/Modules/Compiler/Clang-features.cmake
index 074e5a1..012502d 100644
--- a/Modules/Compiler/Clang-features.cmake
+++ b/Modules/Compiler/Clang-features.cmake
@@ -1,4 +1,6 @@
+set(compiler_test_macro __clang__)
+
set(testable_features
cxx_delegating_constructors
)
diff --git a/Modules/Compiler/GNU-features.cmake b/Modules/Compiler/GNU-features.cmake
index bb63250..169a6a9 100644
--- a/Modules/Compiler/GNU-features.cmake
+++ b/Modules/Compiler/GNU-features.cmake
@@ -1,2 +1,4 @@
+set(compiler_test_macro __GNUC__)
+
set(feature_test_cxx_delegating_constructors "(__GNUC__ * 100 + __GNUC_MINOR__) >= 407")
diff --git a/Modules/Compiler/Intel-features.cmake b/Modules/Compiler/Intel-features.cmake
index 07676a0..b074912 100644
--- a/Modules/Compiler/Intel-features.cmake
+++ b/Modules/Compiler/Intel-features.cmake
@@ -1,2 +1,4 @@
+set(compiler_test_macro __INTEL_COMPILER)
+
set(feature_test_cxx_delegating_constructors "__INTEL_COMPILER >= 1400")
diff --git a/Modules/Compiler/XL-features.cmake b/Modules/Compiler/XL-features.cmake
index 64dcb2c..cfbaa3c 100644
--- a/Modules/Compiler/XL-features.cmake
+++ b/Modules/Compiler/XL-features.cmake
@@ -1,2 +1,4 @@
+set(compiler_test_macro __IBMCPP__)
+
set(feature_test_cxx_delegating_constructors "__IBMCPP__ >= 1110")
diff --git a/Modules/WriteCompilerDetectionHeader.cmake b/Modules/WriteCompilerDetectionHeader.cmake
new file mode 100644
index 0000000..4fadbb1
--- /dev/null
+++ b/Modules/WriteCompilerDetectionHeader.cmake
@@ -0,0 +1,89 @@
+
+#=============================================================================
+# Copyright 2013 Stephen Kelly <steveire at 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.)
+
+include(${CMAKE_CURRENT_LIST_DIR}/CMakeParseArguments.cmake)
+
+function(_load_compiler_variables CompilerId)
+ include("${CMAKE_ROOT}/Modules/Compiler/${CompilerId}-features.cmake" OPTIONAL)
+ if (NOT compiler_test_macro)
+ message(FATAL_ERROR "Compiler ${CompilerId} does not define compiler_test_macro")
+ endif()
+ foreach(feature ${ARGN})
+ set(x ${feature_tests_${feature}})
+ if (feature_test_${feature})
+ list(APPEND x "(defined (${compiler_test_macro}) && ${feature_test_${feature}})")
+ set(feature_tests_${feature} ${x} PARENT_SCOPE)
+ endif()
+ endforeach()
+endfunction()
+
+function(write_compiler_detection_header
+ file_keyword file_arg
+ prefix_keyword prefix_arg
+ )
+ if (NOT file_keyword STREQUAL FILE)
+ message(FATAL_ERROR "Wrong parameters for function.")
+ endif()
+ if (NOT prefix_keyword STREQUAL PREFIX)
+ message(FATAL_ERROR "Wrong parameters for function.")
+ endif()
+ set(options)
+ set(oneValueArgs VERSION)
+ set(multiValueArgs COMPILERS FEATURES)
+ cmake_parse_arguments(_WCD "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
+
+ if(_WCD_UNPARSED_ARGUMENTS)
+ message(FATAL_ERROR "Unparsed arguments: ${_WCD_UNPARSED_ARGUMENTS}")
+ endif()
+
+ if(NOT _WCD_VERSION)
+ set(_WCD_VERSION ${CMAKE_MINIMUM_REQUIRED_VERSION})
+ endif()
+# if (_WCD_VERSION VERSION_LESS 3.0.0) # Version which introduced this function
+# if (_WCD_VERSION VERSION_LESS 2.8.12.20131023)
+# message(FATAL_ERROR "VERSION parameter too low.")
+# endif()
+
+ file(WRITE ${file_arg} "
+// This is a generated file. Do not edit!
+
+#ifndef ${prefix_arg}_COMPILER_DETECTION_H
+#define ${prefix_arg}_COMPILER_DETECTION_H
+")
+
+ foreach(ordered_compiler
+ # Order is relevant here. We need to list the compilers which pretend to
+ # be GNU/MSVC before the actual GNU/MSVC compiler.
+ XL
+ Intel
+ Clang
+ GNU
+ )
+ list(FIND _WCD_COMPILERS ${ordered_compiler} idx)
+ if (NOT idx EQUAL -1)
+ _load_compiler_variables(${ordered_compiler} ${_WCD_FEATURES})
+ endif()
+ endforeach()
+
+ foreach(feature ${_WCD_FEATURES})
+ set(_define_check "\n#define ${prefix_arg}_${CMAKE_PP_NAME_${feature}} 0\n")
+ if (feature_tests_${feature})
+ string(REPLACE ";" " \\\n || " feature_tests_${feature} "${feature_tests_${feature}}")
+ set(_define_check "\n#if ${feature_tests_${feature}}\n#define ${prefix_arg}_${CMAKE_PP_NAME_${feature}} 1\n#else${_define_check}#endif\n")
+ endif()
+ file(APPEND "${file_arg}" "${_define_check}")
+ endforeach()
+
+ file(APPEND ${file_arg} "\n#endif\n")
+endfunction()
http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=eeee85bf9d76366c25bd55ed25c18f3210602a7b
commit eeee85bf9d76366c25bd55ed25c18f3210602a7b
Author: Stephen Kelly <steveire at gmail.com>
AuthorDate: Tue Oct 22 01:40:47 2013 +0200
Commit: Stephen Kelly <steveire at gmail.com>
CommitDate: Thu Oct 24 08:58:21 2013 +0200
Transitively evaluate compiler features.
Extend the interface of the target_compiler_features command with
PUBLIC and INTERFACE keywords. Populate the INTERFACE_COMPILER_FEATURES
target property if they are set. Consume the INTERFACE_COMPILER_FEATURES
target property from linked dependent targets to determine the final
required compiler features and the compile flag, if needed.
diff --git a/Help/command/target_compiler_features.rst b/Help/command/target_compiler_features.rst
index 1b37112..ade0310 100644
--- a/Help/command/target_compiler_features.rst
+++ b/Help/command/target_compiler_features.rst
@@ -5,7 +5,7 @@ Add expected compiler features to a target.
::
- target_compiler_features(<target> PRIVATE <feature> [...])
+ target_compiler_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_COMPILER_FEATURES` variable,
@@ -13,6 +13,12 @@ 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:`COMPILER_FEATURES` property of <target>. PUBLIC and
+INTERFACE items will populate the :prop_tgt:`INTERFACE_COMPILER_FEATURES` property
+of <target>. Repeated calls for the same <target> append items in the order called.
+
The named <target> must have been created by a command such as
add_executable or add_library and must not be an IMPORTED target.
diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx
index 92dc054..d139092 100644
--- a/Source/cmGeneratorExpressionDAGChecker.cxx
+++ b/Source/cmGeneratorExpressionDAGChecker.cxx
@@ -210,3 +210,11 @@ bool cmGeneratorExpressionDAGChecker::EvaluatingCompileOptions() const
return (strcmp(prop, "COMPILE_OPTIONS") == 0
|| strcmp(prop, "INTERFACE_COMPILE_OPTIONS") == 0 );
}
+
+//----------------------------------------------------------------------------
+bool cmGeneratorExpressionDAGChecker::EvaluatingCompilerFeatures() const
+{
+ const char *prop = this->Property.c_str();
+ return (strcmp(prop, "COMPILER_FEATURES") == 0
+ || strcmp(prop, "INTERFACE_COMPILER_FEATURES") == 0);
+}
diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h
index 0b7ef02..3f75a45 100644
--- a/Source/cmGeneratorExpressionDAGChecker.h
+++ b/Source/cmGeneratorExpressionDAGChecker.h
@@ -20,13 +20,15 @@
F(EvaluatingIncludeDirectories) \
F(EvaluatingSystemIncludeDirectories) \
F(EvaluatingCompileDefinitions) \
- F(EvaluatingCompileOptions)
+ F(EvaluatingCompileOptions) \
+ F(EvaluatingCompilerFeatures)
#define CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(F) \
F(INTERFACE_INCLUDE_DIRECTORIES) \
F(INTERFACE_SYSTEM_INCLUDE_DIRECTORIES) \
F(INTERFACE_COMPILE_DEFINITIONS) \
- F(INTERFACE_COMPILE_OPTIONS)
+ F(INTERFACE_COMPILE_OPTIONS) \
+ F(INTERFACE_COMPILER_FEATURES)
//----------------------------------------------------------------------------
struct cmGeneratorExpressionDAGChecker
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index 33863f4..ec8e9b7 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -913,6 +913,11 @@ static const struct TargetPropertyNode : public cmGeneratorExpressionNode
{
interfacePropertyName = "INTERFACE_COMPILE_OPTIONS";
}
+ else if (propertyName == "INTERFACE_COMPILER_FEATURES"
+ || propertyName == "COMPILER_FEATURES")
+ {
+ interfacePropertyName = "INTERFACE_COMPILER_FEATURES";
+ }
cmTarget *headTarget = context->HeadTarget ? context->HeadTarget : target;
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 3b5e222..a11c5f8 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -140,6 +140,7 @@ public:
};
std::vector<TargetPropertyEntry*> IncludeDirectoriesEntries;
std::vector<TargetPropertyEntry*> CompileOptionsEntries;
+ std::vector<TargetPropertyEntry*> CompilerFeaturesEntries;
std::vector<TargetPropertyEntry*> CompileDefinitionsEntries;
std::vector<cmValueWithOrigin> LinkInterfacePropertyEntries;
@@ -148,11 +149,14 @@ public:
std::map<std::string, std::vector<TargetPropertyEntry*> >
CachedLinkInterfaceCompileOptionsEntries;
std::map<std::string, std::vector<TargetPropertyEntry*> >
+ CachedLinkInterfaceCompilerFeaturesEntries;
+ std::map<std::string, std::vector<TargetPropertyEntry*> >
CachedLinkInterfaceCompileDefinitionsEntries;
std::map<std::string, bool> CacheLinkInterfaceIncludeDirectoriesDone;
std::map<std::string, bool> CacheLinkInterfaceCompileDefinitionsDone;
std::map<std::string, bool> CacheLinkInterfaceCompileOptionsDone;
+ std::map<std::string, bool> CacheLinkInterfaceCompilerFeaturesDone;
};
//----------------------------------------------------------------------------
@@ -210,6 +214,7 @@ cmTarget::cmTarget()
this->BuildInterfaceIncludesAppended = false;
this->DebugIncludesDone = false;
this->DebugCompileOptionsDone = false;
+ this->DebugCompilerFeaturesDone = false;
this->DebugCompileDefinitionsDone = false;
}
@@ -2533,6 +2538,121 @@ void cmTarget::GetCompileDefinitions(std::vector<std::string> &list,
}
//----------------------------------------------------------------------------
+static void processCompilerFeatures(cmTarget *tgt,
+ const std::vector<cmTargetInternals::TargetPropertyEntry*> &entries,
+ std::vector<std::string> &options,
+ std::set<std::string> &uniqueOptions,
+ cmGeneratorExpressionDAGChecker *dagChecker,
+ const char *config, bool debugOptions)
+{
+ processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
+ dagChecker, config, debugOptions, "features");
+}
+
+//----------------------------------------------------------------------------
+void cmTarget::GetCompilerFeatures(std::vector<std::string> &result,
+ const char *config)
+{
+ std::set<std::string> uniqueFeatures;
+ cmListFileBacktrace lfbt;
+
+ cmGeneratorExpressionDAGChecker dagChecker(lfbt,
+ this->GetName(),
+ "COMPILER_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->DebugCompilerFeaturesDone
+ && std::find(debugProperties.begin(),
+ debugProperties.end(),
+ "COMPILER_FEATURES")
+ != debugProperties.end();
+
+ if (this->Makefile->IsGeneratingBuildSystem())
+ {
+ this->DebugCompilerFeaturesDone = true;
+ }
+
+ processCompilerFeatures(this,
+ this->Internal->CompilerFeaturesEntries,
+ result,
+ uniqueFeatures,
+ &dagChecker,
+ config,
+ debugFeatures);
+
+ std::string configString = config ? config : "";
+ if (!this->Internal->CacheLinkInterfaceCompilerFeaturesDone[configString])
+ {
+
+ for (std::vector<cmValueWithOrigin>::const_iterator
+ it = this->Internal->LinkInterfacePropertyEntries.begin(),
+ end = this->Internal->LinkInterfacePropertyEntries.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.c_str()))
+ {
+ continue;
+ }
+ }
+ std::string featureGenex = "$<TARGET_PROPERTY:" +
+ it->Value + ",INTERFACE_COMPILER_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
+ ->CachedLinkInterfaceCompilerFeaturesEntries[configString].push_back(
+ new cmTargetInternals::TargetPropertyEntry(cge,
+ it->Value));
+ }
+ }
+
+ processCompilerFeatures(this,
+ this->Internal->CachedLinkInterfaceCompilerFeaturesEntries[configString],
+ result,
+ uniqueFeatures,
+ &dagChecker,
+ config,
+ debugFeatures);
+
+ if (!this->Makefile->IsGeneratingBuildSystem())
+ {
+ deleteAndClear(this->Internal->CachedLinkInterfaceCompilerFeaturesEntries);
+ }
+ else
+ {
+ this->Internal->CacheLinkInterfaceCompilerFeaturesDone[configString]
+ = true;
+ }
+}
+
+//----------------------------------------------------------------------------
void cmTarget::MaybeInvalidatePropertyCache(const char* prop)
{
// Wipe out maps caching information affected by this property.
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index e8f4e08..a58f8e3 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -530,6 +530,8 @@ public:
void GetCompileOptions(std::vector<std::string> &result,
const char *config);
+ void GetCompilerFeatures(std::vector<std::string> &result,
+ const char *config);
bool IsNullImpliedByLinkLibraries(const std::string &p);
bool IsLinkInterfaceDependentBoolProperty(const std::string &p,
@@ -680,6 +682,7 @@ private:
bool IsImportedTarget;
bool DebugIncludesDone;
bool DebugCompileOptionsDone;
+ bool DebugCompilerFeaturesDone;
bool DebugCompileDefinitionsDone;
mutable std::set<std::string> LinkImplicitNullProperties;
bool BuildInterfaceIncludesAppended;
diff --git a/Source/cmTargetCompilerFeaturesCommand.cxx b/Source/cmTargetCompilerFeaturesCommand.cxx
index eb9d0e3..7a77aac 100644
--- a/Source/cmTargetCompilerFeaturesCommand.cxx
+++ b/Source/cmTargetCompilerFeaturesCommand.cxx
@@ -34,7 +34,8 @@ bool cmTargetCompilerFeaturesCommand::InitialPass(
return false;
}
- if(args[1] != "PRIVATE")
+ const bool interfaceOnly = args[1] == "INTERFACE";
+ if(args[1] != "PRIVATE" && args[1] != "PUBLIC" && !interfaceOnly)
{
this->SetError("called with invalid arguments.");
return false;
@@ -44,13 +45,20 @@ bool cmTargetCompilerFeaturesCommand::InitialPass(
{
std::string feature = args[i];
- bool result = this->Makefile->AddRequiredTargetFeature(target,
- feature.c_str());
+ if (!interfaceOnly)
+ {
+ bool result = this->Makefile->AddRequiredTargetFeature(target,
+ feature.c_str());
- if (!result)
+ if (!result)
+ {
+ this->SetError("specified unknown feature.");
+ return false;
+ }
+ }
+ if (interfaceOnly || args[1] == "PUBLIC")
{
- this->SetError("specified unknown feature.");
- return false;
+ target->AppendProperty("INTERFACE_COMPILER_FEATURES", feature.c_str());
}
}
return true;
diff --git a/Tests/CMakeCommands/target_compiler_features/CMakeLists.txt b/Tests/CMakeCommands/target_compiler_features/CMakeLists.txt
index 4a7cb5f..d643107 100644
--- a/Tests/CMakeCommands/target_compiler_features/CMakeLists.txt
+++ b/Tests/CMakeCommands/target_compiler_features/CMakeLists.txt
@@ -11,3 +11,11 @@ add_executable(target_compiler_features main.cpp)
target_compiler_features(target_compiler_features
PRIVATE cxx_delegating_constructors
)
+
+add_library(lib_delegating_constructors lib_delegating_constructors.cpp)
+target_compiler_features(lib_delegating_constructors
+ PUBLIC cxx_delegating_constructors
+)
+
+add_executable(lib_user lib_user.cpp)
+target_link_libraries(lib_user lib_delegating_constructors)
diff --git a/Tests/CMakeCommands/target_compiler_features/lib_delegating_constructors.cpp b/Tests/CMakeCommands/target_compiler_features/lib_delegating_constructors.cpp
new file mode 100644
index 0000000..e597acd
--- /dev/null
+++ b/Tests/CMakeCommands/target_compiler_features/lib_delegating_constructors.cpp
@@ -0,0 +1,8 @@
+
+#include "lib_delegating_constructors.h"
+
+Foo::Foo(int i)
+ : m_i(i)
+{
+
+}
diff --git a/Tests/CMakeCommands/target_compiler_features/lib_delegating_constructors.h b/Tests/CMakeCommands/target_compiler_features/lib_delegating_constructors.h
new file mode 100644
index 0000000..75be701
--- /dev/null
+++ b/Tests/CMakeCommands/target_compiler_features/lib_delegating_constructors.h
@@ -0,0 +1,17 @@
+
+#include <cstring>
+
+class Foo
+{
+public:
+ Foo(int i);
+
+ Foo(const char *a)
+ : Foo(strlen(a))
+ {
+
+ }
+
+private:
+ int m_i;
+};
diff --git a/Tests/CMakeCommands/target_compiler_features/lib_user.cpp b/Tests/CMakeCommands/target_compiler_features/lib_user.cpp
new file mode 100644
index 0000000..83ad51e
--- /dev/null
+++ b/Tests/CMakeCommands/target_compiler_features/lib_user.cpp
@@ -0,0 +1,27 @@
+
+#include "lib_delegating_constructors.h"
+
+class Bar
+{
+ Bar(int i)
+ :m_i(i)
+ {
+
+ }
+
+ Bar(const char *a)
+ : Bar(strlen(a))
+ {
+
+ }
+
+private:
+ int m_i;
+};
+
+int main(int argc, char **argv)
+{
+ Foo f("hello");
+ Foo b("world");
+ return 0;
+}
-----------------------------------------------------------------------
Summary of changes:
hooks/post-receive
--
CMake
More information about the Cmake-commits
mailing list