summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLists.txt4
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/CPack/WiX/cmCPackWIXGenerator.cxx20
-rw-r--r--Source/CTest/cmCTestBuildHandler.cxx1
-rw-r--r--Source/CTest/cmCTestRunTest.cxx15
-rw-r--r--Source/CTest/cmParseJacocoCoverage.cxx5
-rw-r--r--Source/CursesDialog/cmCursesMainForm.cxx1
-rw-r--r--Source/cmAlgorithms.h50
-rw-r--r--Source/cmCTest.cxx1
-rw-r--r--Source/cmComputeLinkDepends.cxx1
-rw-r--r--Source/cmComputeLinkInformation.cxx1
-rw-r--r--Source/cmConfigureFileCommand.cxx7
-rw-r--r--Source/cmCoreTryCompile.cxx1
-rw-r--r--Source/cmDependsC.cxx1
-rw-r--r--Source/cmDocumentation.cxx1
-rw-r--r--Source/cmExportFileGenerator.cxx1
-rw-r--r--Source/cmExportInstallFileGenerator.cxx1
-rw-r--r--Source/cmExtraCodeBlocksGenerator.cxx73
-rw-r--r--Source/cmExtraCodeBlocksGenerator.h4
-rw-r--r--Source/cmExtraSublimeTextGenerator.cxx2
-rw-r--r--Source/cmFileCommand.cxx63
-rw-r--r--Source/cmFindBase.cxx2
-rw-r--r--Source/cmFindPackageCommand.cxx1
-rw-r--r--Source/cmGeneratorExpression.cxx36
-rw-r--r--Source/cmGeneratorExpression.h10
-rw-r--r--Source/cmGeneratorExpressionContext.cxx34
-rw-r--r--Source/cmGeneratorExpressionContext.h54
-rw-r--r--Source/cmGeneratorExpressionDAGChecker.cxx1
-rw-r--r--Source/cmGeneratorExpressionEvaluationFile.cxx51
-rw-r--r--Source/cmGeneratorExpressionEvaluationFile.h2
-rw-r--r--Source/cmGeneratorExpressionEvaluator.cxx1821
-rw-r--r--Source/cmGeneratorExpressionEvaluator.h28
-rw-r--r--Source/cmGeneratorExpressionNode.cxx1870
-rw-r--r--Source/cmGeneratorExpressionNode.h70
-rw-r--r--Source/cmGeneratorTarget.cxx6
-rw-r--r--Source/cmGeneratorTarget.h2
-rw-r--r--Source/cmGetCMakePropertyCommand.cxx1
-rw-r--r--Source/cmGlobalBorlandMakefileGenerator.cxx1
-rw-r--r--Source/cmGlobalGenerator.cxx18
-rw-r--r--Source/cmGlobalNinjaGenerator.cxx2
-rw-r--r--Source/cmGlobalUnixMakefileGenerator3.cxx3
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx1
-rw-r--r--Source/cmGlobalVisualStudio11Generator.cxx1
-rw-r--r--Source/cmGlobalVisualStudio12Generator.cxx1
-rw-r--r--Source/cmGlobalVisualStudio14Generator.cxx1
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx2
-rw-r--r--Source/cmInstalledFile.cxx11
-rw-r--r--Source/cmInstalledFile.h12
-rw-r--r--Source/cmListCommand.cxx1
-rw-r--r--Source/cmLocalGenerator.cxx13
-rw-r--r--Source/cmLocalGenerator.h5
-rw-r--r--Source/cmLocalNinjaGenerator.cxx3
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.cxx107
-rw-r--r--Source/cmLocalUnixMakefileGenerator3.h11
-rw-r--r--Source/cmLocalVisualStudio6Generator.cxx145
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx9
-rw-r--r--Source/cmMacroCommand.cxx1
-rw-r--r--Source/cmMakeDepend.cxx1
-rw-r--r--Source/cmMakefile.cxx28
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx5
-rw-r--r--Source/cmMakefileTargetGenerator.cxx115
-rw-r--r--Source/cmMakefileTargetGenerator.h10
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx1
-rw-r--r--Source/cmNinjaTargetGenerator.cxx2
-rw-r--r--Source/cmOrderDirectories.cxx1
-rw-r--r--Source/cmOutputRequiredFilesCommand.cxx1
-rw-r--r--Source/cmPolicies.cxx6
-rw-r--r--Source/cmPolicies.h2
-rw-r--r--Source/cmQtAutoGenerators.cxx3
-rw-r--r--Source/cmSearchPath.cxx1
-rw-r--r--Source/cmSourceFileLocation.cxx1
-rw-r--r--Source/cmTarget.cxx53
-rw-r--r--Source/cmTarget.h9
-rw-r--r--Source/cmTargetCompileDefinitionsCommand.cxx2
-rw-r--r--Source/cmTargetCompileFeaturesCommand.cxx2
-rw-r--r--Source/cmTargetCompileOptionsCommand.cxx2
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx3
-rw-r--r--Source/cmake.cxx1
-rw-r--r--Source/cmakemain.cxx1
-rw-r--r--Source/cmcmd.cxx1
-rw-r--r--Source/kwsys/Glob.cxx93
-rw-r--r--Source/kwsys/Glob.hxx.in47
-rw-r--r--Source/kwsys/SystemInformation.cxx8
-rw-r--r--Source/kwsys/SystemTools.cxx4
-rw-r--r--Source/kwsys/hashtable.hxx.in2
-rw-r--r--Source/kwsys/testHashSTL.cxx4
86 files changed, 2811 insertions, 2190 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 5b518b8..482bd39 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -238,12 +238,16 @@ set(SRCS
cmFileTimeComparison.cxx
cmFileTimeComparison.h
cmGeneratedFileStream.cxx
+ cmGeneratorExpressionContext.cxx
+ cmGeneratorExpressionContext.h
cmGeneratorExpressionDAGChecker.cxx
cmGeneratorExpressionDAGChecker.h
cmGeneratorExpressionEvaluator.cxx
cmGeneratorExpressionEvaluator.h
cmGeneratorExpressionLexer.cxx
cmGeneratorExpressionLexer.h
+ cmGeneratorExpressionNode.cxx
+ cmGeneratorExpressionNode.h
cmGeneratorExpressionParser.cxx
cmGeneratorExpressionParser.h
cmGeneratorExpression.cxx
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 22af221..5ef57ab 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -1,5 +1,5 @@
# CMake version number components.
set(CMake_VERSION_MAJOR 3)
set(CMake_VERSION_MINOR 2)
-set(CMake_VERSION_PATCH 20150302)
+set(CMake_VERSION_PATCH 20150323)
#set(CMake_VERSION_RC 1)
diff --git a/Source/CPack/WiX/cmCPackWIXGenerator.cxx b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
index 4b8daf8..257ce7a 100644
--- a/Source/CPack/WiX/cmCPackWIXGenerator.cxx
+++ b/Source/CPack/WiX/cmCPackWIXGenerator.cxx
@@ -265,13 +265,30 @@ bool cmCPackWIXGenerator::PackageFilesImpl()
AppendUserSuppliedExtraSources();
+ std::set<std::string> usedBaseNames;
+
std::stringstream objectFiles;
for(size_t i = 0; i < this->WixSources.size(); ++i)
{
std::string const& sourceFilename = this->WixSources[i];
+ std::string baseName =
+ cmSystemTools::GetFilenameWithoutLastExtension(sourceFilename);
+
+ unsigned int counter = 0;
+ std::string uniqueBaseName = baseName;
+
+ while(usedBaseNames.find(uniqueBaseName) != usedBaseNames.end())
+ {
+ std::stringstream tmp;
+ tmp << baseName << ++counter;
+ uniqueBaseName = tmp.str();
+ }
+
+ usedBaseNames.insert(uniqueBaseName);
+
std::string objectFilename =
- cmSystemTools::GetFilenameWithoutExtension(sourceFilename) + ".wixobj";
+ this->CPackTopLevel + "/" + uniqueBaseName + ".wixobj";
if(!RunCandleCommand(sourceFilename, objectFilename))
{
@@ -474,6 +491,7 @@ bool cmCPackWIXGenerator::CreateWiXSourceFiles()
featureDefinitions.AddAttribute("Title", cpackPackageName);
featureDefinitions.AddAttribute("Level", "1");
+ this->Patch->ApplyFragment("#PRODUCTFEATURE", featureDefinitions);
const char* package = GetOption("CPACK_WIX_CMAKE_PACKAGE_REGISTRY");
if(package)
diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx
index fe27e2b..29e07ef 100644
--- a/Source/CTest/cmCTestBuildHandler.cxx
+++ b/Source/CTest/cmCTestBuildHandler.cxx
@@ -20,6 +20,7 @@
#include "cmGeneratedFileStream.h"
#include "cmXMLSafe.h"
#include "cmFileTimeComparison.h"
+#include "cmAlgorithms.h"
//#include <cmsys/RegularExpression.hxx>
#include <cmsys/Process.h>
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index 6f72684..d7da2b4 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -577,11 +577,26 @@ void cmCTestRunTest::ComputeArguments()
}
this->TestResult.FullCommandLine = testCommand;
+ // Print the test command in verbose mode
cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, std::endl
<< this->Index << ": "
<< (this->TestHandler->MemCheck?"MemCheck":"Test")
<< " command: " << testCommand
<< std::endl);
+
+ // Print any test-specific env vars in verbose mode
+ if (this->TestProperties->Environment.size())
+ {
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->Index << ": "
+ << "Environment variables: " << std::endl);
+ }
+ for(std::vector<std::string>::const_iterator e =
+ this->TestProperties->Environment.begin();
+ e != this->TestProperties->Environment.end(); ++e)
+ {
+ cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, this->Index << ": " << *e
+ << std::endl);
+ }
}
//----------------------------------------------------------------------
diff --git a/Source/CTest/cmParseJacocoCoverage.cxx b/Source/CTest/cmParseJacocoCoverage.cxx
index ec4cfad..31ad9fe 100644
--- a/Source/CTest/cmParseJacocoCoverage.cxx
+++ b/Source/CTest/cmParseJacocoCoverage.cxx
@@ -78,7 +78,10 @@ class cmParseJacocoCoverage::XMLParser: public cmXMLParser
std::string line;
FileLinesType& curFileLines =
this->Coverage.TotalCoverage[this->CurFileName];
- curFileLines.push_back(-1);
+ if(fin)
+ {
+ curFileLines.push_back(-1);
+ }
while(cmSystemTools::GetLineFromStream(fin, line))
{
curFileLines.push_back(-1);
diff --git a/Source/CursesDialog/cmCursesMainForm.cxx b/Source/CursesDialog/cmCursesMainForm.cxx
index dcd0b6c..d60062e 100644
--- a/Source/CursesDialog/cmCursesMainForm.cxx
+++ b/Source/CursesDialog/cmCursesMainForm.cxx
@@ -22,6 +22,7 @@
#include "cmCursesDummyWidget.h"
#include "cmCursesCacheEntryComposite.h"
#include "cmCursesLongMessageForm.h"
+#include "cmAlgorithms.h"
inline int ctrl(int z)
diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h
index b9d7e78..f117475 100644
--- a/Source/cmAlgorithms.h
+++ b/Source/cmAlgorithms.h
@@ -237,6 +237,11 @@ typename Range::const_iterator cmRemoveIndices(Range& r, InputRange const& rem)
{
typename InputRange::const_iterator remIt = rem.begin();
typename InputRange::const_iterator remEnd = rem.end();
+ const typename Range::iterator rangeEnd = r.end();
+ if (remIt == remEnd)
+ {
+ return rangeEnd;
+ }
typename Range::iterator writer = r.begin();
std::advance(writer, *remIt);
@@ -244,7 +249,6 @@ typename Range::const_iterator cmRemoveIndices(Range& r, InputRange const& rem)
typename InputRange::value_type prevRem = *remIt;
++remIt;
size_t count = 1;
- const typename Range::iterator rangeEnd = r.end();
for ( ; writer != rangeEnd && remIt != remEnd; ++count, ++remIt)
{
std::advance(pivot, *remIt - prevRem);
@@ -261,23 +265,53 @@ typename Range::const_iterator cmRemoveMatching(Range &r, MatchRange const& m)
ContainerAlgorithms::BinarySearcher<MatchRange>(m));
}
+namespace ContainerAlgorithms {
+
+template<typename Range, typename T = typename Range::value_type>
+struct RemoveDuplicatesAPI
+{
+ typedef typename Range::const_iterator const_iterator;
+ typedef typename Range::const_iterator value_type;
+
+ static bool lessThan(value_type a, value_type b) { return *a < *b; }
+ static value_type uniqueValue(const_iterator a) { return a; }
+ template<typename It>
+ static bool valueCompare(It it, const_iterator it2) { return **it != *it2; }
+};
+
+template<typename Range, typename T>
+struct RemoveDuplicatesAPI<Range, T*>
+{
+ typedef typename Range::const_iterator const_iterator;
+ typedef T* value_type;
+
+ static bool lessThan(value_type a, value_type b) { return a < b; }
+ static value_type uniqueValue(const_iterator a) { return *a; }
+ template<typename It>
+ static bool valueCompare(It it, const_iterator it2) { return *it != *it2; }
+};
+
+}
+
template<typename Range>
typename Range::const_iterator cmRemoveDuplicates(Range& r)
{
- typedef std::vector<typename Range::value_type> UniqueVector;
- UniqueVector unique;
+ typedef typename ContainerAlgorithms::RemoveDuplicatesAPI<Range> API;
+ typedef typename API::value_type T;
+ std::vector<T> unique;
unique.reserve(r.size());
std::vector<size_t> indices;
size_t count = 0;
- const typename Range::iterator end = r.end();
+ const typename Range::const_iterator end = r.end();
for(typename Range::const_iterator it = r.begin();
it != end; ++it, ++count)
{
- const typename UniqueVector::iterator low =
- std::lower_bound(unique.begin(), unique.end(), *it);
- if (low == unique.end() || *low != *it)
+ const typename std::vector<T>::iterator low =
+ std::lower_bound(unique.begin(), unique.end(),
+ API::uniqueValue(it), API::lessThan);
+ if (low == unique.end() || API::valueCompare(low, it))
{
- unique.insert(low, *it);
+ unique.insert(low, API::uniqueValue(it));
}
else
{
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index 2cbdf9c..0026fd7 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -26,6 +26,7 @@
#include "cmVersionMacros.h"
#include "cmCTestCommand.h"
#include "cmCTestStartCommand.h"
+#include "cmAlgorithms.h"
#include "cmCTestBuildHandler.h"
#include "cmCTestBuildAndTestHandler.h"
diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx
index be28b2f..6005d5f 100644
--- a/Source/cmComputeLinkDepends.cxx
+++ b/Source/cmComputeLinkDepends.cxx
@@ -17,6 +17,7 @@
#include "cmMakefile.h"
#include "cmTarget.h"
#include "cmake.h"
+#include "cmAlgorithms.h"
#include <cmsys/stl/algorithm>
diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx
index 479da75..b0e0f36 100644
--- a/Source/cmComputeLinkInformation.cxx
+++ b/Source/cmComputeLinkInformation.cxx
@@ -19,6 +19,7 @@
#include "cmMakefile.h"
#include "cmTarget.h"
#include "cmake.h"
+#include "cmAlgorithms.h"
#include <ctype.h>
diff --git a/Source/cmConfigureFileCommand.cxx b/Source/cmConfigureFileCommand.cxx
index fa7f486..6876388 100644
--- a/Source/cmConfigureFileCommand.cxx
+++ b/Source/cmConfigureFileCommand.cxx
@@ -100,6 +100,13 @@ bool cmConfigureFileCommand
{
/* Ignore legacy option. */
}
+ else if(args[i] == "NEWLINE_STYLE" ||
+ args[i] == "LF" || args[i] == "UNIX" ||
+ args[i] == "CRLF" || args[i] == "WIN32" ||
+ args[i] == "DOS")
+ {
+ /* Options handled by NewLineStyle member above. */
+ }
else
{
unknown_args += " ";
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index e9390e4..59efa52 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -14,6 +14,7 @@
#include "cmCacheManager.h"
#include "cmLocalGenerator.h"
#include "cmGlobalGenerator.h"
+#include "cmAlgorithms.h"
#include "cmExportTryCompileFileGenerator.h"
#include <cmsys/Directory.hxx>
diff --git a/Source/cmDependsC.cxx b/Source/cmDependsC.cxx
index 6dde349..63d8fa6 100644
--- a/Source/cmDependsC.cxx
+++ b/Source/cmDependsC.cxx
@@ -15,6 +15,7 @@
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
+#include "cmAlgorithms.h"
#include <cmsys/FStream.hxx>
#include <ctype.h> // isspace
diff --git a/Source/cmDocumentation.cxx b/Source/cmDocumentation.cxx
index f4e3a75..8c17536 100644
--- a/Source/cmDocumentation.cxx
+++ b/Source/cmDocumentation.cxx
@@ -14,6 +14,7 @@
#include "cmSystemTools.h"
#include "cmVersion.h"
#include "cmRST.h"
+#include "cmAlgorithms.h"
#include <cmsys/Directory.hxx>
#include <cmsys/Glob.hxx>
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index 71728be..b4fad98 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -22,6 +22,7 @@
#include "cmTargetExport.h"
#include "cmVersion.h"
#include "cmComputeLinkInformation.h"
+#include "cmAlgorithms.h"
#include <cmsys/auto_ptr.hxx>
#include <cmsys/FStream.hxx>
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index ba1dde2..6d639c9 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -19,6 +19,7 @@
#include "cmInstallExportGenerator.h"
#include "cmInstallTargetGenerator.h"
#include "cmTargetExport.h"
+#include "cmAlgorithms.h"
//----------------------------------------------------------------------------
cmExportInstallFileGenerator
diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx
index 69857ef..554b686 100644
--- a/Source/cmExtraCodeBlocksGenerator.cxx
+++ b/Source/cmExtraCodeBlocksGenerator.cxx
@@ -376,11 +376,13 @@ void cmExtraCodeBlocksGenerator
fout<<" </Build>\n";
- // Collect all used source files in the project
- // Sort them into two containers, one for C/C++ implementation files
- // which may have an acompanying header, one for all other files
- std::map<std::string, cmSourceFile*> cFiles;
- std::set<std::string> otherFiles;
+ // Collect all used source files in the project.
+ // Keep a list of C/C++ source files which might have an acompanying header
+ // that should be looked for.
+ typedef std::map<std::string, CbpUnit> all_files_map_t;
+ all_files_map_t allFiles;
+ std::vector<std::string> cFiles;
+
for (std::vector<cmLocalGenerator*>::const_iterator lg=lgs.begin();
lg!=lgs.end(); lg++)
{
@@ -429,15 +431,15 @@ void cmExtraCodeBlocksGenerator
}
}
- // then put it accordingly into one of the two containers
- if (isCFile)
- {
- cFiles[(*si)->GetFullPath()] = *si ;
- }
- else
+ std::string fullPath = (*si)->GetFullPath();
+
+ if(isCFile)
{
- otherFiles.insert((*si)->GetFullPath());
+ cFiles.push_back(fullPath);
}
+
+ CbpUnit &cbpUnit = allFiles[fullPath];
+ cbpUnit.Targets.push_back(&(ti->second));
}
}
default: // intended fallthrough
@@ -447,19 +449,21 @@ void cmExtraCodeBlocksGenerator
}
// The following loop tries to add header files matching to implementation
- // files to the project. It does that by iterating over all source files,
+ // files to the project. It does that by iterating over all
+ // C/C++ source files,
// replacing the file name extension with ".h" and checks whether such a
// file exists. If it does, it is inserted into the map of files.
// A very similar version of that code exists also in the kdevelop
// project generator.
- for (std::map<std::string, cmSourceFile*>::const_iterator
+ for (std::vector<std::string>::const_iterator
sit=cFiles.begin();
sit!=cFiles.end();
++sit)
{
- std::string headerBasename=cmSystemTools::GetFilenamePath(sit->first);
+ std::string const& fileName = *sit;
+ std::string headerBasename=cmSystemTools::GetFilenamePath(fileName);
headerBasename+="/";
- headerBasename+=cmSystemTools::GetFilenameWithoutExtension(sit->first);
+ headerBasename+=cmSystemTools::GetFilenameWithoutExtension(fileName);
// check if there's a matching header around
for(std::vector<std::string>::const_iterator
@@ -471,37 +475,38 @@ void cmExtraCodeBlocksGenerator
hname += ".";
hname += *ext;
// if it's already in the set, don't check if it exists on disk
- std::set<std::string>::const_iterator headerIt=otherFiles.find(hname);
- if (headerIt != otherFiles.end())
+ if (allFiles.find(hname) != allFiles.end())
{
break;
}
if(cmSystemTools::FileExists(hname.c_str()))
{
- otherFiles.insert(hname);
+ allFiles[hname].Targets = allFiles[fileName].Targets;
break;
}
}
}
// insert all source files in the CodeBlocks project
- // first the C/C++ implementation files, then all others
- for (std::map<std::string, cmSourceFile*>::const_iterator
- sit=cFiles.begin();
- sit!=cFiles.end();
+ for (all_files_map_t::const_iterator
+ sit=allFiles.begin();
+ sit!=allFiles.end();
++sit)
{
- fout<<" <Unit filename=\""<< sit->first <<"\">\n"
- " </Unit>\n";
- }
- for (std::set<std::string>::const_iterator
- sit=otherFiles.begin();
- sit!=otherFiles.end();
- ++sit)
- {
- fout<<" <Unit filename=\""<< *sit <<"\">\n"
- " </Unit>\n";
+ std::string const& unitFilename = sit->first;
+ CbpUnit const& unit = sit->second;
+
+ fout<<" <Unit filename=\""<< cmXMLSafe(unitFilename) <<"\">\n";
+
+ for(std::vector<const cmTarget*>::const_iterator ti = unit.Targets.begin();
+ ti != unit.Targets.end(); ++ti)
+ {
+ std::string const& targetName = (*ti)->GetName();
+ fout<<" <Option target=\""<< cmXMLSafe(targetName) <<"\"/>\n";
+ }
+
+ fout<<" </Unit>\n";
}
// Add CMakeLists.txt
@@ -599,7 +604,7 @@ void cmExtraCodeBlocksGenerator::AppendTarget(cmGeneratedFileStream& fout,
// the compilerdefines for this target
std::vector<std::string> cdefs;
- target->GetCompileDefinitions(cdefs, buildType);
+ target->GetCompileDefinitions(cdefs, buildType, "C");
// Expand the list.
for(std::vector<std::string>::const_iterator di = cdefs.begin();
diff --git a/Source/cmExtraCodeBlocksGenerator.h b/Source/cmExtraCodeBlocksGenerator.h
index 0435ad8..97da1b8 100644
--- a/Source/cmExtraCodeBlocksGenerator.h
+++ b/Source/cmExtraCodeBlocksGenerator.h
@@ -39,6 +39,10 @@ public:
virtual void Generate();
private:
+ struct CbpUnit
+ {
+ std::vector<const cmTarget*> Targets;
+ };
void CreateProjectFile(const std::vector<cmLocalGenerator*>& lgs);
diff --git a/Source/cmExtraSublimeTextGenerator.cxx b/Source/cmExtraSublimeTextGenerator.cxx
index 5fff0fb..25f9005 100644
--- a/Source/cmExtraSublimeTextGenerator.cxx
+++ b/Source/cmExtraSublimeTextGenerator.cxx
@@ -436,7 +436,7 @@ ComputeDefines(cmSourceFile *source, cmLocalGenerator* lg, cmTarget *target,
}
// Add preprocessor definitions for this target and configuration.
- lg->AddCompileDefinitions(defines, target, config);
+ lg->AddCompileDefinitions(defines, target, config, language);
lg->AppendDefines(defines, source->GetProperty("COMPILE_DEFINITIONS"));
{
std::string defPropName = "COMPILE_DEFINITIONS_";
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 0290c92..ae9099e 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -16,6 +16,7 @@
#include "cmInstallType.h"
#include "cmFileTimeComparison.h"
#include "cmCryptoHash.h"
+#include "cmAlgorithms.h"
#include "cmTimestamp.h"
@@ -919,6 +920,35 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args,
bool first = true;
for ( ; i != args.end(); ++i )
{
+ if( *i == "LIST_DIRECTORIES" )
+ {
+ ++i;
+ if(i != args.end())
+ {
+ if(cmSystemTools::IsOn(i->c_str()))
+ {
+ g.SetListDirs(true);
+ g.SetRecurseListDirs(true);
+ }
+ else if(cmSystemTools::IsOff(i->c_str()))
+ {
+ g.SetListDirs(false);
+ g.SetRecurseListDirs(false);
+ }
+ else
+ {
+ this->SetError("LIST_DIRECTORIES missing bool value.");
+ return false;
+ }
+ }
+ else
+ {
+ this->SetError("LIST_DIRECTORIES missing bool value.");
+ return false;
+ }
+ ++i;
+ }
+
if ( recurse && (*i == "FOLLOW_SYMLINKS") )
{
explicitFollowSymlinks = true;
@@ -949,6 +979,7 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args,
}
}
+ cmsys::Glob::GlobMessages globMessages;
if ( !cmsys::SystemTools::FileIsFullPath(i->c_str()) )
{
std::string expr = this->Makefile->GetCurrentDirectory();
@@ -956,16 +987,42 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args,
if (!expr.empty())
{
expr += "/" + *i;
- g.FindFiles(expr);
+ g.FindFiles(expr, &globMessages);
}
else
{
- g.FindFiles(*i);
+ g.FindFiles(*i, &globMessages);
}
}
else
{
- g.FindFiles(*i);
+ g.FindFiles(*i, &globMessages);
+ }
+
+ if(!globMessages.empty())
+ {
+ bool shouldExit = false;
+ for(cmsys::Glob::GlobMessagesIterator it=globMessages.begin();
+ it != globMessages.end(); ++it)
+ {
+ if(it->type == cmsys::Glob::cyclicRecursion)
+ {
+ this->Makefile->IssueMessage(cmake::AUTHOR_WARNING,
+ "Cyclic recursion detected while globbing for '"
+ + *i + "':\n" + it->content);
+ }
+ else
+ {
+ this->Makefile->IssueMessage(cmake::FATAL_ERROR,
+ "Error has occured while globbing for '"
+ + *i + "' - " + it->content);
+ shouldExit = true;
+ }
+ }
+ if(shouldExit)
+ {
+ return false;
+ }
}
std::vector<std::string>::size_type cc;
diff --git a/Source/cmFindBase.cxx b/Source/cmFindBase.cxx
index ffc641c..f63df61 100644
--- a/Source/cmFindBase.cxx
+++ b/Source/cmFindBase.cxx
@@ -11,6 +11,8 @@
============================================================================*/
#include "cmFindBase.h"
+#include "cmAlgorithms.h"
+
cmFindBase::cmFindBase()
{
this->AlreadyInCache = false;
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index 26bd4b9..87f9037 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -14,6 +14,7 @@
#include <cmsys/Directory.hxx>
#include <cmsys/RegularExpression.hxx>
#include <cmsys/Encoding.hxx>
+#include "cmAlgorithms.h"
#ifdef CMAKE_BUILD_WITH_CMAKE
#include "cmVariableWatch.h"
diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx
index bf96951..a1c405b 100644
--- a/Source/cmGeneratorExpression.cxx
+++ b/Source/cmGeneratorExpression.cxx
@@ -14,6 +14,7 @@
#include "cmMakefile.h"
#include "cmTarget.h"
#include "assert.h"
+#include "cmAlgorithms.h"
#include "cmGeneratorExpressionEvaluator.h"
#include "cmGeneratorExpressionLexer.h"
@@ -52,14 +53,16 @@ cmGeneratorExpression::~cmGeneratorExpression()
const char *cmCompiledGeneratorExpression::Evaluate(
cmMakefile* mf, const std::string& config, bool quiet,
cmTarget const* headTarget,
- cmGeneratorExpressionDAGChecker *dagChecker) const
+ cmGeneratorExpressionDAGChecker *dagChecker,
+ std::string const& language) const
{
return this->Evaluate(mf,
config,
quiet,
headTarget,
headTarget,
- dagChecker);
+ dagChecker,
+ language);
}
//----------------------------------------------------------------------------
@@ -67,7 +70,21 @@ const char *cmCompiledGeneratorExpression::Evaluate(
cmMakefile* mf, const std::string& config, bool quiet,
cmTarget const* headTarget,
cmTarget const* currentTarget,
- cmGeneratorExpressionDAGChecker *dagChecker) const
+ cmGeneratorExpressionDAGChecker *dagChecker,
+ std::string const& language) const
+{
+ cmGeneratorExpressionContext context(mf, config, quiet, headTarget,
+ currentTarget ? currentTarget : headTarget,
+ this->EvaluateForBuildsystem,
+ this->Backtrace, language);
+
+ return this->EvaluateWithContext(context, dagChecker);
+}
+
+//----------------------------------------------------------------------------
+const char* cmCompiledGeneratorExpression::EvaluateWithContext(
+ cmGeneratorExpressionContext& context,
+ cmGeneratorExpressionDAGChecker *dagChecker) const
{
if (!this->NeedsEvaluation)
{
@@ -81,19 +98,6 @@ const char *cmCompiledGeneratorExpression::Evaluate(
const std::vector<cmGeneratorExpressionEvaluator*>::const_iterator end
= this->Evaluators.end();
- cmGeneratorExpressionContext context;
- context.Makefile = mf;
- context.Config = config;
- context.Quiet = quiet;
- context.HadError = false;
- context.HadContextSensitiveCondition = false;
- context.HadHeadSensitiveCondition = false;
- context.SourceSensitiveTargets.clear();
- context.HeadTarget = headTarget;
- context.EvaluateForBuildsystem = this->EvaluateForBuildsystem;
- context.CurrentTarget = currentTarget ? currentTarget : headTarget;
- context.Backtrace = this->Backtrace;
-
for ( ; it != end; ++it)
{
this->Output += (*it)->Evaluate(&context, dagChecker);
diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h
index 57f78c5..11c27fd 100644
--- a/Source/cmGeneratorExpression.h
+++ b/Source/cmGeneratorExpression.h
@@ -24,6 +24,7 @@ class cmMakefile;
class cmListFileBacktrace;
struct cmGeneratorExpressionEvaluator;
+struct cmGeneratorExpressionContext;
struct cmGeneratorExpressionDAGChecker;
class cmCompiledGeneratorExpression;
@@ -80,11 +81,13 @@ public:
bool quiet = false,
cmTarget const* headTarget = 0,
cmTarget const* currentTarget = 0,
- cmGeneratorExpressionDAGChecker *dagChecker = 0) const;
+ cmGeneratorExpressionDAGChecker *dagChecker = 0,
+ std::string const& language = std::string()) const;
const char* Evaluate(cmMakefile* mf, const std::string& config,
bool quiet,
cmTarget const* headTarget,
- cmGeneratorExpressionDAGChecker *dagChecker) const;
+ cmGeneratorExpressionDAGChecker *dagChecker,
+ std::string const& language = std::string()) const;
/** Get set of targets found during evaluations. */
std::set<cmTarget*> const& GetTargets() const
@@ -129,6 +132,9 @@ public:
std::map<std::string, std::string>& mapping);
private:
+ const char* EvaluateWithContext(cmGeneratorExpressionContext& context,
+ cmGeneratorExpressionDAGChecker *dagChecker) const;
+
cmCompiledGeneratorExpression(cmListFileBacktrace const& backtrace,
const std::string& input);
diff --git a/Source/cmGeneratorExpressionContext.cxx b/Source/cmGeneratorExpressionContext.cxx
new file mode 100644
index 0000000..947015e
--- /dev/null
+++ b/Source/cmGeneratorExpressionContext.cxx
@@ -0,0 +1,34 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2012 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 "cmGeneratorExpressionContext.h"
+
+cmGeneratorExpressionContext::cmGeneratorExpressionContext(
+ cmMakefile* mf, std::string const& config,
+ bool quiet, cmTarget const* headTarget,
+ cmTarget const* currentTarget,
+ bool evaluateForBuildsystem,
+ cmListFileBacktrace const& backtrace,
+ std::string const& language)
+ : Backtrace(backtrace),
+ Makefile(mf),
+ Config(config),
+ Language(language),
+ HeadTarget(headTarget),
+ CurrentTarget(currentTarget),
+ Quiet(quiet),
+ HadError(false),
+ HadContextSensitiveCondition(false),
+ HadHeadSensitiveCondition(false),
+ EvaluateForBuildsystem(evaluateForBuildsystem)
+{
+}
diff --git a/Source/cmGeneratorExpressionContext.h b/Source/cmGeneratorExpressionContext.h
new file mode 100644
index 0000000..ed83509
--- /dev/null
+++ b/Source/cmGeneratorExpressionContext.h
@@ -0,0 +1,54 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2012 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 cmGeneratorExpressionContext_h
+#define cmGeneratorExpressionContext_h
+
+#include "cmListFileCache.h"
+
+#include <set>
+#include <map>
+#include <string>
+
+class cmTarget;
+
+//----------------------------------------------------------------------------
+struct cmGeneratorExpressionContext
+{
+ cmGeneratorExpressionContext(cmMakefile* mf, std::string const& config,
+ bool quiet, cmTarget const* headTarget,
+ cmTarget const* currentTarget,
+ bool evaluateForBuildsystem,
+ cmListFileBacktrace const& backtrace,
+ std::string const& language);
+
+
+ cmListFileBacktrace Backtrace;
+ std::set<cmTarget*> DependTargets;
+ std::set<cmTarget const*> AllTargets;
+ std::set<std::string> SeenTargetProperties;
+ std::set<cmTarget const*> SourceSensitiveTargets;
+ std::map<cmTarget const*, std::map<std::string, std::string> >
+ MaxLanguageStandard;
+ cmMakefile *Makefile;
+ std::string Config;
+ std::string Language;
+ cmTarget const* HeadTarget; // The target whose property is being evaluated.
+ cmTarget const* CurrentTarget; // The dependent of HeadTarget which appears
+ // directly or indirectly in the property.
+ bool Quiet;
+ bool HadError;
+ bool HadContextSensitiveCondition;
+ bool HadHeadSensitiveCondition;
+ bool EvaluateForBuildsystem;
+};
+
+#endif
diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx
index c8b9949..ff8790c 100644
--- a/Source/cmGeneratorExpressionDAGChecker.cxx
+++ b/Source/cmGeneratorExpressionDAGChecker.cxx
@@ -13,6 +13,7 @@
#include "cmGeneratorExpressionDAGChecker.h"
#include "cmMakefile.h"
+#include "cmAlgorithms.h"
//----------------------------------------------------------------------------
cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
diff --git a/Source/cmGeneratorExpressionEvaluationFile.cxx b/Source/cmGeneratorExpressionEvaluationFile.cxx
index 4e2a868..fa00283 100644
--- a/Source/cmGeneratorExpressionEvaluationFile.cxx
+++ b/Source/cmGeneratorExpressionEvaluationFile.cxx
@@ -38,13 +38,15 @@ cmGeneratorExpressionEvaluationFile::cmGeneratorExpressionEvaluationFile(
//----------------------------------------------------------------------------
void cmGeneratorExpressionEvaluationFile::Generate(const std::string& config,
+ const std::string& lang,
cmCompiledGeneratorExpression* inputExpression,
std::map<std::string, std::string> &outputFiles, mode_t perm)
{
std::string rawCondition = this->Condition->GetInput();
if (!rawCondition.empty())
{
- std::string condResult = this->Condition->Evaluate(this->Makefile, config);
+ std::string condResult = this->Condition->Evaluate(this->Makefile, config,
+ false, 0, 0, 0, lang);
if (condResult == "0")
{
return;
@@ -60,9 +62,11 @@ void cmGeneratorExpressionEvaluationFile::Generate(const std::string& config,
}
const std::string outputFileName
- = this->OutputFileExpr->Evaluate(this->Makefile, config);
+ = this->OutputFileExpr->Evaluate(this->Makefile, config,
+ false, 0, 0, 0, lang);
const std::string outputContent
- = inputExpression->Evaluate(this->Makefile, config);
+ = inputExpression->Evaluate(this->Makefile, config,
+ false, 0, 0, 0, lang);
std::map<std::string, std::string>::iterator it
= outputFiles.find(outputFileName);
@@ -75,7 +79,8 @@ void cmGeneratorExpressionEvaluationFile::Generate(const std::string& config,
}
std::ostringstream e;
e << "Evaluation file to be written multiple times for different "
- "configurations with different content:\n " << outputFileName;
+ "configurations or languages with different content:\n "
+ << outputFileName;
this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str());
return;
}
@@ -97,14 +102,22 @@ void cmGeneratorExpressionEvaluationFile::Generate(const std::string& config,
void cmGeneratorExpressionEvaluationFile::CreateOutputFile(
std::string const& config)
{
- std::string name = this->OutputFileExpr->Evaluate(this->Makefile, config);
- cmSourceFile* sf = this->Makefile->GetOrCreateSource(name);
- sf->SetProperty("GENERATED", "1");
-
+ std::vector<std::string> enabledLanguages;
cmGlobalGenerator *gg
= this->Makefile->GetLocalGenerator()->GetGlobalGenerator();
- gg->SetFilenameTargetDepends(sf,
+ gg->GetEnabledLanguages(enabledLanguages);
+
+ for(std::vector<std::string>::const_iterator le = enabledLanguages.begin();
+ le != enabledLanguages.end(); ++le)
+ {
+ std::string name = this->OutputFileExpr->Evaluate(this->Makefile, config,
+ false, 0, 0, 0, *le);
+ cmSourceFile* sf = this->Makefile->GetOrCreateSource(name);
+ sf->SetProperty("GENERATED", "1");
+
+ gg->SetFilenameTargetDepends(sf,
this->OutputFileExpr->GetSourceSensitiveTargets());
+ }
}
//----------------------------------------------------------------------------
@@ -153,13 +166,23 @@ void cmGeneratorExpressionEvaluationFile::Generate()
{
allConfigs.push_back("");
}
- for(std::vector<std::string>::const_iterator li = allConfigs.begin();
- li != allConfigs.end(); ++li)
+
+ std::vector<std::string> enabledLanguages;
+ cmGlobalGenerator *gg
+ = this->Makefile->GetLocalGenerator()->GetGlobalGenerator();
+ gg->GetEnabledLanguages(enabledLanguages);
+
+ for(std::vector<std::string>::const_iterator le = enabledLanguages.begin();
+ le != enabledLanguages.end(); ++le)
{
- this->Generate(*li, inputExpression.get(), outputFiles, perm);
- if(cmSystemTools::GetFatalErrorOccured())
+ for(std::vector<std::string>::const_iterator li = allConfigs.begin();
+ li != allConfigs.end(); ++li)
{
- return;
+ this->Generate(*li, *le, inputExpression.get(), outputFiles, perm);
+ if(cmSystemTools::GetFatalErrorOccured())
+ {
+ return;
+ }
}
}
}
diff --git a/Source/cmGeneratorExpressionEvaluationFile.h b/Source/cmGeneratorExpressionEvaluationFile.h
index 3394ade..4424bec 100644
--- a/Source/cmGeneratorExpressionEvaluationFile.h
+++ b/Source/cmGeneratorExpressionEvaluationFile.h
@@ -34,7 +34,7 @@ public:
void CreateOutputFile(std::string const& config);
private:
- void Generate(const std::string& config,
+ void Generate(const std::string& config, const std::string& lang,
cmCompiledGeneratorExpression* inputExpression,
std::map<std::string, std::string> &outputFiles, mode_t perm);
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index ba18faa..af94bcc 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -16,1828 +16,16 @@
#include "cmGeneratorExpressionDAGChecker.h"
#include "cmGeneratorExpression.h"
#include "cmLocalGenerator.h"
+#include "cmGlobalGenerator.h"
#include "cmSourceFile.h"
+#include "cmAlgorithms.h"
#include <cmsys/String.h>
#include <assert.h>
#include <errno.h>
-//----------------------------------------------------------------------------
-static void reportError(cmGeneratorExpressionContext *context,
- const std::string &expr, const std::string &result)
-{
- context->HadError = true;
- if (context->Quiet)
- {
- return;
- }
-
- std::ostringstream e;
- e << "Error evaluating generator expression:\n"
- << " " << expr << "\n"
- << result;
- context->Makefile->GetCMakeInstance()
- ->IssueMessage(cmake::FATAL_ERROR, e.str(),
- context->Backtrace);
-}
-
-//----------------------------------------------------------------------------
-struct cmGeneratorExpressionNode
-{
- enum {
- DynamicParameters = 0,
- OneOrMoreParameters = -1,
- OneOrZeroParameters = -2
- };
- virtual ~cmGeneratorExpressionNode() {}
-
- virtual bool GeneratesContent() const { return true; }
-
- virtual bool RequiresLiteralInput() const { return false; }
-
- virtual bool AcceptsArbitraryContentParameter() const
- { return false; }
-
- virtual int NumExpectedParameters() const { return 1; }
-
- virtual std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *dagChecker
- ) const = 0;
-
- static std::string EvaluateDependentExpression(
- std::string const& prop, cmMakefile *makefile,
- cmGeneratorExpressionContext *context,
- cmTarget const* headTarget, cmTarget const* currentTarget,
- cmGeneratorExpressionDAGChecker *dagChecker);
-};
-
-//----------------------------------------------------------------------------
-std::string cmGeneratorExpressionNode::EvaluateDependentExpression(
- std::string const& prop, cmMakefile *makefile,
- cmGeneratorExpressionContext *context,
- cmTarget const* headTarget, cmTarget const* currentTarget,
- cmGeneratorExpressionDAGChecker *dagChecker)
-{
- cmGeneratorExpression ge(&context->Backtrace);
- cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
- cge->SetEvaluateForBuildsystem(context->EvaluateForBuildsystem);
- std::string result = cge->Evaluate(makefile,
- context->Config,
- context->Quiet,
- headTarget,
- currentTarget,
- dagChecker);
- if (cge->GetHadContextSensitiveCondition())
- {
- context->HadContextSensitiveCondition = true;
- }
- if (cge->GetHadHeadSensitiveCondition())
- {
- context->HadHeadSensitiveCondition = true;
- }
- return result;
-}
-
-//----------------------------------------------------------------------------
-static const struct ZeroNode : public cmGeneratorExpressionNode
-{
- ZeroNode() {}
-
- virtual bool GeneratesContent() const { return false; }
-
- virtual bool AcceptsArbitraryContentParameter() const { return true; }
-
- std::string Evaluate(const std::vector<std::string> &,
- cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- return std::string();
- }
-} zeroNode;
-
-//----------------------------------------------------------------------------
-static const struct OneNode : public cmGeneratorExpressionNode
-{
- OneNode() {}
-
- virtual bool AcceptsArbitraryContentParameter() const { return true; }
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- return parameters.front();
- }
-} oneNode;
-
-//----------------------------------------------------------------------------
-static const struct OneNode buildInterfaceNode;
-
-//----------------------------------------------------------------------------
-static const struct ZeroNode installInterfaceNode;
-
-//----------------------------------------------------------------------------
-#define BOOLEAN_OP_NODE(OPNAME, OP, SUCCESS_VALUE, FAILURE_VALUE) \
-static const struct OP ## Node : public cmGeneratorExpressionNode \
-{ \
- OP ## Node () {} \
- virtual int NumExpectedParameters() const { return OneOrMoreParameters; } \
- \
- std::string Evaluate(const std::vector<std::string> &parameters, \
- cmGeneratorExpressionContext *context, \
- const GeneratorExpressionContent *content, \
- cmGeneratorExpressionDAGChecker *) const \
- { \
- std::vector<std::string>::const_iterator it = parameters.begin(); \
- const std::vector<std::string>::const_iterator end = parameters.end(); \
- for ( ; it != end; ++it) \
- { \
- if (*it == #FAILURE_VALUE) \
- { \
- return #FAILURE_VALUE; \
- } \
- else if (*it != #SUCCESS_VALUE) \
- { \
- reportError(context, content->GetOriginalExpression(), \
- "Parameters to $<" #OP "> must resolve to either '0' or '1'."); \
- return std::string(); \
- } \
- } \
- return #SUCCESS_VALUE; \
- } \
-} OPNAME;
-
-BOOLEAN_OP_NODE(andNode, AND, 1, 0)
-BOOLEAN_OP_NODE(orNode, OR, 0, 1)
-
-#undef BOOLEAN_OP_NODE
-
-//----------------------------------------------------------------------------
-static const struct NotNode : public cmGeneratorExpressionNode
-{
- NotNode() {}
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *) const
- {
- if (*parameters.begin() != "0" && *parameters.begin() != "1")
- {
- reportError(context, content->GetOriginalExpression(),
- "$<NOT> parameter must resolve to exactly one '0' or '1' value.");
- return std::string();
- }
- return *parameters.begin() == "0" ? "1" : "0";
- }
-} notNode;
-
-//----------------------------------------------------------------------------
-static const struct BoolNode : public cmGeneratorExpressionNode
-{
- BoolNode() {}
-
- virtual int NumExpectedParameters() const { return 1; }
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- return !cmSystemTools::IsOff(parameters.begin()->c_str()) ? "1" : "0";
- }
-} boolNode;
-
-//----------------------------------------------------------------------------
-static const struct StrEqualNode : public cmGeneratorExpressionNode
-{
- StrEqualNode() {}
-
- virtual int NumExpectedParameters() const { return 2; }
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- return *parameters.begin() == parameters[1] ? "1" : "0";
- }
-} strEqualNode;
-
-//----------------------------------------------------------------------------
-static const struct EqualNode : public cmGeneratorExpressionNode
-{
- EqualNode() {}
-
- virtual int NumExpectedParameters() const { return 2; }
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *) const
- {
- char *pEnd;
-
- int base = 0;
- bool flipSign = false;
-
- const char *lhs = parameters[0].c_str();
- if (cmHasLiteralPrefix(lhs, "0b") || cmHasLiteralPrefix(lhs, "0B"))
- {
- base = 2;
- lhs += 2;
- }
- if (cmHasLiteralPrefix(lhs, "-0b") || cmHasLiteralPrefix(lhs, "-0B"))
- {
- base = 2;
- lhs += 3;
- flipSign = true;
- }
- if (cmHasLiteralPrefix(lhs, "+0b") || cmHasLiteralPrefix(lhs, "+0B"))
- {
- base = 2;
- lhs += 3;
- }
-
- long lnum = strtol(lhs, &pEnd, base);
- if (pEnd == lhs || *pEnd != '\0' || errno == ERANGE)
- {
- reportError(context, content->GetOriginalExpression(),
- "$<EQUAL> parameter " + parameters[0] + " is not a valid integer.");
- return std::string();
- }
-
- if (flipSign)
- {
- lnum = -lnum;
- }
-
- base = 0;
- flipSign = false;
-
- const char *rhs = parameters[1].c_str();
- if (cmHasLiteralPrefix(rhs, "0b") || cmHasLiteralPrefix(rhs, "0B"))
- {
- base = 2;
- rhs += 2;
- }
- if (cmHasLiteralPrefix(rhs, "-0b") || cmHasLiteralPrefix(rhs, "-0B"))
- {
- base = 2;
- rhs += 3;
- flipSign = true;
- }
- if (cmHasLiteralPrefix(rhs, "+0b") || cmHasLiteralPrefix(rhs, "+0B"))
- {
- base = 2;
- rhs += 3;
- }
-
- long rnum = strtol(rhs, &pEnd, base);
- if (pEnd == rhs || *pEnd != '\0' || errno == ERANGE)
- {
- reportError(context, content->GetOriginalExpression(),
- "$<EQUAL> parameter " + parameters[1] + " is not a valid integer.");
- return std::string();
- }
-
- if (flipSign)
- {
- rnum = -rnum;
- }
-
- return lnum == rnum ? "1" : "0";
- }
-} equalNode;
-
-//----------------------------------------------------------------------------
-static const struct LowerCaseNode : public cmGeneratorExpressionNode
-{
- LowerCaseNode() {}
-
- bool AcceptsArbitraryContentParameter() const { return true; }
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- return cmSystemTools::LowerCase(parameters.front());
- }
-} lowerCaseNode;
-
-//----------------------------------------------------------------------------
-static const struct UpperCaseNode : public cmGeneratorExpressionNode
-{
- UpperCaseNode() {}
-
- bool AcceptsArbitraryContentParameter() const { return true; }
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- return cmSystemTools::UpperCase(parameters.front());
- }
-} upperCaseNode;
-
-//----------------------------------------------------------------------------
-static const struct MakeCIdentifierNode : public cmGeneratorExpressionNode
-{
- MakeCIdentifierNode() {}
-
- bool AcceptsArbitraryContentParameter() const { return true; }
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- return cmSystemTools::MakeCidentifier(parameters.front());
- }
-} makeCIdentifierNode;
-
-//----------------------------------------------------------------------------
-static const struct Angle_RNode : public cmGeneratorExpressionNode
-{
- Angle_RNode() {}
-
- virtual int NumExpectedParameters() const { return 0; }
-
- std::string Evaluate(const std::vector<std::string> &,
- cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- return ">";
- }
-} angle_rNode;
-
-//----------------------------------------------------------------------------
-static const struct CommaNode : public cmGeneratorExpressionNode
-{
- CommaNode() {}
-
- virtual int NumExpectedParameters() const { return 0; }
-
- std::string Evaluate(const std::vector<std::string> &,
- cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- return ",";
- }
-} commaNode;
-
-//----------------------------------------------------------------------------
-static const struct SemicolonNode : public cmGeneratorExpressionNode
-{
- SemicolonNode() {}
-
- virtual int NumExpectedParameters() const { return 0; }
-
- std::string Evaluate(const std::vector<std::string> &,
- cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- return ";";
- }
-} semicolonNode;
-
-//----------------------------------------------------------------------------
-struct CompilerIdNode : public cmGeneratorExpressionNode
-{
- CompilerIdNode() {}
-
- virtual int NumExpectedParameters() const { return OneOrZeroParameters; }
-
- std::string EvaluateWithLanguage(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *,
- const std::string &lang) const
- {
- const char *compilerId =
- context->Makefile->GetSafeDefinition("CMAKE_" + lang + "_COMPILER_ID");
- if (parameters.empty())
- {
- return compilerId ? compilerId : "";
- }
- static cmsys::RegularExpression compilerIdValidator("^[A-Za-z0-9_]*$");
- if (!compilerIdValidator.find(*parameters.begin()))
- {
- reportError(context, content->GetOriginalExpression(),
- "Expression syntax not recognized.");
- return std::string();
- }
- if (!compilerId)
- {
- return parameters.front().empty() ? "1" : "0";
- }
-
- if (strcmp(parameters.begin()->c_str(), compilerId) == 0)
- {
- return "1";
- }
-
- if (cmsysString_strcasecmp(parameters.begin()->c_str(), compilerId) == 0)
- {
- switch(context->Makefile->GetPolicyStatus(cmPolicies::CMP0044))
- {
- case cmPolicies::WARN:
- {
- std::ostringstream e;
- e << context->Makefile->GetPolicies()
- ->GetPolicyWarning(cmPolicies::CMP0044);
- context->Makefile->GetCMakeInstance()
- ->IssueMessage(cmake::AUTHOR_WARNING,
- e.str(), context->Backtrace);
- }
- case cmPolicies::OLD:
- return "1";
- case cmPolicies::NEW:
- case cmPolicies::REQUIRED_ALWAYS:
- case cmPolicies::REQUIRED_IF_USED:
- break;
- }
- }
- return "0";
- }
-};
-
-//----------------------------------------------------------------------------
-static const struct CCompilerIdNode : public CompilerIdNode
-{
- CCompilerIdNode() {}
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *dagChecker) const
- {
- if (!context->HeadTarget)
- {
- reportError(context, content->GetOriginalExpression(),
- "$<C_COMPILER_ID> may only be used with binary targets. It may "
- "not be used with add_custom_command or add_custom_target.");
- return std::string();
- }
- return this->EvaluateWithLanguage(parameters, context, content,
- dagChecker, "C");
- }
-} cCompilerIdNode;
-
-//----------------------------------------------------------------------------
-static const struct CXXCompilerIdNode : public CompilerIdNode
-{
- CXXCompilerIdNode() {}
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *dagChecker) const
- {
- if (!context->HeadTarget)
- {
- reportError(context, content->GetOriginalExpression(),
- "$<CXX_COMPILER_ID> may only be used with binary targets. It may "
- "not be used with add_custom_command or add_custom_target.");
- return std::string();
- }
- return this->EvaluateWithLanguage(parameters, context, content,
- dagChecker, "CXX");
- }
-} cxxCompilerIdNode;
-
-//----------------------------------------------------------------------------
-struct CompilerVersionNode : public cmGeneratorExpressionNode
-{
- CompilerVersionNode() {}
-
- virtual int NumExpectedParameters() const { return OneOrZeroParameters; }
-
- std::string EvaluateWithLanguage(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *,
- const std::string &lang) const
- {
- const char *compilerVersion = context->Makefile->GetSafeDefinition(
- "CMAKE_" + lang + "_COMPILER_VERSION");
- if (parameters.empty())
- {
- return compilerVersion ? compilerVersion : "";
- }
-
- static cmsys::RegularExpression compilerIdValidator("^[0-9\\.]*$");
- if (!compilerIdValidator.find(*parameters.begin()))
- {
- reportError(context, content->GetOriginalExpression(),
- "Expression syntax not recognized.");
- return std::string();
- }
- if (!compilerVersion)
- {
- return parameters.front().empty() ? "1" : "0";
- }
-
- return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
- parameters.begin()->c_str(),
- compilerVersion) ? "1" : "0";
- }
-};
-
-//----------------------------------------------------------------------------
-static const struct CCompilerVersionNode : public CompilerVersionNode
-{
- CCompilerVersionNode() {}
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *dagChecker) const
- {
- if (!context->HeadTarget)
- {
- reportError(context, content->GetOriginalExpression(),
- "$<C_COMPILER_VERSION> may only be used with binary targets. It "
- "may not be used with add_custom_command or add_custom_target.");
- return std::string();
- }
- return this->EvaluateWithLanguage(parameters, context, content,
- dagChecker, "C");
- }
-} cCompilerVersionNode;
-
-//----------------------------------------------------------------------------
-static const struct CxxCompilerVersionNode : public CompilerVersionNode
-{
- CxxCompilerVersionNode() {}
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *dagChecker) const
- {
- if (!context->HeadTarget)
- {
- reportError(context, content->GetOriginalExpression(),
- "$<CXX_COMPILER_VERSION> may only be used with binary targets. It "
- "may not be used with add_custom_command or add_custom_target.");
- return std::string();
- }
- return this->EvaluateWithLanguage(parameters, context, content,
- dagChecker, "CXX");
- }
-} cxxCompilerVersionNode;
-
-
-//----------------------------------------------------------------------------
-struct PlatformIdNode : public cmGeneratorExpressionNode
-{
- PlatformIdNode() {}
-
- virtual int NumExpectedParameters() const { return OneOrZeroParameters; }
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- const char *platformId =
- context->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME");
- if (parameters.empty())
- {
- return platformId ? platformId : "";
- }
-
- if (!platformId)
- {
- return parameters.front().empty() ? "1" : "0";
- }
-
- if (strcmp(parameters.begin()->c_str(), platformId) == 0)
- {
- return "1";
- }
- return "0";
- }
-} platformIdNode;
-
-//----------------------------------------------------------------------------
-static const struct VersionGreaterNode : public cmGeneratorExpressionNode
-{
- VersionGreaterNode() {}
-
- virtual int NumExpectedParameters() const { return 2; }
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER,
- parameters.front().c_str(),
- parameters[1].c_str()) ? "1" : "0";
- }
-} versionGreaterNode;
-
-//----------------------------------------------------------------------------
-static const struct VersionLessNode : public cmGeneratorExpressionNode
-{
- VersionLessNode() {}
-
- virtual int NumExpectedParameters() const { return 2; }
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- return cmSystemTools::VersionCompare(cmSystemTools::OP_LESS,
- parameters.front().c_str(),
- parameters[1].c_str()) ? "1" : "0";
- }
-} versionLessNode;
-
-//----------------------------------------------------------------------------
-static const struct VersionEqualNode : public cmGeneratorExpressionNode
-{
- VersionEqualNode() {}
-
- virtual int NumExpectedParameters() const { return 2; }
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
- parameters.front().c_str(),
- parameters[1].c_str()) ? "1" : "0";
- }
-} versionEqualNode;
-
-//----------------------------------------------------------------------------
-static const struct LinkOnlyNode : public cmGeneratorExpressionNode
-{
- LinkOnlyNode() {}
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *dagChecker) const
- {
- if(!dagChecker->GetTransitivePropertiesOnly())
- {
- return parameters.front();
- }
- return "";
- }
-} linkOnlyNode;
-
-//----------------------------------------------------------------------------
-static const struct ConfigurationNode : public cmGeneratorExpressionNode
-{
- ConfigurationNode() {}
-
- virtual int NumExpectedParameters() const { return 0; }
-
- std::string Evaluate(const std::vector<std::string> &,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- context->HadContextSensitiveCondition = true;
- return context->Config;
- }
-} configurationNode;
-
-//----------------------------------------------------------------------------
-static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
-{
- ConfigurationTestNode() {}
-
- virtual int NumExpectedParameters() const { return OneOrZeroParameters; }
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *) const
- {
- if (parameters.empty())
- {
- return configurationNode.Evaluate(parameters, context, content, 0);
- }
- static cmsys::RegularExpression configValidator("^[A-Za-z0-9_]*$");
- if (!configValidator.find(*parameters.begin()))
- {
- reportError(context, content->GetOriginalExpression(),
- "Expression syntax not recognized.");
- return std::string();
- }
- context->HadContextSensitiveCondition = true;
- if (context->Config.empty())
- {
- return parameters.front().empty() ? "1" : "0";
- }
-
- if (cmsysString_strcasecmp(parameters.begin()->c_str(),
- context->Config.c_str()) == 0)
- {
- return "1";
- }
-
- if (context->CurrentTarget
- && context->CurrentTarget->IsImported())
- {
- const char* loc = 0;
- const char* imp = 0;
- std::string suffix;
- if (context->CurrentTarget->GetMappedConfig(context->Config,
- &loc,
- &imp,
- suffix))
- {
- // This imported target has an appropriate location
- // for this (possibly mapped) config.
- // Check if there is a proper config mapping for the tested config.
- std::vector<std::string> mappedConfigs;
- std::string mapProp = "MAP_IMPORTED_CONFIG_";
- mapProp += cmSystemTools::UpperCase(context->Config);
- if(const char* mapValue =
- context->CurrentTarget->GetProperty(mapProp))
- {
- cmSystemTools::ExpandListArgument(cmSystemTools::UpperCase(mapValue),
- mappedConfigs);
- return std::find(mappedConfigs.begin(), mappedConfigs.end(),
- cmSystemTools::UpperCase(parameters.front()))
- != mappedConfigs.end() ? "1" : "0";
- }
- }
- }
- return "0";
- }
-} configurationTestNode;
-
-static const struct JoinNode : public cmGeneratorExpressionNode
-{
- JoinNode() {}
-
- virtual int NumExpectedParameters() const { return 2; }
-
- virtual bool AcceptsArbitraryContentParameter() const { return true; }
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- std::vector<std::string> list;
- cmSystemTools::ExpandListArgument(parameters.front(), list);
- return cmJoin(list, parameters[1]);
- }
-} joinNode;
-
-#define TRANSITIVE_PROPERTY_NAME(PROPERTY) \
- , "INTERFACE_" #PROPERTY
-
-//----------------------------------------------------------------------------
-static const char* targetPropertyTransitiveWhitelist[] = {
- 0
- CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(TRANSITIVE_PROPERTY_NAME)
-};
-
-#undef TRANSITIVE_PROPERTY_NAME
-
-template <typename T>
-std::string
-getLinkedTargetsContent(
- std::vector<T> const &libraries,
- cmTarget const* target,
- cmTarget const* headTarget,
- cmGeneratorExpressionContext *context,
- cmGeneratorExpressionDAGChecker *dagChecker,
- const std::string &interfacePropertyName)
-{
- std::string linkedTargetsContent;
- std::string sep;
- std::string depString;
- for (typename std::vector<T>::const_iterator it = libraries.begin();
- it != libraries.end(); ++it)
- {
- // Broken code can have a target in its own link interface.
- // Don't follow such link interface entries so as not to create a
- // self-referencing loop.
- if (it->Target && it->Target != target)
- {
- depString +=
- sep + "$<TARGET_PROPERTY:" +
- it->Target->GetName() + "," + interfacePropertyName + ">";
- sep = ";";
- }
- }
- if(!depString.empty())
- {
- linkedTargetsContent =
- cmGeneratorExpressionNode::EvaluateDependentExpression(depString,
- target->GetMakefile(), context,
- headTarget, target, dagChecker);
- }
- linkedTargetsContent =
- cmGeneratorExpression::StripEmptyListElements(linkedTargetsContent);
- return linkedTargetsContent;
-}
-
-//----------------------------------------------------------------------------
-static const struct TargetPropertyNode : public cmGeneratorExpressionNode
-{
- TargetPropertyNode() {}
-
- // This node handles errors on parameter count itself.
- virtual int NumExpectedParameters() const { return OneOrMoreParameters; }
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *dagCheckerParent
- ) const
- {
- if (parameters.size() != 1 && parameters.size() != 2)
- {
- reportError(context, content->GetOriginalExpression(),
- "$<TARGET_PROPERTY:...> expression requires one or two parameters");
- return std::string();
- }
- static cmsys::RegularExpression propertyNameValidator("^[A-Za-z0-9_]+$");
-
- cmTarget const* target = context->HeadTarget;
- std::string propertyName = *parameters.begin();
-
- if (parameters.size() == 1)
- {
- context->HadHeadSensitiveCondition = true;
- }
- if (!target && parameters.size() == 1)
- {
- reportError(context, content->GetOriginalExpression(),
- "$<TARGET_PROPERTY:prop> may only be used with binary targets. "
- "It may not be used with add_custom_command or add_custom_target. "
- "Specify the target to read a property from using the "
- "$<TARGET_PROPERTY:tgt,prop> signature instead.");
- return std::string();
- }
-
- if (parameters.size() == 2)
- {
- if (parameters.begin()->empty() && parameters[1].empty())
- {
- reportError(context, content->GetOriginalExpression(),
- "$<TARGET_PROPERTY:tgt,prop> expression requires a non-empty "
- "target name and property name.");
- return std::string();
- }
- if (parameters.begin()->empty())
- {
- reportError(context, content->GetOriginalExpression(),
- "$<TARGET_PROPERTY:tgt,prop> expression requires a non-empty "
- "target name.");
- return std::string();
- }
-
- std::string targetName = parameters.front();
- propertyName = parameters[1];
- if (!cmGeneratorExpression::IsValidTargetName(targetName))
- {
- if (!propertyNameValidator.find(propertyName.c_str()))
- {
- ::reportError(context, content->GetOriginalExpression(),
- "Target name and property name not supported.");
- return std::string();
- }
- ::reportError(context, content->GetOriginalExpression(),
- "Target name not supported.");
- return std::string();
- }
- if(propertyName == "ALIASED_TARGET")
- {
- if(context->Makefile->IsAlias(targetName))
- {
- if(cmTarget* tgt = context->Makefile->FindTargetToUse(targetName))
- {
- return tgt->GetName();
- }
- }
- return "";
- }
- target = context->Makefile->FindTargetToUse(targetName);
-
- if (!target)
- {
- std::ostringstream e;
- e << "Target \""
- << targetName
- << "\" not found.";
- reportError(context, content->GetOriginalExpression(), e.str());
- return std::string();
- }
- context->AllTargets.insert(target);
- }
-
- if (target == context->HeadTarget)
- {
- // Keep track of the properties seen while processing.
- // The evaluation of the LINK_LIBRARIES generator expressions
- // will check this to ensure that properties have one consistent
- // value for all evaluations.
- context->SeenTargetProperties.insert(propertyName);
- }
- if (propertyName == "SOURCES")
- {
- context->SourceSensitiveTargets.insert(target);
- }
-
- if (propertyName.empty())
- {
- reportError(context, content->GetOriginalExpression(),
- "$<TARGET_PROPERTY:...> expression requires a non-empty property "
- "name.");
- return std::string();
- }
-
- if (!propertyNameValidator.find(propertyName))
- {
- ::reportError(context, content->GetOriginalExpression(),
- "Property name not supported.");
- return std::string();
- }
-
- assert(target);
-
- if (propertyName == "LINKER_LANGUAGE")
- {
- if (target->LinkLanguagePropagatesToDependents() &&
- dagCheckerParent && (dagCheckerParent->EvaluatingLinkLibraries()
- || dagCheckerParent->EvaluatingSources()))
- {
- reportError(context, content->GetOriginalExpression(),
- "LINKER_LANGUAGE target property can not be used while evaluating "
- "link libraries for a static library");
- return std::string();
- }
- return target->GetLinkerLanguage(context->Config);
- }
-
- cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace,
- target->GetName(),
- propertyName,
- content,
- dagCheckerParent);
-
- switch (dagChecker.Check())
- {
- case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
- dagChecker.ReportError(context, content->GetOriginalExpression());
- return std::string();
- case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE:
- // No error. We just skip cyclic references.
- return std::string();
- case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
- for (size_t i = 1;
- i < cmArraySize(targetPropertyTransitiveWhitelist);
- ++i)
- {
- if (targetPropertyTransitiveWhitelist[i] == propertyName)
- {
- // No error. We're not going to find anything new here.
- return std::string();
- }
- }
- case cmGeneratorExpressionDAGChecker::DAG:
- break;
- }
-
- const char *prop = target->GetProperty(propertyName);
-
- if (dagCheckerParent)
- {
- if (dagCheckerParent->EvaluatingLinkLibraries())
- {
-#define TRANSITIVE_PROPERTY_COMPARE(PROPERTY) \
- (#PROPERTY == propertyName || "INTERFACE_" #PROPERTY == propertyName) ||
- if (CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(TRANSITIVE_PROPERTY_COMPARE)
- false)
- {
- reportError(context, content->GetOriginalExpression(),
- "$<TARGET_PROPERTY:...> expression in link libraries "
- "evaluation depends on target property which is transitive "
- "over the link libraries, creating a recursion.");
- return std::string();
- }
-#undef TRANSITIVE_PROPERTY_COMPARE
-
- if(!prop)
- {
- return std::string();
- }
- }
- else
- {
-#define ASSERT_TRANSITIVE_PROPERTY_METHOD(METHOD) \
- dagCheckerParent->METHOD () ||
-
- assert(
- CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(
- ASSERT_TRANSITIVE_PROPERTY_METHOD)
- false);
-#undef ASSERT_TRANSITIVE_PROPERTY_METHOD
- }
- }
-
- std::string linkedTargetsContent;
-
- std::string interfacePropertyName;
- bool isInterfaceProperty = false;
-
-#define POPULATE_INTERFACE_PROPERTY_NAME(prop) \
- if (propertyName == #prop) \
- { \
- interfacePropertyName = "INTERFACE_" #prop; \
- } \
- else if (propertyName == "INTERFACE_" #prop) \
- { \
- interfacePropertyName = "INTERFACE_" #prop; \
- isInterfaceProperty = true; \
- } \
- else
-
- CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(POPULATE_INTERFACE_PROPERTY_NAME)
- // Note that the above macro terminates with an else
- /* else */ if (cmHasLiteralPrefix(propertyName.c_str(),
- "COMPILE_DEFINITIONS_"))
- {
- cmPolicies::PolicyStatus polSt =
- context->Makefile->GetPolicyStatus(cmPolicies::CMP0043);
- if (polSt == cmPolicies::WARN || polSt == cmPolicies::OLD)
- {
- interfacePropertyName = "INTERFACE_COMPILE_DEFINITIONS";
- }
- }
-#undef POPULATE_INTERFACE_PROPERTY_NAME
- cmTarget const* headTarget = context->HeadTarget && isInterfaceProperty
- ? context->HeadTarget : target;
-
- if(isInterfaceProperty)
- {
- if(cmTarget::LinkInterfaceLibraries const* iface =
- target->GetLinkInterfaceLibraries(context->Config, headTarget, true))
- {
- linkedTargetsContent =
- getLinkedTargetsContent(iface->Libraries, target,
- headTarget,
- context, &dagChecker,
- interfacePropertyName);
- }
- }
- else if(!interfacePropertyName.empty())
- {
- if(cmTarget::LinkImplementationLibraries const* impl =
- target->GetLinkImplementationLibraries(context->Config))
- {
- linkedTargetsContent =
- getLinkedTargetsContent(impl->Libraries, target,
- target,
- context, &dagChecker,
- interfacePropertyName);
- }
- }
-
- if (!prop)
- {
- if (target->IsImported()
- || target->GetType() == cmTarget::INTERFACE_LIBRARY)
- {
- return linkedTargetsContent;
- }
- if (target->IsLinkInterfaceDependentBoolProperty(propertyName,
- context->Config))
- {
- context->HadContextSensitiveCondition = true;
- return target->GetLinkInterfaceDependentBoolProperty(
- propertyName,
- context->Config) ? "1" : "0";
- }
- if (target->IsLinkInterfaceDependentStringProperty(propertyName,
- context->Config))
- {
- context->HadContextSensitiveCondition = true;
- const char *propContent =
- target->GetLinkInterfaceDependentStringProperty(
- propertyName,
- context->Config);
- return propContent ? propContent : "";
- }
- if (target->IsLinkInterfaceDependentNumberMinProperty(propertyName,
- context->Config))
- {
- context->HadContextSensitiveCondition = true;
- const char *propContent =
- target->GetLinkInterfaceDependentNumberMinProperty(
- propertyName,
- context->Config);
- return propContent ? propContent : "";
- }
- if (target->IsLinkInterfaceDependentNumberMaxProperty(propertyName,
- context->Config))
- {
- context->HadContextSensitiveCondition = true;
- const char *propContent =
- target->GetLinkInterfaceDependentNumberMaxProperty(
- propertyName,
- context->Config);
- return propContent ? propContent : "";
- }
-
- return linkedTargetsContent;
- }
-
- if (!target->IsImported()
- && dagCheckerParent && !dagCheckerParent->EvaluatingLinkLibraries())
- {
- if (target->IsLinkInterfaceDependentNumberMinProperty(propertyName,
- context->Config))
- {
- context->HadContextSensitiveCondition = true;
- const char *propContent =
- target->GetLinkInterfaceDependentNumberMinProperty(
- propertyName,
- context->Config);
- return propContent ? propContent : "";
- }
- if (target->IsLinkInterfaceDependentNumberMaxProperty(propertyName,
- context->Config))
- {
- context->HadContextSensitiveCondition = true;
- const char *propContent =
- target->GetLinkInterfaceDependentNumberMaxProperty(
- propertyName,
- context->Config);
- return propContent ? propContent : "";
- }
- }
- if(!interfacePropertyName.empty())
- {
- std::string result = this->EvaluateDependentExpression(prop,
- context->Makefile, context,
- headTarget, target, &dagChecker);
- if (!linkedTargetsContent.empty())
- {
- result += (result.empty() ? "" : ";") + linkedTargetsContent;
- }
- return result;
- }
- return prop;
- }
-} targetPropertyNode;
-
-//----------------------------------------------------------------------------
-static const struct TargetNameNode : public cmGeneratorExpressionNode
-{
- TargetNameNode() {}
-
- virtual bool GeneratesContent() const { return true; }
-
- virtual bool AcceptsArbitraryContentParameter() const { return true; }
- virtual bool RequiresLiteralInput() const { return true; }
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *,
- cmGeneratorExpressionDAGChecker *) const
- {
- return parameters.front();
- }
-
- virtual int NumExpectedParameters() const { return 1; }
-
-} targetNameNode;
-
-//----------------------------------------------------------------------------
-static const struct TargetObjectsNode : public cmGeneratorExpressionNode
-{
- TargetObjectsNode() {}
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *) const
- {
- if (!context->EvaluateForBuildsystem)
- {
- std::ostringstream e;
- e << "The evaluation of the TARGET_OBJECTS generator expression "
- "is only suitable for consumption by CMake. It is not suitable "
- "for writing out elsewhere.";
- reportError(context, content->GetOriginalExpression(), e.str());
- return std::string();
- }
-
- std::string tgtName = parameters.front();
- cmGeneratorTarget* gt =
- context->Makefile->FindGeneratorTargetToUse(tgtName);
- if (!gt)
- {
- std::ostringstream e;
- e << "Objects of target \"" << tgtName
- << "\" referenced but no such target exists.";
- reportError(context, content->GetOriginalExpression(), e.str());
- return std::string();
- }
- if (gt->GetType() != cmTarget::OBJECT_LIBRARY)
- {
- std::ostringstream e;
- e << "Objects of target \"" << tgtName
- << "\" referenced but is not an OBJECT library.";
- reportError(context, content->GetOriginalExpression(), e.str());
- return std::string();
- }
-
- std::vector<cmSourceFile const*> objectSources;
- gt->GetObjectSources(objectSources, context->Config);
- std::map<cmSourceFile const*, std::string> mapping;
-
- for(std::vector<cmSourceFile const*>::const_iterator it
- = objectSources.begin(); it != objectSources.end(); ++it)
- {
- mapping[*it];
- }
-
- gt->LocalGenerator->ComputeObjectFilenames(mapping, gt);
-
- std::string obj_dir = gt->ObjectDirectory;
- std::string result;
- const char* sep = "";
- for(std::vector<cmSourceFile const*>::const_iterator it
- = objectSources.begin(); it != objectSources.end(); ++it)
- {
- // Find the object file name corresponding to this source file.
- std::map<cmSourceFile const*, std::string>::const_iterator
- map_it = mapping.find(*it);
- // It must exist because we populated the mapping just above.
- assert(!map_it->second.empty());
- result += sep;
- std::string objFile = obj_dir + map_it->second;
- cmSourceFile* sf = context->Makefile->GetOrCreateSource(objFile, true);
- sf->SetObjectLibrary(tgtName);
- sf->SetProperty("EXTERNAL_OBJECT", "1");
- result += objFile;
- sep = ";";
- }
- return result;
- }
-} targetObjectsNode;
-
-//----------------------------------------------------------------------------
-static const struct CompileFeaturesNode : public cmGeneratorExpressionNode
-{
- CompileFeaturesNode() {}
-
- virtual int NumExpectedParameters() const { return OneOrMoreParameters; }
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *dagChecker) const
- {
- cmTarget const* target = context->HeadTarget;
- if (!target)
- {
- reportError(context, content->GetOriginalExpression(),
- "$<COMPILE_FEATURE> may only be used with binary targets. It may "
- "not be used with add_custom_command or add_custom_target.");
- return std::string();
- }
- context->HadHeadSensitiveCondition = true;
-
- typedef std::map<std::string, std::vector<std::string> > LangMap;
- static LangMap availableFeatures;
-
- LangMap testedFeatures;
-
- for (std::vector<std::string>::const_iterator it = parameters.begin();
- it != parameters.end(); ++it)
- {
- std::string error;
- std::string lang;
- if (!context->Makefile->CompileFeatureKnown(context->HeadTarget,
- *it, lang, &error))
- {
- reportError(context, content->GetOriginalExpression(), error);
- return std::string();
- }
- testedFeatures[lang].push_back(*it);
-
- if (availableFeatures.find(lang) == availableFeatures.end())
- {
- const char* featuresKnown
- = context->Makefile->CompileFeaturesAvailable(lang, &error);
- if (!featuresKnown)
- {
- reportError(context, content->GetOriginalExpression(), error);
- return std::string();
- }
- cmSystemTools::ExpandListArgument(featuresKnown,
- availableFeatures[lang]);
- }
- }
-
- bool evalLL = dagChecker && dagChecker->EvaluatingLinkLibraries();
-
- std::string result;
-
- for (LangMap::const_iterator lit = testedFeatures.begin();
- lit != testedFeatures.end(); ++lit)
- {
- std::vector<std::string> const& langAvailable
- = availableFeatures[lit->first];
- const char* standardDefault = context->Makefile
- ->GetDefinition("CMAKE_" + lit->first + "_STANDARD_DEFAULT");
- for (std::vector<std::string>::const_iterator it = lit->second.begin();
- it != lit->second.end(); ++it)
- {
- if (std::find(langAvailable.begin(), langAvailable.end(), *it)
- == langAvailable.end())
- {
- return "0";
- }
- if (standardDefault && !*standardDefault)
- {
- // This compiler has no notion of language standard levels.
- // All features known for the language are always available.
- continue;
- }
- if (!context->Makefile->HaveStandardAvailable(target,
- lit->first, *it))
- {
- if (evalLL)
- {
- const char* l = target->GetProperty(lit->first + "_STANDARD");
- if (!l)
- {
- l = standardDefault;
- }
- assert(l);
- context->MaxLanguageStandard[target][lit->first] = l;
- }
- else
- {
- return "0";
- }
- }
- }
- }
- return "1";
- }
-} compileFeaturesNode;
-
-//----------------------------------------------------------------------------
-static const char* targetPolicyWhitelist[] = {
- 0
-#define TARGET_POLICY_STRING(POLICY) \
- , #POLICY
-
- CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_STRING)
-
-#undef TARGET_POLICY_STRING
-};
-
-cmPolicies::PolicyStatus statusForTarget(cmTarget const* tgt,
- const char *policy)
-{
-#define RETURN_POLICY(POLICY) \
- if (strcmp(policy, #POLICY) == 0) \
- { \
- return tgt->GetPolicyStatus ## POLICY (); \
- } \
-
- CM_FOR_EACH_TARGET_POLICY(RETURN_POLICY)
-
-#undef RETURN_POLICY
-
- assert(0 && "Unreachable code. Not a valid policy");
- return cmPolicies::WARN;
-}
-
-cmPolicies::PolicyID policyForString(const char *policy_id)
-{
-#define RETURN_POLICY_ID(POLICY_ID) \
- if (strcmp(policy_id, #POLICY_ID) == 0) \
- { \
- return cmPolicies:: POLICY_ID; \
- } \
-
- CM_FOR_EACH_TARGET_POLICY(RETURN_POLICY_ID)
-
-#undef RETURN_POLICY_ID
-
- assert(0 && "Unreachable code. Not a valid policy");
- return cmPolicies::CMP0002;
-}
-
-//----------------------------------------------------------------------------
-static const struct TargetPolicyNode : public cmGeneratorExpressionNode
-{
- TargetPolicyNode() {}
-
- virtual int NumExpectedParameters() const { return 1; }
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *context ,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *) const
- {
- if (!context->HeadTarget)
- {
- reportError(context, content->GetOriginalExpression(),
- "$<TARGET_POLICY:prop> may only be used with binary targets. It "
- "may not be used with add_custom_command or add_custom_target.");
- return std::string();
- }
-
- context->HadContextSensitiveCondition = true;
- context->HadHeadSensitiveCondition = true;
-
- for (size_t i = 1; i < cmArraySize(targetPolicyWhitelist); ++i)
- {
- const char *policy = targetPolicyWhitelist[i];
- if (parameters.front() == policy)
- {
- cmMakefile *mf = context->HeadTarget->GetMakefile();
- switch(statusForTarget(context->HeadTarget, policy))
- {
- case cmPolicies::WARN:
- mf->IssueMessage(cmake::AUTHOR_WARNING,
- mf->GetPolicies()->
- GetPolicyWarning(policyForString(policy)));
- case cmPolicies::REQUIRED_IF_USED:
- case cmPolicies::REQUIRED_ALWAYS:
- case cmPolicies::OLD:
- return "0";
- case cmPolicies::NEW:
- return "1";
- }
- }
- }
- reportError(context, content->GetOriginalExpression(),
- "$<TARGET_POLICY:prop> may only be used with a limited number of "
- "policies. Currently it may be used with the following policies:\n"
-
-#define STRINGIFY_HELPER(X) #X
-#define STRINGIFY(X) STRINGIFY_HELPER(X)
-
-#define TARGET_POLICY_LIST_ITEM(POLICY) \
- " * " STRINGIFY(POLICY) "\n"
-
- CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_LIST_ITEM)
-
-#undef TARGET_POLICY_LIST_ITEM
- );
- return std::string();
- }
-
-} targetPolicyNode;
-
-//----------------------------------------------------------------------------
-static const struct InstallPrefixNode : public cmGeneratorExpressionNode
-{
- InstallPrefixNode() {}
-
- virtual bool GeneratesContent() const { return true; }
- virtual int NumExpectedParameters() const { return 0; }
-
- std::string Evaluate(const std::vector<std::string> &,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *) const
- {
- reportError(context, content->GetOriginalExpression(),
- "INSTALL_PREFIX is a marker for install(EXPORT) only. It "
- "should never be evaluated.");
- return std::string();
- }
-
-} installPrefixNode;
-
-//----------------------------------------------------------------------------
-class ArtifactNameTag;
-class ArtifactLinkerTag;
-class ArtifactSonameTag;
-class ArtifactPdbTag;
-
-class ArtifactPathTag;
-class ArtifactDirTag;
-class ArtifactNameTag;
-
-//----------------------------------------------------------------------------
-template<typename ArtifactT>
-struct TargetFilesystemArtifactResultCreator
-{
- static std::string Create(cmTarget* target,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content);
-};
-
-//----------------------------------------------------------------------------
-template<>
-struct TargetFilesystemArtifactResultCreator<ArtifactSonameTag>
-{
- static std::string Create(cmTarget* target,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content)
- {
- // The target soname file (.so.1).
- if(target->IsDLLPlatform())
- {
- ::reportError(context, content->GetOriginalExpression(),
- "TARGET_SONAME_FILE is not allowed "
- "for DLL target platforms.");
- return std::string();
- }
- if(target->GetType() != cmTarget::SHARED_LIBRARY)
- {
- ::reportError(context, content->GetOriginalExpression(),
- "TARGET_SONAME_FILE is allowed only for "
- "SHARED libraries.");
- return std::string();
- }
- std::string result = target->GetDirectory(context->Config);
- result += "/";
- result += target->GetSOName(context->Config);
- return result;
- }
-};
-
-//----------------------------------------------------------------------------
-template<>
-struct TargetFilesystemArtifactResultCreator<ArtifactPdbTag>
-{
- static std::string Create(cmTarget* target,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content)
- {
- std::string language = target->GetLinkerLanguage(context->Config);
-
- std::string pdbSupportVar = "CMAKE_" + language + "_LINKER_SUPPORTS_PDB";
-
- if(!context->Makefile->IsOn(pdbSupportVar))
- {
- ::reportError(context, content->GetOriginalExpression(),
- "TARGET_PDB_FILE is not supported by the target linker.");
- return std::string();
- }
-
- cmTarget::TargetType targetType = target->GetType();
-
- if(targetType != cmTarget::SHARED_LIBRARY &&
- targetType != cmTarget::MODULE_LIBRARY &&
- targetType != cmTarget::EXECUTABLE)
- {
- ::reportError(context, content->GetOriginalExpression(),
- "TARGET_PDB_FILE is allowed only for "
- "targets with linker created artifacts.");
- return std::string();
- }
-
- std::string result = target->GetPDBDirectory(context->Config);
- result += "/";
- result += target->GetPDBName(context->Config);
- return result;
- }
-};
-
-//----------------------------------------------------------------------------
-template<>
-struct TargetFilesystemArtifactResultCreator<ArtifactLinkerTag>
-{
- static std::string Create(cmTarget* target,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content)
- {
- // The file used to link to the target (.so, .lib, .a).
- if(!target->IsLinkable())
- {
- ::reportError(context, content->GetOriginalExpression(),
- "TARGET_LINKER_FILE is allowed only for libraries and "
- "executables with ENABLE_EXPORTS.");
- return std::string();
- }
- return target->GetFullPath(context->Config,
- target->HasImportLibrary());
- }
-};
-
-//----------------------------------------------------------------------------
-template<>
-struct TargetFilesystemArtifactResultCreator<ArtifactNameTag>
-{
- static std::string Create(cmTarget* target,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *)
- {
- return target->GetFullPath(context->Config, false, true);
- }
-};
-
-
-//----------------------------------------------------------------------------
-template<typename ArtifactT>
-struct TargetFilesystemArtifactResultGetter
-{
- static std::string Get(const std::string &result);
-};
-
-//----------------------------------------------------------------------------
-template<>
-struct TargetFilesystemArtifactResultGetter<ArtifactNameTag>
-{
- static std::string Get(const std::string &result)
- { return cmSystemTools::GetFilenameName(result); }
-};
-
-//----------------------------------------------------------------------------
-template<>
-struct TargetFilesystemArtifactResultGetter<ArtifactDirTag>
-{
- static std::string Get(const std::string &result)
- { return cmSystemTools::GetFilenamePath(result); }
-};
-
-//----------------------------------------------------------------------------
-template<>
-struct TargetFilesystemArtifactResultGetter<ArtifactPathTag>
-{
- static std::string Get(const std::string &result)
- { return result; }
-};
-
-//----------------------------------------------------------------------------
-template<typename ArtifactT, typename ComponentT>
-struct TargetFilesystemArtifact : public cmGeneratorExpressionNode
-{
- TargetFilesystemArtifact() {}
-
- virtual int NumExpectedParameters() const { return 1; }
-
- std::string Evaluate(const std::vector<std::string> &parameters,
- cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content,
- cmGeneratorExpressionDAGChecker *dagChecker) const
- {
- // Lookup the referenced target.
- std::string name = *parameters.begin();
-
- if (!cmGeneratorExpression::IsValidTargetName(name))
- {
- ::reportError(context, content->GetOriginalExpression(),
- "Expression syntax not recognized.");
- return std::string();
- }
- cmTarget* target = context->Makefile->FindTargetToUse(name);
- if(!target)
- {
- ::reportError(context, content->GetOriginalExpression(),
- "No target \"" + name + "\"");
- return std::string();
- }
- if(target->GetType() >= cmTarget::OBJECT_LIBRARY &&
- target->GetType() != cmTarget::UNKNOWN_LIBRARY)
- {
- ::reportError(context, content->GetOriginalExpression(),
- "Target \"" + name + "\" is not an executable or library.");
- return std::string();
- }
- if (dagChecker && (dagChecker->EvaluatingLinkLibraries(name.c_str())
- || (dagChecker->EvaluatingSources()
- && name == dagChecker->TopTarget())))
- {
- ::reportError(context, content->GetOriginalExpression(),
- "Expressions which require the linker language may not "
- "be used while evaluating link libraries");
- return std::string();
- }
- context->DependTargets.insert(target);
- context->AllTargets.insert(target);
-
- std::string result =
- TargetFilesystemArtifactResultCreator<ArtifactT>::Create(
- target,
- context,
- content);
- if (context->HadError)
- {
- return std::string();
- }
- return
- TargetFilesystemArtifactResultGetter<ComponentT>::Get(result);
- }
-};
-
-//----------------------------------------------------------------------------
-template<typename ArtifactT>
-struct TargetFilesystemArtifactNodeGroup
-{
- TargetFilesystemArtifactNodeGroup()
- {
- }
-
- TargetFilesystemArtifact<ArtifactT, ArtifactPathTag> File;
- TargetFilesystemArtifact<ArtifactT, ArtifactNameTag> FileName;
- TargetFilesystemArtifact<ArtifactT, ArtifactDirTag> FileDir;
-};
-
-//----------------------------------------------------------------------------
-static const
-TargetFilesystemArtifactNodeGroup<ArtifactNameTag> targetNodeGroup;
-
-static const
-TargetFilesystemArtifactNodeGroup<ArtifactLinkerTag> targetLinkerNodeGroup;
-
-static const
-TargetFilesystemArtifactNodeGroup<ArtifactSonameTag> targetSoNameNodeGroup;
-
-static const
-TargetFilesystemArtifactNodeGroup<ArtifactPdbTag> targetPdbNodeGroup;
-
-//----------------------------------------------------------------------------
-static const
-cmGeneratorExpressionNode* GetNode(const std::string &identifier)
-{
- typedef std::map<std::string, const cmGeneratorExpressionNode*> NodeMap;
- static NodeMap nodeMap;
- if (nodeMap.empty())
- {
- nodeMap["0"] = &zeroNode;
- nodeMap["1"] = &oneNode;
- nodeMap["AND"] = &andNode;
- nodeMap["OR"] = &orNode;
- nodeMap["NOT"] = &notNode;
- nodeMap["C_COMPILER_ID"] = &cCompilerIdNode;
- nodeMap["CXX_COMPILER_ID"] = &cxxCompilerIdNode;
- nodeMap["VERSION_GREATER"] = &versionGreaterNode;
- nodeMap["VERSION_LESS"] = &versionLessNode;
- nodeMap["VERSION_EQUAL"] = &versionEqualNode;
- nodeMap["C_COMPILER_VERSION"] = &cCompilerVersionNode;
- nodeMap["CXX_COMPILER_VERSION"] = &cxxCompilerVersionNode;
- nodeMap["PLATFORM_ID"] = &platformIdNode;
- nodeMap["COMPILE_FEATURES"] = &compileFeaturesNode;
- nodeMap["CONFIGURATION"] = &configurationNode;
- nodeMap["CONFIG"] = &configurationTestNode;
- nodeMap["TARGET_FILE"] = &targetNodeGroup.File;
- nodeMap["TARGET_LINKER_FILE"] = &targetLinkerNodeGroup.File;
- nodeMap["TARGET_SONAME_FILE"] = &targetSoNameNodeGroup.File;
- nodeMap["TARGET_PDB_FILE"] = &targetPdbNodeGroup.File;
- nodeMap["TARGET_FILE_NAME"] = &targetNodeGroup.FileName;
- nodeMap["TARGET_LINKER_FILE_NAME"] = &targetLinkerNodeGroup.FileName;
- nodeMap["TARGET_SONAME_FILE_NAME"] = &targetSoNameNodeGroup.FileName;
- nodeMap["TARGET_PDB_FILE_NAME"] = &targetPdbNodeGroup.FileName;
- nodeMap["TARGET_FILE_DIR"] = &targetNodeGroup.FileDir;
- nodeMap["TARGET_LINKER_FILE_DIR"] = &targetLinkerNodeGroup.FileDir;
- nodeMap["TARGET_SONAME_FILE_DIR"] = &targetSoNameNodeGroup.FileDir;
- nodeMap["TARGET_PDB_FILE_DIR"] = &targetPdbNodeGroup.FileDir;
- nodeMap["STREQUAL"] = &strEqualNode;
- nodeMap["EQUAL"] = &equalNode;
- nodeMap["LOWER_CASE"] = &lowerCaseNode;
- nodeMap["UPPER_CASE"] = &upperCaseNode;
- nodeMap["MAKE_C_IDENTIFIER"] = &makeCIdentifierNode;
- nodeMap["BOOL"] = &boolNode;
- nodeMap["ANGLE-R"] = &angle_rNode;
- nodeMap["COMMA"] = &commaNode;
- nodeMap["SEMICOLON"] = &semicolonNode;
- nodeMap["TARGET_PROPERTY"] = &targetPropertyNode;
- nodeMap["TARGET_NAME"] = &targetNameNode;
- nodeMap["TARGET_OBJECTS"] = &targetObjectsNode;
- nodeMap["TARGET_POLICY"] = &targetPolicyNode;
- nodeMap["BUILD_INTERFACE"] = &buildInterfaceNode;
- nodeMap["INSTALL_INTERFACE"] = &installInterfaceNode;
- nodeMap["INSTALL_PREFIX"] = &installPrefixNode;
- nodeMap["JOIN"] = &joinNode;
- nodeMap["LINK_ONLY"] = &linkOnlyNode;
- }
- NodeMap::const_iterator i = nodeMap.find(identifier);
- if (i == nodeMap.end())
- {
- return 0;
- }
- return i->second;
-
-}
+#include "cmGeneratorExpressionNode.h"
//----------------------------------------------------------------------------
GeneratorExpressionContent::GeneratorExpressionContent(
@@ -1926,7 +114,8 @@ std::string GeneratorExpressionContent::Evaluate(
}
}
- const cmGeneratorExpressionNode *node = GetNode(identifier);
+ const cmGeneratorExpressionNode *node =
+ cmGeneratorExpressionNode::GetNode(identifier);
if (!node)
{
diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h
index 0bf1797..7c1bd8c 100644
--- a/Source/cmGeneratorExpressionEvaluator.h
+++ b/Source/cmGeneratorExpressionEvaluator.h
@@ -16,36 +16,10 @@
#include <string>
#include "cmListFileCache.h"
+#include "cmGeneratorExpressionContext.h"
class cmTarget;
-//----------------------------------------------------------------------------
-struct cmGeneratorExpressionContext
-{
- cmGeneratorExpressionContext()
- : Backtrace(NULL)
- {
- }
-
- cmListFileBacktrace Backtrace;
- std::set<cmTarget*> DependTargets;
- std::set<cmTarget const*> AllTargets;
- std::set<std::string> SeenTargetProperties;
- std::set<cmTarget const*> SourceSensitiveTargets;
- std::map<cmTarget const*, std::map<std::string, std::string> >
- MaxLanguageStandard;
- cmMakefile *Makefile;
- std::string Config;
- cmTarget const* HeadTarget; // The target whose property is being evaluated.
- cmTarget const* CurrentTarget; // The dependent of HeadTarget which appears
- // directly or indirectly in the property.
- bool Quiet;
- bool HadError;
- bool HadContextSensitiveCondition;
- bool HadHeadSensitiveCondition;
- bool EvaluateForBuildsystem;
-};
-
struct cmGeneratorExpressionDAGChecker;
struct cmGeneratorExpressionNode;
diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx
new file mode 100644
index 0000000..673dcb9
--- /dev/null
+++ b/Source/cmGeneratorExpressionNode.cxx
@@ -0,0 +1,1870 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2012 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 "cmGeneratorExpressionNode.h"
+#include "cmGlobalGenerator.h"
+#include "cmAlgorithms.h"
+
+//----------------------------------------------------------------------------
+std::string cmGeneratorExpressionNode::EvaluateDependentExpression(
+ std::string const& prop, cmMakefile *makefile,
+ cmGeneratorExpressionContext *context,
+ cmTarget const* headTarget, cmTarget const* currentTarget,
+ cmGeneratorExpressionDAGChecker *dagChecker)
+{
+ cmGeneratorExpression ge(&context->Backtrace);
+ cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
+ cge->SetEvaluateForBuildsystem(context->EvaluateForBuildsystem);
+ std::string result = cge->Evaluate(makefile,
+ context->Config,
+ context->Quiet,
+ headTarget,
+ currentTarget,
+ dagChecker,
+ context->Language);
+ if (cge->GetHadContextSensitiveCondition())
+ {
+ context->HadContextSensitiveCondition = true;
+ }
+ if (cge->GetHadHeadSensitiveCondition())
+ {
+ context->HadHeadSensitiveCondition = true;
+ }
+ return result;
+}
+
+//----------------------------------------------------------------------------
+static const struct ZeroNode : public cmGeneratorExpressionNode
+{
+ ZeroNode() {}
+
+ virtual bool GeneratesContent() const { return false; }
+
+ virtual bool AcceptsArbitraryContentParameter() const { return true; }
+
+ std::string Evaluate(const std::vector<std::string> &,
+ cmGeneratorExpressionContext *,
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ return std::string();
+ }
+} zeroNode;
+
+//----------------------------------------------------------------------------
+static const struct OneNode : public cmGeneratorExpressionNode
+{
+ OneNode() {}
+
+ virtual bool AcceptsArbitraryContentParameter() const { return true; }
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *,
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ return parameters.front();
+ }
+} oneNode;
+
+//----------------------------------------------------------------------------
+static const struct OneNode buildInterfaceNode;
+
+//----------------------------------------------------------------------------
+static const struct ZeroNode installInterfaceNode;
+
+//----------------------------------------------------------------------------
+#define BOOLEAN_OP_NODE(OPNAME, OP, SUCCESS_VALUE, FAILURE_VALUE) \
+static const struct OP ## Node : public cmGeneratorExpressionNode \
+{ \
+ OP ## Node () {} \
+ virtual int NumExpectedParameters() const { return OneOrMoreParameters; } \
+ \
+ std::string Evaluate(const std::vector<std::string> &parameters, \
+ cmGeneratorExpressionContext *context, \
+ const GeneratorExpressionContent *content, \
+ cmGeneratorExpressionDAGChecker *) const \
+ { \
+ std::vector<std::string>::const_iterator it = parameters.begin(); \
+ const std::vector<std::string>::const_iterator end = parameters.end(); \
+ for ( ; it != end; ++it) \
+ { \
+ if (*it == #FAILURE_VALUE) \
+ { \
+ return #FAILURE_VALUE; \
+ } \
+ else if (*it != #SUCCESS_VALUE) \
+ { \
+ reportError(context, content->GetOriginalExpression(), \
+ "Parameters to $<" #OP "> must resolve to either '0' or '1'."); \
+ return std::string(); \
+ } \
+ } \
+ return #SUCCESS_VALUE; \
+ } \
+} OPNAME;
+
+BOOLEAN_OP_NODE(andNode, AND, 1, 0)
+BOOLEAN_OP_NODE(orNode, OR, 0, 1)
+
+#undef BOOLEAN_OP_NODE
+
+//----------------------------------------------------------------------------
+static const struct NotNode : public cmGeneratorExpressionNode
+{
+ NotNode() {}
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ if (*parameters.begin() != "0" && *parameters.begin() != "1")
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<NOT> parameter must resolve to exactly one '0' or '1' value.");
+ return std::string();
+ }
+ return *parameters.begin() == "0" ? "1" : "0";
+ }
+} notNode;
+
+//----------------------------------------------------------------------------
+static const struct BoolNode : public cmGeneratorExpressionNode
+{
+ BoolNode() {}
+
+ virtual int NumExpectedParameters() const { return 1; }
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *,
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ return !cmSystemTools::IsOff(parameters.begin()->c_str()) ? "1" : "0";
+ }
+} boolNode;
+
+//----------------------------------------------------------------------------
+static const struct StrEqualNode : public cmGeneratorExpressionNode
+{
+ StrEqualNode() {}
+
+ virtual int NumExpectedParameters() const { return 2; }
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *,
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ return *parameters.begin() == parameters[1] ? "1" : "0";
+ }
+} strEqualNode;
+
+//----------------------------------------------------------------------------
+static const struct EqualNode : public cmGeneratorExpressionNode
+{
+ EqualNode() {}
+
+ virtual int NumExpectedParameters() const { return 2; }
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ char *pEnd;
+
+ int base = 0;
+ bool flipSign = false;
+
+ const char *lhs = parameters[0].c_str();
+ if (cmHasLiteralPrefix(lhs, "0b") || cmHasLiteralPrefix(lhs, "0B"))
+ {
+ base = 2;
+ lhs += 2;
+ }
+ if (cmHasLiteralPrefix(lhs, "-0b") || cmHasLiteralPrefix(lhs, "-0B"))
+ {
+ base = 2;
+ lhs += 3;
+ flipSign = true;
+ }
+ if (cmHasLiteralPrefix(lhs, "+0b") || cmHasLiteralPrefix(lhs, "+0B"))
+ {
+ base = 2;
+ lhs += 3;
+ }
+
+ long lnum = strtol(lhs, &pEnd, base);
+ if (pEnd == lhs || *pEnd != '\0' || errno == ERANGE)
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<EQUAL> parameter " + parameters[0] + " is not a valid integer.");
+ return std::string();
+ }
+
+ if (flipSign)
+ {
+ lnum = -lnum;
+ }
+
+ base = 0;
+ flipSign = false;
+
+ const char *rhs = parameters[1].c_str();
+ if (cmHasLiteralPrefix(rhs, "0b") || cmHasLiteralPrefix(rhs, "0B"))
+ {
+ base = 2;
+ rhs += 2;
+ }
+ if (cmHasLiteralPrefix(rhs, "-0b") || cmHasLiteralPrefix(rhs, "-0B"))
+ {
+ base = 2;
+ rhs += 3;
+ flipSign = true;
+ }
+ if (cmHasLiteralPrefix(rhs, "+0b") || cmHasLiteralPrefix(rhs, "+0B"))
+ {
+ base = 2;
+ rhs += 3;
+ }
+
+ long rnum = strtol(rhs, &pEnd, base);
+ if (pEnd == rhs || *pEnd != '\0' || errno == ERANGE)
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<EQUAL> parameter " + parameters[1] + " is not a valid integer.");
+ return std::string();
+ }
+
+ if (flipSign)
+ {
+ rnum = -rnum;
+ }
+
+ return lnum == rnum ? "1" : "0";
+ }
+} equalNode;
+
+//----------------------------------------------------------------------------
+static const struct LowerCaseNode : public cmGeneratorExpressionNode
+{
+ LowerCaseNode() {}
+
+ bool AcceptsArbitraryContentParameter() const { return true; }
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *,
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ return cmSystemTools::LowerCase(parameters.front());
+ }
+} lowerCaseNode;
+
+//----------------------------------------------------------------------------
+static const struct UpperCaseNode : public cmGeneratorExpressionNode
+{
+ UpperCaseNode() {}
+
+ bool AcceptsArbitraryContentParameter() const { return true; }
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *,
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ return cmSystemTools::UpperCase(parameters.front());
+ }
+} upperCaseNode;
+
+//----------------------------------------------------------------------------
+static const struct MakeCIdentifierNode : public cmGeneratorExpressionNode
+{
+ MakeCIdentifierNode() {}
+
+ bool AcceptsArbitraryContentParameter() const { return true; }
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *,
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ return cmSystemTools::MakeCidentifier(parameters.front());
+ }
+} makeCIdentifierNode;
+
+//----------------------------------------------------------------------------
+static const struct Angle_RNode : public cmGeneratorExpressionNode
+{
+ Angle_RNode() {}
+
+ virtual int NumExpectedParameters() const { return 0; }
+
+ std::string Evaluate(const std::vector<std::string> &,
+ cmGeneratorExpressionContext *,
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ return ">";
+ }
+} angle_rNode;
+
+//----------------------------------------------------------------------------
+static const struct CommaNode : public cmGeneratorExpressionNode
+{
+ CommaNode() {}
+
+ virtual int NumExpectedParameters() const { return 0; }
+
+ std::string Evaluate(const std::vector<std::string> &,
+ cmGeneratorExpressionContext *,
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ return ",";
+ }
+} commaNode;
+
+//----------------------------------------------------------------------------
+static const struct SemicolonNode : public cmGeneratorExpressionNode
+{
+ SemicolonNode() {}
+
+ virtual int NumExpectedParameters() const { return 0; }
+
+ std::string Evaluate(const std::vector<std::string> &,
+ cmGeneratorExpressionContext *,
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ return ";";
+ }
+} semicolonNode;
+
+//----------------------------------------------------------------------------
+struct CompilerIdNode : public cmGeneratorExpressionNode
+{
+ CompilerIdNode() {}
+
+ virtual int NumExpectedParameters() const { return OneOrZeroParameters; }
+
+ std::string EvaluateWithLanguage(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *,
+ const std::string &lang) const
+ {
+ const char *compilerId =
+ context->Makefile->GetSafeDefinition("CMAKE_" + lang + "_COMPILER_ID");
+ if (parameters.empty())
+ {
+ return compilerId ? compilerId : "";
+ }
+ static cmsys::RegularExpression compilerIdValidator("^[A-Za-z0-9_]*$");
+ if (!compilerIdValidator.find(*parameters.begin()))
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "Expression syntax not recognized.");
+ return std::string();
+ }
+ if (!compilerId)
+ {
+ return parameters.front().empty() ? "1" : "0";
+ }
+
+ if (strcmp(parameters.begin()->c_str(), compilerId) == 0)
+ {
+ return "1";
+ }
+
+ if (cmsysString_strcasecmp(parameters.begin()->c_str(), compilerId) == 0)
+ {
+ switch(context->Makefile->GetPolicyStatus(cmPolicies::CMP0044))
+ {
+ case cmPolicies::WARN:
+ {
+ std::ostringstream e;
+ e << context->Makefile->GetPolicies()
+ ->GetPolicyWarning(cmPolicies::CMP0044);
+ context->Makefile->GetCMakeInstance()
+ ->IssueMessage(cmake::AUTHOR_WARNING,
+ e.str(), context->Backtrace);
+ }
+ case cmPolicies::OLD:
+ return "1";
+ case cmPolicies::NEW:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::REQUIRED_IF_USED:
+ break;
+ }
+ }
+ return "0";
+ }
+};
+
+//----------------------------------------------------------------------------
+static const struct CCompilerIdNode : public CompilerIdNode
+{
+ CCompilerIdNode() {}
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *dagChecker) const
+ {
+ if (!context->HeadTarget)
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<C_COMPILER_ID> may only be used with binary targets. It may "
+ "not be used with add_custom_command or add_custom_target.");
+ return std::string();
+ }
+ return this->EvaluateWithLanguage(parameters, context, content,
+ dagChecker, "C");
+ }
+} cCompilerIdNode;
+
+//----------------------------------------------------------------------------
+static const struct CXXCompilerIdNode : public CompilerIdNode
+{
+ CXXCompilerIdNode() {}
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *dagChecker) const
+ {
+ if (!context->HeadTarget)
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<CXX_COMPILER_ID> may only be used with binary targets. It may "
+ "not be used with add_custom_command or add_custom_target.");
+ return std::string();
+ }
+ return this->EvaluateWithLanguage(parameters, context, content,
+ dagChecker, "CXX");
+ }
+} cxxCompilerIdNode;
+
+//----------------------------------------------------------------------------
+struct CompilerVersionNode : public cmGeneratorExpressionNode
+{
+ CompilerVersionNode() {}
+
+ virtual int NumExpectedParameters() const { return OneOrZeroParameters; }
+
+ std::string EvaluateWithLanguage(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *,
+ const std::string &lang) const
+ {
+ const char *compilerVersion = context->Makefile->GetSafeDefinition(
+ "CMAKE_" + lang + "_COMPILER_VERSION");
+ if (parameters.empty())
+ {
+ return compilerVersion ? compilerVersion : "";
+ }
+
+ static cmsys::RegularExpression compilerIdValidator("^[0-9\\.]*$");
+ if (!compilerIdValidator.find(*parameters.begin()))
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "Expression syntax not recognized.");
+ return std::string();
+ }
+ if (!compilerVersion)
+ {
+ return parameters.front().empty() ? "1" : "0";
+ }
+
+ return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
+ parameters.begin()->c_str(),
+ compilerVersion) ? "1" : "0";
+ }
+};
+
+//----------------------------------------------------------------------------
+static const struct CCompilerVersionNode : public CompilerVersionNode
+{
+ CCompilerVersionNode() {}
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *dagChecker) const
+ {
+ if (!context->HeadTarget)
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<C_COMPILER_VERSION> may only be used with binary targets. It "
+ "may not be used with add_custom_command or add_custom_target.");
+ return std::string();
+ }
+ return this->EvaluateWithLanguage(parameters, context, content,
+ dagChecker, "C");
+ }
+} cCompilerVersionNode;
+
+//----------------------------------------------------------------------------
+static const struct CxxCompilerVersionNode : public CompilerVersionNode
+{
+ CxxCompilerVersionNode() {}
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *dagChecker) const
+ {
+ if (!context->HeadTarget)
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<CXX_COMPILER_VERSION> may only be used with binary targets. It "
+ "may not be used with add_custom_command or add_custom_target.");
+ return std::string();
+ }
+ return this->EvaluateWithLanguage(parameters, context, content,
+ dagChecker, "CXX");
+ }
+} cxxCompilerVersionNode;
+
+
+//----------------------------------------------------------------------------
+struct PlatformIdNode : public cmGeneratorExpressionNode
+{
+ PlatformIdNode() {}
+
+ virtual int NumExpectedParameters() const { return OneOrZeroParameters; }
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ const char *platformId =
+ context->Makefile->GetSafeDefinition("CMAKE_SYSTEM_NAME");
+ if (parameters.empty())
+ {
+ return platformId ? platformId : "";
+ }
+
+ if (!platformId)
+ {
+ return parameters.front().empty() ? "1" : "0";
+ }
+
+ if (strcmp(parameters.begin()->c_str(), platformId) == 0)
+ {
+ return "1";
+ }
+ return "0";
+ }
+} platformIdNode;
+
+//----------------------------------------------------------------------------
+static const struct VersionGreaterNode : public cmGeneratorExpressionNode
+{
+ VersionGreaterNode() {}
+
+ virtual int NumExpectedParameters() const { return 2; }
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *,
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER,
+ parameters.front().c_str(),
+ parameters[1].c_str()) ? "1" : "0";
+ }
+} versionGreaterNode;
+
+//----------------------------------------------------------------------------
+static const struct VersionLessNode : public cmGeneratorExpressionNode
+{
+ VersionLessNode() {}
+
+ virtual int NumExpectedParameters() const { return 2; }
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *,
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ return cmSystemTools::VersionCompare(cmSystemTools::OP_LESS,
+ parameters.front().c_str(),
+ parameters[1].c_str()) ? "1" : "0";
+ }
+} versionLessNode;
+
+//----------------------------------------------------------------------------
+static const struct VersionEqualNode : public cmGeneratorExpressionNode
+{
+ VersionEqualNode() {}
+
+ virtual int NumExpectedParameters() const { return 2; }
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *,
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
+ parameters.front().c_str(),
+ parameters[1].c_str()) ? "1" : "0";
+ }
+} versionEqualNode;
+
+//----------------------------------------------------------------------------
+static const struct LinkOnlyNode : public cmGeneratorExpressionNode
+{
+ LinkOnlyNode() {}
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *,
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *dagChecker) const
+ {
+ if(!dagChecker->GetTransitivePropertiesOnly())
+ {
+ return parameters.front();
+ }
+ return "";
+ }
+} linkOnlyNode;
+
+//----------------------------------------------------------------------------
+static const struct ConfigurationNode : public cmGeneratorExpressionNode
+{
+ ConfigurationNode() {}
+
+ virtual int NumExpectedParameters() const { return 0; }
+
+ std::string Evaluate(const std::vector<std::string> &,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ context->HadContextSensitiveCondition = true;
+ return context->Config;
+ }
+} configurationNode;
+
+//----------------------------------------------------------------------------
+static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
+{
+ ConfigurationTestNode() {}
+
+ virtual int NumExpectedParameters() const { return OneOrZeroParameters; }
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ if (parameters.empty())
+ {
+ return configurationNode.Evaluate(parameters, context, content, 0);
+ }
+ static cmsys::RegularExpression configValidator("^[A-Za-z0-9_]*$");
+ if (!configValidator.find(*parameters.begin()))
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "Expression syntax not recognized.");
+ return std::string();
+ }
+ context->HadContextSensitiveCondition = true;
+ if (context->Config.empty())
+ {
+ return parameters.front().empty() ? "1" : "0";
+ }
+
+ if (cmsysString_strcasecmp(parameters.begin()->c_str(),
+ context->Config.c_str()) == 0)
+ {
+ return "1";
+ }
+
+ if (context->CurrentTarget
+ && context->CurrentTarget->IsImported())
+ {
+ const char* loc = 0;
+ const char* imp = 0;
+ std::string suffix;
+ if (context->CurrentTarget->GetMappedConfig(context->Config,
+ &loc,
+ &imp,
+ suffix))
+ {
+ // This imported target has an appropriate location
+ // for this (possibly mapped) config.
+ // Check if there is a proper config mapping for the tested config.
+ std::vector<std::string> mappedConfigs;
+ std::string mapProp = "MAP_IMPORTED_CONFIG_";
+ mapProp += cmSystemTools::UpperCase(context->Config);
+ if(const char* mapValue =
+ context->CurrentTarget->GetProperty(mapProp))
+ {
+ cmSystemTools::ExpandListArgument(cmSystemTools::UpperCase(mapValue),
+ mappedConfigs);
+ return std::find(mappedConfigs.begin(), mappedConfigs.end(),
+ cmSystemTools::UpperCase(parameters.front()))
+ != mappedConfigs.end() ? "1" : "0";
+ }
+ }
+ }
+ return "0";
+ }
+} configurationTestNode;
+
+static const struct JoinNode : public cmGeneratorExpressionNode
+{
+ JoinNode() {}
+
+ virtual int NumExpectedParameters() const { return 2; }
+
+ virtual bool AcceptsArbitraryContentParameter() const { return true; }
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *,
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ std::vector<std::string> list;
+ cmSystemTools::ExpandListArgument(parameters.front(), list);
+ return cmJoin(list, parameters[1]);
+ }
+} joinNode;
+
+static const struct CompileLanguageNode : public cmGeneratorExpressionNode
+{
+ CompileLanguageNode() {}
+
+ virtual int NumExpectedParameters() const { return OneOrZeroParameters; }
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *dagChecker) const
+ {
+ if(context->Language.empty())
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<COMPILE_LANGUAGE:...> may only be used to specify include "
+ "directories compile definitions, compile options and to evaluate "
+ "components of the file(GENERATE) command.");
+ return std::string();
+ }
+
+ std::vector<std::string> enabledLanguages;
+ cmGlobalGenerator* gg
+ = context->Makefile->GetLocalGenerator()->GetGlobalGenerator();
+ gg->GetEnabledLanguages(enabledLanguages);
+ if (!parameters.empty() &&
+ std::find(enabledLanguages.begin(), enabledLanguages.end(),
+ parameters.front()) == enabledLanguages.end())
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<COMPILE_LANGUAGE:...> Unknown language.");
+ return std::string();
+ }
+ std::string genName = gg->GetName();
+ if (genName.find("Visual Studio") != std::string::npos)
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<COMPILE_LANGUAGE:...> may not be used with Visual Studio "
+ "generators.");
+ return std::string();
+ }
+ else if (genName.find("Xcode") != std::string::npos)
+ {
+ if (dagChecker && (dagChecker->EvaluatingCompileDefinitions()
+ || dagChecker->EvaluatingIncludeDirectories()))
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<COMPILE_LANGUAGE:...> may only be used with COMPILE_OPTIONS "
+ "with the Xcode generator.");
+ return std::string();
+ }
+ }
+ else
+ {
+ if(genName.find("Makefiles") == std::string::npos &&
+ genName.find("Ninja") == std::string::npos &&
+ genName.find("Watcom WMake") == std::string::npos)
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<COMPILE_LANGUAGE:...> not supported for this generator.");
+ return std::string();
+ }
+ }
+ if (parameters.empty())
+ {
+ return context->Language;
+ }
+ return context->Language == parameters.front() ? "1" : "0";
+ }
+} languageNode;
+
+#define TRANSITIVE_PROPERTY_NAME(PROPERTY) \
+ , "INTERFACE_" #PROPERTY
+
+//----------------------------------------------------------------------------
+static const char* targetPropertyTransitiveWhitelist[] = {
+ 0
+ CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(TRANSITIVE_PROPERTY_NAME)
+};
+
+#undef TRANSITIVE_PROPERTY_NAME
+
+template <typename T>
+std::string
+getLinkedTargetsContent(
+ std::vector<T> const &libraries,
+ cmTarget const* target,
+ cmTarget const* headTarget,
+ cmGeneratorExpressionContext *context,
+ cmGeneratorExpressionDAGChecker *dagChecker,
+ const std::string &interfacePropertyName)
+{
+ std::string linkedTargetsContent;
+ std::string sep;
+ std::string depString;
+ for (typename std::vector<T>::const_iterator it = libraries.begin();
+ it != libraries.end(); ++it)
+ {
+ // Broken code can have a target in its own link interface.
+ // Don't follow such link interface entries so as not to create a
+ // self-referencing loop.
+ if (it->Target && it->Target != target)
+ {
+ depString +=
+ sep + "$<TARGET_PROPERTY:" +
+ it->Target->GetName() + "," + interfacePropertyName + ">";
+ sep = ";";
+ }
+ }
+ if(!depString.empty())
+ {
+ linkedTargetsContent =
+ cmGeneratorExpressionNode::EvaluateDependentExpression(depString,
+ target->GetMakefile(), context,
+ headTarget, target, dagChecker);
+ }
+ linkedTargetsContent =
+ cmGeneratorExpression::StripEmptyListElements(linkedTargetsContent);
+ return linkedTargetsContent;
+}
+
+//----------------------------------------------------------------------------
+static const struct TargetPropertyNode : public cmGeneratorExpressionNode
+{
+ TargetPropertyNode() {}
+
+ // This node handles errors on parameter count itself.
+ virtual int NumExpectedParameters() const { return OneOrMoreParameters; }
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *dagCheckerParent
+ ) const
+ {
+ if (parameters.size() != 1 && parameters.size() != 2)
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<TARGET_PROPERTY:...> expression requires one or two parameters");
+ return std::string();
+ }
+ static cmsys::RegularExpression propertyNameValidator("^[A-Za-z0-9_]+$");
+
+ cmTarget const* target = context->HeadTarget;
+ std::string propertyName = *parameters.begin();
+
+ if (parameters.size() == 1)
+ {
+ context->HadHeadSensitiveCondition = true;
+ }
+ if (!target && parameters.size() == 1)
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<TARGET_PROPERTY:prop> may only be used with binary targets. "
+ "It may not be used with add_custom_command or add_custom_target. "
+ "Specify the target to read a property from using the "
+ "$<TARGET_PROPERTY:tgt,prop> signature instead.");
+ return std::string();
+ }
+
+ if (parameters.size() == 2)
+ {
+ if (parameters.begin()->empty() && parameters[1].empty())
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<TARGET_PROPERTY:tgt,prop> expression requires a non-empty "
+ "target name and property name.");
+ return std::string();
+ }
+ if (parameters.begin()->empty())
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<TARGET_PROPERTY:tgt,prop> expression requires a non-empty "
+ "target name.");
+ return std::string();
+ }
+
+ std::string targetName = parameters.front();
+ propertyName = parameters[1];
+ if (!cmGeneratorExpression::IsValidTargetName(targetName))
+ {
+ if (!propertyNameValidator.find(propertyName.c_str()))
+ {
+ ::reportError(context, content->GetOriginalExpression(),
+ "Target name and property name not supported.");
+ return std::string();
+ }
+ ::reportError(context, content->GetOriginalExpression(),
+ "Target name not supported.");
+ return std::string();
+ }
+ if(propertyName == "ALIASED_TARGET")
+ {
+ if(context->Makefile->IsAlias(targetName))
+ {
+ if(cmTarget* tgt = context->Makefile->FindTargetToUse(targetName))
+ {
+ return tgt->GetName();
+ }
+ }
+ return "";
+ }
+ target = context->Makefile->FindTargetToUse(targetName);
+
+ if (!target)
+ {
+ std::ostringstream e;
+ e << "Target \""
+ << targetName
+ << "\" not found.";
+ reportError(context, content->GetOriginalExpression(), e.str());
+ return std::string();
+ }
+ context->AllTargets.insert(target);
+ }
+
+ if (target == context->HeadTarget)
+ {
+ // Keep track of the properties seen while processing.
+ // The evaluation of the LINK_LIBRARIES generator expressions
+ // will check this to ensure that properties have one consistent
+ // value for all evaluations.
+ context->SeenTargetProperties.insert(propertyName);
+ }
+ if (propertyName == "SOURCES")
+ {
+ context->SourceSensitiveTargets.insert(target);
+ }
+
+ if (propertyName.empty())
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<TARGET_PROPERTY:...> expression requires a non-empty property "
+ "name.");
+ return std::string();
+ }
+
+ if (!propertyNameValidator.find(propertyName))
+ {
+ ::reportError(context, content->GetOriginalExpression(),
+ "Property name not supported.");
+ return std::string();
+ }
+
+ assert(target);
+
+ if (propertyName == "LINKER_LANGUAGE")
+ {
+ if (target->LinkLanguagePropagatesToDependents() &&
+ dagCheckerParent && (dagCheckerParent->EvaluatingLinkLibraries()
+ || dagCheckerParent->EvaluatingSources()))
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "LINKER_LANGUAGE target property can not be used while evaluating "
+ "link libraries for a static library");
+ return std::string();
+ }
+ return target->GetLinkerLanguage(context->Config);
+ }
+
+ cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace,
+ target->GetName(),
+ propertyName,
+ content,
+ dagCheckerParent);
+
+ switch (dagChecker.Check())
+ {
+ case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
+ dagChecker.ReportError(context, content->GetOriginalExpression());
+ return std::string();
+ case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE:
+ // No error. We just skip cyclic references.
+ return std::string();
+ case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
+ for (size_t i = 1;
+ i < cmArraySize(targetPropertyTransitiveWhitelist);
+ ++i)
+ {
+ if (targetPropertyTransitiveWhitelist[i] == propertyName)
+ {
+ // No error. We're not going to find anything new here.
+ return std::string();
+ }
+ }
+ case cmGeneratorExpressionDAGChecker::DAG:
+ break;
+ }
+
+ const char *prop = target->GetProperty(propertyName);
+
+ if (dagCheckerParent)
+ {
+ if (dagCheckerParent->EvaluatingLinkLibraries())
+ {
+#define TRANSITIVE_PROPERTY_COMPARE(PROPERTY) \
+ (#PROPERTY == propertyName || "INTERFACE_" #PROPERTY == propertyName) ||
+ if (CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(TRANSITIVE_PROPERTY_COMPARE)
+ false)
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<TARGET_PROPERTY:...> expression in link libraries "
+ "evaluation depends on target property which is transitive "
+ "over the link libraries, creating a recursion.");
+ return std::string();
+ }
+#undef TRANSITIVE_PROPERTY_COMPARE
+
+ if(!prop)
+ {
+ return std::string();
+ }
+ }
+ else
+ {
+#define ASSERT_TRANSITIVE_PROPERTY_METHOD(METHOD) \
+ dagCheckerParent->METHOD () ||
+
+ assert(
+ CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(
+ ASSERT_TRANSITIVE_PROPERTY_METHOD)
+ false);
+#undef ASSERT_TRANSITIVE_PROPERTY_METHOD
+ }
+ }
+
+ std::string linkedTargetsContent;
+
+ std::string interfacePropertyName;
+ bool isInterfaceProperty = false;
+
+#define POPULATE_INTERFACE_PROPERTY_NAME(prop) \
+ if (propertyName == #prop) \
+ { \
+ interfacePropertyName = "INTERFACE_" #prop; \
+ } \
+ else if (propertyName == "INTERFACE_" #prop) \
+ { \
+ interfacePropertyName = "INTERFACE_" #prop; \
+ isInterfaceProperty = true; \
+ } \
+ else
+
+ CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(POPULATE_INTERFACE_PROPERTY_NAME)
+ // Note that the above macro terminates with an else
+ /* else */ if (cmHasLiteralPrefix(propertyName.c_str(),
+ "COMPILE_DEFINITIONS_"))
+ {
+ cmPolicies::PolicyStatus polSt =
+ context->Makefile->GetPolicyStatus(cmPolicies::CMP0043);
+ if (polSt == cmPolicies::WARN || polSt == cmPolicies::OLD)
+ {
+ interfacePropertyName = "INTERFACE_COMPILE_DEFINITIONS";
+ }
+ }
+#undef POPULATE_INTERFACE_PROPERTY_NAME
+ cmTarget const* headTarget = context->HeadTarget && isInterfaceProperty
+ ? context->HeadTarget : target;
+
+ if(isInterfaceProperty)
+ {
+ if(cmTarget::LinkInterfaceLibraries const* iface =
+ target->GetLinkInterfaceLibraries(context->Config, headTarget, true))
+ {
+ linkedTargetsContent =
+ getLinkedTargetsContent(iface->Libraries, target,
+ headTarget,
+ context, &dagChecker,
+ interfacePropertyName);
+ }
+ }
+ else if(!interfacePropertyName.empty())
+ {
+ if(cmTarget::LinkImplementationLibraries const* impl =
+ target->GetLinkImplementationLibraries(context->Config))
+ {
+ linkedTargetsContent =
+ getLinkedTargetsContent(impl->Libraries, target,
+ target,
+ context, &dagChecker,
+ interfacePropertyName);
+ }
+ }
+
+ if (!prop)
+ {
+ if (target->IsImported()
+ || target->GetType() == cmTarget::INTERFACE_LIBRARY)
+ {
+ return linkedTargetsContent;
+ }
+ if (target->IsLinkInterfaceDependentBoolProperty(propertyName,
+ context->Config))
+ {
+ context->HadContextSensitiveCondition = true;
+ return target->GetLinkInterfaceDependentBoolProperty(
+ propertyName,
+ context->Config) ? "1" : "0";
+ }
+ if (target->IsLinkInterfaceDependentStringProperty(propertyName,
+ context->Config))
+ {
+ context->HadContextSensitiveCondition = true;
+ const char *propContent =
+ target->GetLinkInterfaceDependentStringProperty(
+ propertyName,
+ context->Config);
+ return propContent ? propContent : "";
+ }
+ if (target->IsLinkInterfaceDependentNumberMinProperty(propertyName,
+ context->Config))
+ {
+ context->HadContextSensitiveCondition = true;
+ const char *propContent =
+ target->GetLinkInterfaceDependentNumberMinProperty(
+ propertyName,
+ context->Config);
+ return propContent ? propContent : "";
+ }
+ if (target->IsLinkInterfaceDependentNumberMaxProperty(propertyName,
+ context->Config))
+ {
+ context->HadContextSensitiveCondition = true;
+ const char *propContent =
+ target->GetLinkInterfaceDependentNumberMaxProperty(
+ propertyName,
+ context->Config);
+ return propContent ? propContent : "";
+ }
+
+ return linkedTargetsContent;
+ }
+
+ if (!target->IsImported()
+ && dagCheckerParent && !dagCheckerParent->EvaluatingLinkLibraries())
+ {
+ if (target->IsLinkInterfaceDependentNumberMinProperty(propertyName,
+ context->Config))
+ {
+ context->HadContextSensitiveCondition = true;
+ const char *propContent =
+ target->GetLinkInterfaceDependentNumberMinProperty(
+ propertyName,
+ context->Config);
+ return propContent ? propContent : "";
+ }
+ if (target->IsLinkInterfaceDependentNumberMaxProperty(propertyName,
+ context->Config))
+ {
+ context->HadContextSensitiveCondition = true;
+ const char *propContent =
+ target->GetLinkInterfaceDependentNumberMaxProperty(
+ propertyName,
+ context->Config);
+ return propContent ? propContent : "";
+ }
+ }
+ if(!interfacePropertyName.empty())
+ {
+ std::string result = this->EvaluateDependentExpression(prop,
+ context->Makefile, context,
+ headTarget, target, &dagChecker);
+ if (!linkedTargetsContent.empty())
+ {
+ result += (result.empty() ? "" : ";") + linkedTargetsContent;
+ }
+ return result;
+ }
+ return prop;
+ }
+} targetPropertyNode;
+
+//----------------------------------------------------------------------------
+static const struct TargetNameNode : public cmGeneratorExpressionNode
+{
+ TargetNameNode() {}
+
+ virtual bool GeneratesContent() const { return true; }
+
+ virtual bool AcceptsArbitraryContentParameter() const { return true; }
+ virtual bool RequiresLiteralInput() const { return true; }
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *,
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ return parameters.front();
+ }
+
+ virtual int NumExpectedParameters() const { return 1; }
+
+} targetNameNode;
+
+//----------------------------------------------------------------------------
+static const struct TargetObjectsNode : public cmGeneratorExpressionNode
+{
+ TargetObjectsNode() {}
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ if (!context->EvaluateForBuildsystem)
+ {
+ std::ostringstream e;
+ e << "The evaluation of the TARGET_OBJECTS generator expression "
+ "is only suitable for consumption by CMake. It is not suitable "
+ "for writing out elsewhere.";
+ reportError(context, content->GetOriginalExpression(), e.str());
+ return std::string();
+ }
+
+ std::string tgtName = parameters.front();
+ cmGeneratorTarget* gt =
+ context->Makefile->FindGeneratorTargetToUse(tgtName);
+ if (!gt)
+ {
+ std::ostringstream e;
+ e << "Objects of target \"" << tgtName
+ << "\" referenced but no such target exists.";
+ reportError(context, content->GetOriginalExpression(), e.str());
+ return std::string();
+ }
+ if (gt->GetType() != cmTarget::OBJECT_LIBRARY)
+ {
+ std::ostringstream e;
+ e << "Objects of target \"" << tgtName
+ << "\" referenced but is not an OBJECT library.";
+ reportError(context, content->GetOriginalExpression(), e.str());
+ return std::string();
+ }
+
+ std::vector<cmSourceFile const*> objectSources;
+ gt->GetObjectSources(objectSources, context->Config);
+ std::map<cmSourceFile const*, std::string> mapping;
+
+ for(std::vector<cmSourceFile const*>::const_iterator it
+ = objectSources.begin(); it != objectSources.end(); ++it)
+ {
+ mapping[*it];
+ }
+
+ gt->LocalGenerator->ComputeObjectFilenames(mapping, gt);
+
+ std::string obj_dir = gt->ObjectDirectory;
+ std::string result;
+ const char* sep = "";
+ for(std::vector<cmSourceFile const*>::const_iterator it
+ = objectSources.begin(); it != objectSources.end(); ++it)
+ {
+ // Find the object file name corresponding to this source file.
+ std::map<cmSourceFile const*, std::string>::const_iterator
+ map_it = mapping.find(*it);
+ // It must exist because we populated the mapping just above.
+ assert(!map_it->second.empty());
+ result += sep;
+ std::string objFile = obj_dir + map_it->second;
+ cmSourceFile* sf = context->Makefile->GetOrCreateSource(objFile, true);
+ sf->SetObjectLibrary(tgtName);
+ sf->SetProperty("EXTERNAL_OBJECT", "1");
+ result += objFile;
+ sep = ";";
+ }
+ return result;
+ }
+} targetObjectsNode;
+
+//----------------------------------------------------------------------------
+static const struct CompileFeaturesNode : public cmGeneratorExpressionNode
+{
+ CompileFeaturesNode() {}
+
+ virtual int NumExpectedParameters() const { return OneOrMoreParameters; }
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *dagChecker) const
+ {
+ cmTarget const* target = context->HeadTarget;
+ if (!target)
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<COMPILE_FEATURE> may only be used with binary targets. It may "
+ "not be used with add_custom_command or add_custom_target.");
+ return std::string();
+ }
+ context->HadHeadSensitiveCondition = true;
+
+ typedef std::map<std::string, std::vector<std::string> > LangMap;
+ static LangMap availableFeatures;
+
+ LangMap testedFeatures;
+
+ for (std::vector<std::string>::const_iterator it = parameters.begin();
+ it != parameters.end(); ++it)
+ {
+ std::string error;
+ std::string lang;
+ if (!context->Makefile->CompileFeatureKnown(context->HeadTarget,
+ *it, lang, &error))
+ {
+ reportError(context, content->GetOriginalExpression(), error);
+ return std::string();
+ }
+ testedFeatures[lang].push_back(*it);
+
+ if (availableFeatures.find(lang) == availableFeatures.end())
+ {
+ const char* featuresKnown
+ = context->Makefile->CompileFeaturesAvailable(lang, &error);
+ if (!featuresKnown)
+ {
+ reportError(context, content->GetOriginalExpression(), error);
+ return std::string();
+ }
+ cmSystemTools::ExpandListArgument(featuresKnown,
+ availableFeatures[lang]);
+ }
+ }
+
+ bool evalLL = dagChecker && dagChecker->EvaluatingLinkLibraries();
+
+ std::string result;
+
+ for (LangMap::const_iterator lit = testedFeatures.begin();
+ lit != testedFeatures.end(); ++lit)
+ {
+ std::vector<std::string> const& langAvailable
+ = availableFeatures[lit->first];
+ const char* standardDefault = context->Makefile
+ ->GetDefinition("CMAKE_" + lit->first + "_STANDARD_DEFAULT");
+ for (std::vector<std::string>::const_iterator it = lit->second.begin();
+ it != lit->second.end(); ++it)
+ {
+ if (std::find(langAvailable.begin(), langAvailable.end(), *it)
+ == langAvailable.end())
+ {
+ return "0";
+ }
+ if (standardDefault && !*standardDefault)
+ {
+ // This compiler has no notion of language standard levels.
+ // All features known for the language are always available.
+ continue;
+ }
+ if (!context->Makefile->HaveStandardAvailable(target,
+ lit->first, *it))
+ {
+ if (evalLL)
+ {
+ const char* l = target->GetProperty(lit->first + "_STANDARD");
+ if (!l)
+ {
+ l = standardDefault;
+ }
+ assert(l);
+ context->MaxLanguageStandard[target][lit->first] = l;
+ }
+ else
+ {
+ return "0";
+ }
+ }
+ }
+ }
+ return "1";
+ }
+} compileFeaturesNode;
+
+//----------------------------------------------------------------------------
+static const char* targetPolicyWhitelist[] = {
+ 0
+#define TARGET_POLICY_STRING(POLICY) \
+ , #POLICY
+
+ CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_STRING)
+
+#undef TARGET_POLICY_STRING
+};
+
+cmPolicies::PolicyStatus statusForTarget(cmTarget const* tgt,
+ const char *policy)
+{
+#define RETURN_POLICY(POLICY) \
+ if (strcmp(policy, #POLICY) == 0) \
+ { \
+ return tgt->GetPolicyStatus ## POLICY (); \
+ } \
+
+ CM_FOR_EACH_TARGET_POLICY(RETURN_POLICY)
+
+#undef RETURN_POLICY
+
+ assert(0 && "Unreachable code. Not a valid policy");
+ return cmPolicies::WARN;
+}
+
+cmPolicies::PolicyID policyForString(const char *policy_id)
+{
+#define RETURN_POLICY_ID(POLICY_ID) \
+ if (strcmp(policy_id, #POLICY_ID) == 0) \
+ { \
+ return cmPolicies:: POLICY_ID; \
+ } \
+
+ CM_FOR_EACH_TARGET_POLICY(RETURN_POLICY_ID)
+
+#undef RETURN_POLICY_ID
+
+ assert(0 && "Unreachable code. Not a valid policy");
+ return cmPolicies::CMP0002;
+}
+
+//----------------------------------------------------------------------------
+static const struct TargetPolicyNode : public cmGeneratorExpressionNode
+{
+ TargetPolicyNode() {}
+
+ virtual int NumExpectedParameters() const { return 1; }
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *context ,
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ if (!context->HeadTarget)
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "$<TARGET_POLICY:prop> may only be used with binary targets. It "
+ "may not be used with add_custom_command or add_custom_target.");
+ return std::string();
+ }
+
+ context->HadContextSensitiveCondition = true;
+ context->HadHeadSensitiveCondition = true;
+
+ for (size_t i = 1; i < cmArraySize(targetPolicyWhitelist); ++i)
+ {
+ const char *policy = targetPolicyWhitelist[i];
+ if (parameters.front() == policy)
+ {
+ cmMakefile *mf = context->HeadTarget->GetMakefile();
+ switch(statusForTarget(context->HeadTarget, policy))
+ {
+ case cmPolicies::WARN:
+ mf->IssueMessage(cmake::AUTHOR_WARNING,
+ mf->GetPolicies()->
+ GetPolicyWarning(policyForString(policy)));
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ case cmPolicies::OLD:
+ return "0";
+ case cmPolicies::NEW:
+ return "1";
+ }
+ }
+ }
+ reportError(context, content->GetOriginalExpression(),
+ "$<TARGET_POLICY:prop> may only be used with a limited number of "
+ "policies. Currently it may be used with the following policies:\n"
+
+#define STRINGIFY_HELPER(X) #X
+#define STRINGIFY(X) STRINGIFY_HELPER(X)
+
+#define TARGET_POLICY_LIST_ITEM(POLICY) \
+ " * " STRINGIFY(POLICY) "\n"
+
+ CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_LIST_ITEM)
+
+#undef TARGET_POLICY_LIST_ITEM
+ );
+ return std::string();
+ }
+
+} targetPolicyNode;
+
+//----------------------------------------------------------------------------
+static const struct InstallPrefixNode : public cmGeneratorExpressionNode
+{
+ InstallPrefixNode() {}
+
+ virtual bool GeneratesContent() const { return true; }
+ virtual int NumExpectedParameters() const { return 0; }
+
+ std::string Evaluate(const std::vector<std::string> &,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *) const
+ {
+ reportError(context, content->GetOriginalExpression(),
+ "INSTALL_PREFIX is a marker for install(EXPORT) only. It "
+ "should never be evaluated.");
+ return std::string();
+ }
+
+} installPrefixNode;
+
+//----------------------------------------------------------------------------
+class ArtifactNameTag;
+class ArtifactLinkerTag;
+class ArtifactSonameTag;
+class ArtifactPdbTag;
+
+class ArtifactPathTag;
+class ArtifactDirTag;
+class ArtifactNameTag;
+
+//----------------------------------------------------------------------------
+template<typename ArtifactT>
+struct TargetFilesystemArtifactResultCreator
+{
+ static std::string Create(cmTarget* target,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content);
+};
+
+//----------------------------------------------------------------------------
+template<>
+struct TargetFilesystemArtifactResultCreator<ArtifactSonameTag>
+{
+ static std::string Create(cmTarget* target,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content)
+ {
+ // The target soname file (.so.1).
+ if(target->IsDLLPlatform())
+ {
+ ::reportError(context, content->GetOriginalExpression(),
+ "TARGET_SONAME_FILE is not allowed "
+ "for DLL target platforms.");
+ return std::string();
+ }
+ if(target->GetType() != cmTarget::SHARED_LIBRARY)
+ {
+ ::reportError(context, content->GetOriginalExpression(),
+ "TARGET_SONAME_FILE is allowed only for "
+ "SHARED libraries.");
+ return std::string();
+ }
+ std::string result = target->GetDirectory(context->Config);
+ result += "/";
+ result += target->GetSOName(context->Config);
+ return result;
+ }
+};
+
+//----------------------------------------------------------------------------
+template<>
+struct TargetFilesystemArtifactResultCreator<ArtifactPdbTag>
+{
+ static std::string Create(cmTarget* target,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content)
+ {
+ std::string language = target->GetLinkerLanguage(context->Config);
+
+ std::string pdbSupportVar = "CMAKE_" + language + "_LINKER_SUPPORTS_PDB";
+
+ if(!context->Makefile->IsOn(pdbSupportVar))
+ {
+ ::reportError(context, content->GetOriginalExpression(),
+ "TARGET_PDB_FILE is not supported by the target linker.");
+ return std::string();
+ }
+
+ cmTarget::TargetType targetType = target->GetType();
+
+ if(targetType != cmTarget::SHARED_LIBRARY &&
+ targetType != cmTarget::MODULE_LIBRARY &&
+ targetType != cmTarget::EXECUTABLE)
+ {
+ ::reportError(context, content->GetOriginalExpression(),
+ "TARGET_PDB_FILE is allowed only for "
+ "targets with linker created artifacts.");
+ return std::string();
+ }
+
+ std::string result = target->GetPDBDirectory(context->Config);
+ result += "/";
+ result += target->GetPDBName(context->Config);
+ return result;
+ }
+};
+
+//----------------------------------------------------------------------------
+template<>
+struct TargetFilesystemArtifactResultCreator<ArtifactLinkerTag>
+{
+ static std::string Create(cmTarget* target,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content)
+ {
+ // The file used to link to the target (.so, .lib, .a).
+ if(!target->IsLinkable())
+ {
+ ::reportError(context, content->GetOriginalExpression(),
+ "TARGET_LINKER_FILE is allowed only for libraries and "
+ "executables with ENABLE_EXPORTS.");
+ return std::string();
+ }
+ return target->GetFullPath(context->Config,
+ target->HasImportLibrary());
+ }
+};
+
+//----------------------------------------------------------------------------
+template<>
+struct TargetFilesystemArtifactResultCreator<ArtifactNameTag>
+{
+ static std::string Create(cmTarget* target,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *)
+ {
+ return target->GetFullPath(context->Config, false, true);
+ }
+};
+
+
+//----------------------------------------------------------------------------
+template<typename ArtifactT>
+struct TargetFilesystemArtifactResultGetter
+{
+ static std::string Get(const std::string &result);
+};
+
+//----------------------------------------------------------------------------
+template<>
+struct TargetFilesystemArtifactResultGetter<ArtifactNameTag>
+{
+ static std::string Get(const std::string &result)
+ { return cmSystemTools::GetFilenameName(result); }
+};
+
+//----------------------------------------------------------------------------
+template<>
+struct TargetFilesystemArtifactResultGetter<ArtifactDirTag>
+{
+ static std::string Get(const std::string &result)
+ { return cmSystemTools::GetFilenamePath(result); }
+};
+
+//----------------------------------------------------------------------------
+template<>
+struct TargetFilesystemArtifactResultGetter<ArtifactPathTag>
+{
+ static std::string Get(const std::string &result)
+ { return result; }
+};
+
+//----------------------------------------------------------------------------
+template<typename ArtifactT, typename ComponentT>
+struct TargetFilesystemArtifact : public cmGeneratorExpressionNode
+{
+ TargetFilesystemArtifact() {}
+
+ virtual int NumExpectedParameters() const { return 1; }
+
+ std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *dagChecker) const
+ {
+ // Lookup the referenced target.
+ std::string name = *parameters.begin();
+
+ if (!cmGeneratorExpression::IsValidTargetName(name))
+ {
+ ::reportError(context, content->GetOriginalExpression(),
+ "Expression syntax not recognized.");
+ return std::string();
+ }
+ cmTarget* target = context->Makefile->FindTargetToUse(name);
+ if(!target)
+ {
+ ::reportError(context, content->GetOriginalExpression(),
+ "No target \"" + name + "\"");
+ return std::string();
+ }
+ if(target->GetType() >= cmTarget::OBJECT_LIBRARY &&
+ target->GetType() != cmTarget::UNKNOWN_LIBRARY)
+ {
+ ::reportError(context, content->GetOriginalExpression(),
+ "Target \"" + name + "\" is not an executable or library.");
+ return std::string();
+ }
+ if (dagChecker && (dagChecker->EvaluatingLinkLibraries(name.c_str())
+ || (dagChecker->EvaluatingSources()
+ && name == dagChecker->TopTarget())))
+ {
+ ::reportError(context, content->GetOriginalExpression(),
+ "Expressions which require the linker language may not "
+ "be used while evaluating link libraries");
+ return std::string();
+ }
+ context->DependTargets.insert(target);
+ context->AllTargets.insert(target);
+
+ std::string result =
+ TargetFilesystemArtifactResultCreator<ArtifactT>::Create(
+ target,
+ context,
+ content);
+ if (context->HadError)
+ {
+ return std::string();
+ }
+ return
+ TargetFilesystemArtifactResultGetter<ComponentT>::Get(result);
+ }
+};
+
+//----------------------------------------------------------------------------
+template<typename ArtifactT>
+struct TargetFilesystemArtifactNodeGroup
+{
+ TargetFilesystemArtifactNodeGroup()
+ {
+ }
+
+ TargetFilesystemArtifact<ArtifactT, ArtifactPathTag> File;
+ TargetFilesystemArtifact<ArtifactT, ArtifactNameTag> FileName;
+ TargetFilesystemArtifact<ArtifactT, ArtifactDirTag> FileDir;
+};
+
+//----------------------------------------------------------------------------
+static const
+TargetFilesystemArtifactNodeGroup<ArtifactNameTag> targetNodeGroup;
+
+static const
+TargetFilesystemArtifactNodeGroup<ArtifactLinkerTag> targetLinkerNodeGroup;
+
+static const
+TargetFilesystemArtifactNodeGroup<ArtifactSonameTag> targetSoNameNodeGroup;
+
+static const
+TargetFilesystemArtifactNodeGroup<ArtifactPdbTag> targetPdbNodeGroup;
+
+//----------------------------------------------------------------------------
+const cmGeneratorExpressionNode*
+cmGeneratorExpressionNode::GetNode(const std::string &identifier)
+{
+ typedef std::map<std::string, const cmGeneratorExpressionNode*> NodeMap;
+ static NodeMap nodeMap;
+ if (nodeMap.empty())
+ {
+ nodeMap["0"] = &zeroNode;
+ nodeMap["1"] = &oneNode;
+ nodeMap["AND"] = &andNode;
+ nodeMap["OR"] = &orNode;
+ nodeMap["NOT"] = &notNode;
+ nodeMap["C_COMPILER_ID"] = &cCompilerIdNode;
+ nodeMap["CXX_COMPILER_ID"] = &cxxCompilerIdNode;
+ nodeMap["VERSION_GREATER"] = &versionGreaterNode;
+ nodeMap["VERSION_LESS"] = &versionLessNode;
+ nodeMap["VERSION_EQUAL"] = &versionEqualNode;
+ nodeMap["C_COMPILER_VERSION"] = &cCompilerVersionNode;
+ nodeMap["CXX_COMPILER_VERSION"] = &cxxCompilerVersionNode;
+ nodeMap["PLATFORM_ID"] = &platformIdNode;
+ nodeMap["COMPILE_FEATURES"] = &compileFeaturesNode;
+ nodeMap["CONFIGURATION"] = &configurationNode;
+ nodeMap["CONFIG"] = &configurationTestNode;
+ nodeMap["TARGET_FILE"] = &targetNodeGroup.File;
+ nodeMap["TARGET_LINKER_FILE"] = &targetLinkerNodeGroup.File;
+ nodeMap["TARGET_SONAME_FILE"] = &targetSoNameNodeGroup.File;
+ nodeMap["TARGET_PDB_FILE"] = &targetPdbNodeGroup.File;
+ nodeMap["TARGET_FILE_NAME"] = &targetNodeGroup.FileName;
+ nodeMap["TARGET_LINKER_FILE_NAME"] = &targetLinkerNodeGroup.FileName;
+ nodeMap["TARGET_SONAME_FILE_NAME"] = &targetSoNameNodeGroup.FileName;
+ nodeMap["TARGET_PDB_FILE_NAME"] = &targetPdbNodeGroup.FileName;
+ nodeMap["TARGET_FILE_DIR"] = &targetNodeGroup.FileDir;
+ nodeMap["TARGET_LINKER_FILE_DIR"] = &targetLinkerNodeGroup.FileDir;
+ nodeMap["TARGET_SONAME_FILE_DIR"] = &targetSoNameNodeGroup.FileDir;
+ nodeMap["TARGET_PDB_FILE_DIR"] = &targetPdbNodeGroup.FileDir;
+ nodeMap["STREQUAL"] = &strEqualNode;
+ nodeMap["EQUAL"] = &equalNode;
+ nodeMap["LOWER_CASE"] = &lowerCaseNode;
+ nodeMap["UPPER_CASE"] = &upperCaseNode;
+ nodeMap["MAKE_C_IDENTIFIER"] = &makeCIdentifierNode;
+ nodeMap["BOOL"] = &boolNode;
+ nodeMap["ANGLE-R"] = &angle_rNode;
+ nodeMap["COMMA"] = &commaNode;
+ nodeMap["SEMICOLON"] = &semicolonNode;
+ nodeMap["TARGET_PROPERTY"] = &targetPropertyNode;
+ nodeMap["TARGET_NAME"] = &targetNameNode;
+ nodeMap["TARGET_OBJECTS"] = &targetObjectsNode;
+ nodeMap["TARGET_POLICY"] = &targetPolicyNode;
+ nodeMap["BUILD_INTERFACE"] = &buildInterfaceNode;
+ nodeMap["INSTALL_INTERFACE"] = &installInterfaceNode;
+ nodeMap["INSTALL_PREFIX"] = &installPrefixNode;
+ nodeMap["JOIN"] = &joinNode;
+ nodeMap["LINK_ONLY"] = &linkOnlyNode;
+ nodeMap["COMPILE_LANGUAGE"] = &languageNode;
+ }
+ NodeMap::const_iterator i = nodeMap.find(identifier);
+ if (i == nodeMap.end())
+ {
+ return 0;
+ }
+ return i->second;
+}
+
+//----------------------------------------------------------------------------
+void reportError(cmGeneratorExpressionContext *context,
+ const std::string &expr, const std::string &result)
+{
+ context->HadError = true;
+ if (context->Quiet)
+ {
+ return;
+ }
+
+ std::ostringstream e;
+ e << "Error evaluating generator expression:\n"
+ << " " << expr << "\n"
+ << result;
+ context->Makefile->GetCMakeInstance()
+ ->IssueMessage(cmake::FATAL_ERROR, e.str(),
+ context->Backtrace);
+}
diff --git a/Source/cmGeneratorExpressionNode.h b/Source/cmGeneratorExpressionNode.h
new file mode 100644
index 0000000..847a00a
--- /dev/null
+++ b/Source/cmGeneratorExpressionNode.h
@@ -0,0 +1,70 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2012 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 cmGeneratorExpressionNode_h
+#define cmGeneratorExpressionNode_h
+
+#include "cmMakefile.h"
+
+#include "cmGeneratorExpressionEvaluator.h"
+#include "cmGeneratorExpressionParser.h"
+#include "cmGeneratorExpressionDAGChecker.h"
+#include "cmGeneratorExpression.h"
+#include "cmLocalGenerator.h"
+#include "cmSourceFile.h"
+
+#include <cmsys/String.h>
+
+#include <assert.h>
+#include <errno.h>
+
+#include "cmListFileCache.h"
+
+//----------------------------------------------------------------------------
+struct cmGeneratorExpressionNode
+{
+ enum {
+ DynamicParameters = 0,
+ OneOrMoreParameters = -1,
+ OneOrZeroParameters = -2
+ };
+ virtual ~cmGeneratorExpressionNode() {}
+
+ virtual bool GeneratesContent() const { return true; }
+
+ virtual bool RequiresLiteralInput() const { return false; }
+
+ virtual bool AcceptsArbitraryContentParameter() const
+ { return false; }
+
+ virtual int NumExpectedParameters() const { return 1; }
+
+ virtual std::string Evaluate(const std::vector<std::string> &parameters,
+ cmGeneratorExpressionContext *context,
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *dagChecker
+ ) const = 0;
+
+ static std::string EvaluateDependentExpression(
+ std::string const& prop, cmMakefile *makefile,
+ cmGeneratorExpressionContext *context,
+ cmTarget const* headTarget, cmTarget const* currentTarget,
+ cmGeneratorExpressionDAGChecker *dagChecker);
+
+ static const cmGeneratorExpressionNode* GetNode(
+ const std::string &identifier);
+};
+
+//----------------------------------------------------------------------------
+void reportError(cmGeneratorExpressionContext *context,
+ const std::string &expr, const std::string &result);
+
+#endif
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 44c9e9a..e0af47a 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -20,6 +20,7 @@
#include "cmGeneratorExpressionDAGChecker.h"
#include "cmComputeLinkInformation.h"
#include "cmCustomCommandGenerator.h"
+#include "cmAlgorithms.h"
#include <queue>
@@ -960,9 +961,10 @@ cmGeneratorTarget::GetCreateRuleVariable(std::string const& lang,
//----------------------------------------------------------------------------
std::vector<std::string>
-cmGeneratorTarget::GetIncludeDirectories(const std::string& config) const
+cmGeneratorTarget::GetIncludeDirectories(const std::string& config,
+ const std::string& lang) const
{
- return this->Target->GetIncludeDirectories(config);
+ return this->Target->GetIncludeDirectories(config, lang);
}
//----------------------------------------------------------------------------
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 2083b88..c329cf5 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -85,7 +85,7 @@ public:
/** Get the include directories for this target. */
std::vector<std::string> GetIncludeDirectories(
- const std::string& config) const;
+ const std::string& config, const std::string& lang) const;
bool IsSystemIncludeDirectory(const std::string& dir,
const std::string& config) const;
diff --git a/Source/cmGetCMakePropertyCommand.cxx b/Source/cmGetCMakePropertyCommand.cxx
index fd18596..85aa31f 100644
--- a/Source/cmGetCMakePropertyCommand.cxx
+++ b/Source/cmGetCMakePropertyCommand.cxx
@@ -14,6 +14,7 @@
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmake.h"
+#include "cmAlgorithms.h"
// cmGetCMakePropertyCommand
bool cmGetCMakePropertyCommand
diff --git a/Source/cmGlobalBorlandMakefileGenerator.cxx b/Source/cmGlobalBorlandMakefileGenerator.cxx
index 950d440..6c20952 100644
--- a/Source/cmGlobalBorlandMakefileGenerator.cxx
+++ b/Source/cmGlobalBorlandMakefileGenerator.cxx
@@ -49,7 +49,6 @@ cmLocalGenerator *cmGlobalBorlandMakefileGenerator::CreateLocalGenerator()
lg->SetUnixCD(false);
lg->SetMakeCommandEscapeTargetTwice(true);
lg->SetBorlandMakeCurlyHack(true);
- lg->SetNoMultiOutputMultiDepRules(true);
return lg;
}
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 36395aa..8123c99 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -32,6 +32,7 @@
#include "cmGeneratorExpressionEvaluationFile.h"
#include "cmExportBuildFileGenerator.h"
#include "cmCPackPropertiesGenerator.h"
+#include "cmAlgorithms.h"
#include <cmsys/Directory.hxx>
#include <cmsys/FStream.hxx>
@@ -1717,6 +1718,19 @@ int cmGlobalGenerator::Build(
std::string outputBuffer;
std::string* outputPtr = &outputBuffer;
+ std::vector<std::string> makeCommand;
+ this->GenerateBuildCommand(makeCommand, makeCommandCSTR, projectName,
+ bindir, target, config, fast, verbose,
+ nativeOptions);
+
+ // Workaround to convince VCExpress.exe to produce output.
+ if (outputflag == cmSystemTools::OUTPUT_PASSTHROUGH &&
+ !makeCommand.empty() && cmSystemTools::LowerCase(
+ cmSystemTools::GetFilenameName(makeCommand[0])) == "vcexpress.exe")
+ {
+ outputflag = cmSystemTools::OUTPUT_NORMAL;
+ }
+
// should we do a clean first?
if (clean)
{
@@ -1743,10 +1757,6 @@ int cmGlobalGenerator::Build(
}
// now build
- std::vector<std::string> makeCommand;
- this->GenerateBuildCommand(makeCommand, makeCommandCSTR, projectName,
- bindir, target, config, fast, verbose,
- nativeOptions);
std::string makeCommandStr = cmSystemTools::PrintSingleCommand(makeCommand);
output += "\nRun Build Command:";
output += makeCommandStr;
diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx
index 69b1a9d..ac7a6eb 100644
--- a/Source/cmGlobalNinjaGenerator.cxx
+++ b/Source/cmGlobalNinjaGenerator.cxx
@@ -1069,7 +1069,7 @@ void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os)
this->WritePhonyBuild(os,
"",
deps,
- deps);
+ cmNinjaDeps());
}
}
}
diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx
index 1d2dd34..7648813 100644
--- a/Source/cmGlobalUnixMakefileGenerator3.cxx
+++ b/Source/cmGlobalUnixMakefileGenerator3.cxx
@@ -18,6 +18,7 @@
#include "cmSourceFile.h"
#include "cmTarget.h"
#include "cmGeneratorTarget.h"
+#include "cmAlgorithms.h"
cmGlobalUnixMakefileGenerator3::cmGlobalUnixMakefileGenerator3()
{
@@ -563,7 +564,7 @@ void cmGlobalUnixMakefileGenerator3
// Since we have full control over the invocation of nmake, let us
// make it quiet.
- if ( this->GetName() == "NMake Makefiles" )
+ if (cmHasLiteralPrefix(this->GetName(), "NMake Makefiles"))
{
makeCommand.push_back("/NOLOGO");
}
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index 7df2073..18d40e1 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -17,6 +17,7 @@
#include "cmVisualStudioSlnData.h"
#include "cmVisualStudioSlnParser.h"
#include "cmake.h"
+#include "cmAlgorithms.h"
static const char vs10generatorName[] = "Visual Studio 10 2010";
diff --git a/Source/cmGlobalVisualStudio11Generator.cxx b/Source/cmGlobalVisualStudio11Generator.cxx
index 3013200..ed828b6 100644
--- a/Source/cmGlobalVisualStudio11Generator.cxx
+++ b/Source/cmGlobalVisualStudio11Generator.cxx
@@ -12,6 +12,7 @@
#include "cmGlobalVisualStudio11Generator.h"
#include "cmLocalVisualStudio10Generator.h"
#include "cmMakefile.h"
+#include "cmAlgorithms.h"
static const char vs11generatorName[] = "Visual Studio 11 2012";
diff --git a/Source/cmGlobalVisualStudio12Generator.cxx b/Source/cmGlobalVisualStudio12Generator.cxx
index 2bc9379..c2e6f47 100644
--- a/Source/cmGlobalVisualStudio12Generator.cxx
+++ b/Source/cmGlobalVisualStudio12Generator.cxx
@@ -12,6 +12,7 @@
#include "cmGlobalVisualStudio12Generator.h"
#include "cmLocalVisualStudio10Generator.h"
#include "cmMakefile.h"
+#include "cmAlgorithms.h"
static const char vs12generatorName[] = "Visual Studio 12 2013";
diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx
index fe702c0..b551c65 100644
--- a/Source/cmGlobalVisualStudio14Generator.cxx
+++ b/Source/cmGlobalVisualStudio14Generator.cxx
@@ -12,6 +12,7 @@
#include "cmGlobalVisualStudio14Generator.h"
#include "cmLocalVisualStudio10Generator.h"
#include "cmMakefile.h"
+#include "cmAlgorithms.h"
static const char vs14generatorName[] = "Visual Studio 14 2015";
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index e89161d..bd8a1f5 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -1803,7 +1803,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
}
cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&target);
std::vector<std::string> targetDefines;
- target.GetCompileDefinitions(targetDefines, configName);
+ target.GetCompileDefinitions(targetDefines, configName, "C");
this->AppendDefines(ppDefs, targetDefines);
buildSettings->AddAttribute
("GCC_PREPROCESSOR_DEFINITIONS", ppDefs.CreateList());
diff --git a/Source/cmInstalledFile.cxx b/Source/cmInstalledFile.cxx
index 4b53752..8c52b48 100644
--- a/Source/cmInstalledFile.cxx
+++ b/Source/cmInstalledFile.cxx
@@ -12,6 +12,7 @@
#include "cmInstalledFile.h"
#include "cmSystemTools.h"
#include "cmMakefile.h"
+#include "cmAlgorithms.h"
//----------------------------------------------------------------------------
cmInstalledFile::cmInstalledFile():
@@ -29,6 +30,16 @@ cmInstalledFile::~cmInstalledFile()
}
}
+cmInstalledFile::Property::Property()
+{
+
+}
+
+cmInstalledFile::Property::~Property()
+{
+ cmDeleteAll(this->ValueExpressions);
+}
+
//----------------------------------------------------------------------------
void cmInstalledFile::SetName(cmMakefile* mf, const std::string& name)
{
diff --git a/Source/cmInstalledFile.h b/Source/cmInstalledFile.h
index cdb0866..3af90a7 100644
--- a/Source/cmInstalledFile.h
+++ b/Source/cmInstalledFile.h
@@ -13,7 +13,6 @@
#define cmInstalledFile_h
#include "cmGeneratorExpression.h"
-#include "cmAlgorithms.h"
/** \class cmInstalledFile
* \brief Represents a file intended for installation.
@@ -32,15 +31,8 @@ public:
struct Property
{
- Property()
- {
-
- }
-
- ~Property()
- {
- cmDeleteAll(this->ValueExpressions);
- }
+ Property();
+ ~Property();
ExpressionVectorType ValueExpressions;
};
diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx
index 17617aa..d18269d 100644
--- a/Source/cmListCommand.cxx
+++ b/Source/cmListCommand.cxx
@@ -12,6 +12,7 @@
#include "cmListCommand.h"
#include <cmsys/RegularExpression.hxx>
#include <cmsys/SystemTools.hxx>
+#include "cmAlgorithms.h"
#include <stdlib.h> // required for atoi
#include <ctype.h>
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 7c83f27..e1998e4 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -25,6 +25,7 @@
#include "cmCustomCommandGenerator.h"
#include "cmVersion.h"
#include "cmake.h"
+#include "cmAlgorithms.h"
#if defined(CMAKE_BUILD_WITH_CMAKE)
# define CM_LG_ENCODE_OBJECT_NAMES
@@ -1428,11 +1429,11 @@ std::string cmLocalGenerator::GetIncludeFlags(
//----------------------------------------------------------------------------
void cmLocalGenerator::AddCompileDefinitions(std::set<std::string>& defines,
cmTarget const* target,
- const std::string& config)
+ const std::string& config,
+ const std::string& lang)
{
std::vector<std::string> targetDefines;
- target->GetCompileDefinitions(targetDefines,
- config);
+ target->GetCompileDefinitions(targetDefines, config, lang);
this->AppendDefines(defines, targetDefines);
}
@@ -1453,7 +1454,7 @@ void cmLocalGenerator::AddCompileOptions(
{
cmSystemTools::ParseWindowsCommandLine(targetFlags, opts);
}
- target->GetCompileOptions(opts, config);
+ target->GetCompileOptions(opts, config, lang);
for(std::vector<std::string>::const_iterator i = opts.begin();
i != opts.end(); ++i)
{
@@ -1474,7 +1475,7 @@ void cmLocalGenerator::AddCompileOptions(
this->AppendFlags(flags, targetFlags);
}
std::vector<std::string> opts;
- target->GetCompileOptions(opts, config);
+ target->GetCompileOptions(opts, config, lang);
for(std::vector<std::string>::const_iterator i = opts.begin();
i != opts.end(); ++i)
{
@@ -1600,7 +1601,7 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
// Get the target-specific include directories.
std::vector<std::string> includes;
- includes = target->GetIncludeDirectories(config);
+ includes = target->GetIncludeDirectories(config, lang);
// Support putting all the in-project include directories first if
// it is requested by the project.
diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h
index 3a9d5be..6cdee42 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -130,7 +130,7 @@ public:
std::string ConvertToOptionallyRelativeOutputPath(const std::string& remote);
///! set/get the parent generator
- cmLocalGenerator* GetParent(){return this->Parent;}
+ cmLocalGenerator* GetParent() const {return this->Parent;}
void SetParent(cmLocalGenerator* g) { this->Parent = g; g->AddChild(this); }
///! set/get the children
@@ -239,7 +239,8 @@ public:
const std::string& lang, const std::string& config);
void AddCompileDefinitions(std::set<std::string>& defines,
cmTarget const* target,
- const std::string& config);
+ const std::string& config,
+ const std::string& lang);
/** Compute the language used to compile the given source file. */
std::string GetSourceFileLanguage(const cmSourceFile& source);
diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx
index 413dc0f..640c1b3 100644
--- a/Source/cmLocalNinjaGenerator.cxx
+++ b/Source/cmLocalNinjaGenerator.cxx
@@ -182,8 +182,7 @@ cmake* cmLocalNinjaGenerator::GetCMakeInstance()
bool cmLocalNinjaGenerator::isRootMakefile() const
{
- return (strcmp(this->Makefile->GetCurrentDirectory(),
- this->GetCMakeInstance()->GetHomeDirectory()) == 0);
+ return !this->GetParent();
}
void cmLocalNinjaGenerator::WriteBuildFileTop()
diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx
index 432cb3a..8938e67 100644
--- a/Source/cmLocalUnixMakefileGenerator3.cxx
+++ b/Source/cmLocalUnixMakefileGenerator3.cxx
@@ -20,6 +20,7 @@
#include "cmVersion.h"
#include "cmFileTimeComparison.h"
#include "cmCustomCommandGenerator.h"
+#include "cmAlgorithms.h"
// Include dependency scanners for supported languages. Only the
// C/C++ scanner is needed for bootstrapping CMake.
@@ -92,7 +93,6 @@ cmLocalUnixMakefileGenerator3::cmLocalUnixMakefileGenerator3()
this->SkipAssemblySourceRules = false;
this->MakeCommandEscapeTargetTwice = false;
this->BorlandMakeCurlyHack = false;
- this->NoMultiOutputMultiDepRules = false;
}
//----------------------------------------------------------------------------
@@ -600,7 +600,6 @@ const std::string &cmLocalUnixMakefileGenerator3::GetHomeRelativeOutputPath()
return this->HomeRelativeOutputPath;
}
-
//----------------------------------------------------------------------------
void
cmLocalUnixMakefileGenerator3
@@ -619,30 +618,6 @@ cmLocalUnixMakefileGenerator3
comment);
return;
}
- std::vector<std::string> outputs(1, target);
- this->WriteMakeRule(os, comment,
- outputs, depends, commands,
- symbolic, in_help);
-}
-
-//----------------------------------------------------------------------------
-void
-cmLocalUnixMakefileGenerator3
-::WriteMakeRule(std::ostream& os,
- const char* comment,
- const std::vector<std::string>& outputs,
- const std::vector<std::string>& depends,
- const std::vector<std::string>& commands,
- bool symbolic,
- bool in_help)
-{
- // Make sure there is an output.
- if(outputs.empty())
- {
- cmSystemTools::Error("No outputs for WriteMakeRule! called with comment: ",
- comment);
- return;
- }
std::string replace;
@@ -661,17 +636,7 @@ cmLocalUnixMakefileGenerator3
}
// Construct the left hand side of the rule.
- std::string tgt;
- {
- const char* sep = "";
- for (std::vector<std::string>::const_iterator i = outputs.begin();
- i != outputs.end(); ++i)
- {
- tgt += sep;
- tgt += this->Convert(*i,HOME_OUTPUT,MAKERULE);
- sep = " ";
- }
- }
+ std::string tgt = this->Convert(target, HOME_OUTPUT, MAKERULE);
const char* space = "";
if(tgt.size() == 1)
@@ -697,19 +662,6 @@ cmLocalUnixMakefileGenerator3
// No dependencies. The commands will always run.
os << cmMakeSafe(tgt) << space << ":\n";
}
- else if(this->NoMultiOutputMultiDepRules && outputs.size() >= 2)
- {
- // Borland make does not understand multiple dependency rules when
- // there are multiple outputs, so write them all on one line.
- os << cmMakeSafe(tgt) << space << ":";
- for(std::vector<std::string>::const_iterator dep = depends.begin();
- dep != depends.end(); ++dep)
- {
- replace = this->Convert(*dep, HOME_OUTPUT, MAKERULE);
- os << " " << cmMakeSafe(replace);
- }
- os << "\n";
- }
else
{
// Split dependencies into multiple rule lines. This allows for
@@ -733,8 +685,7 @@ cmLocalUnixMakefileGenerator3
// Add the output to the local help if requested.
if(in_help)
{
- this->LocalHelp.insert(this->LocalHelp.end(),
- outputs.begin(), outputs.end());
+ this->LocalHelp.push_back(target);
}
}
@@ -1754,8 +1705,6 @@ cmLocalUnixMakefileGenerator3
//----------------------------------------------------------------------------
void cmLocalUnixMakefileGenerator3::CheckMultipleOutputs(bool verbose)
{
- // Nothing populates multiple output pairs anymore, but we need to
- // honor it when working in a build tree generated by an older CMake.
cmMakefile* mf = this->Makefile;
// Get the string listing the multiple output pairs.
@@ -2094,23 +2043,49 @@ void cmLocalUnixMakefileGenerator3
<< "set(CMAKE_" << l->first << "_COMPILER_ID \""
<< cid << "\")\n";
}
- }
- // Build a list of preprocessor definitions for the target.
- std::set<std::string> defines;
- this->AddCompileDefinitions(defines, &target,
- this->ConfigurationName);
- if(!defines.empty())
- {
+ // Build a list of preprocessor definitions for the target.
+ std::set<std::string> defines;
+ this->AddCompileDefinitions(defines, &target,
+ this->ConfigurationName, l->first);
+ if(!defines.empty())
+ {
+ cmakefileStream
+ << "\n"
+ << "# Preprocessor definitions for this target.\n"
+ << "set(CMAKE_TARGET_DEFINITIONS_" << l->first << "\n";
+ for(std::set<std::string>::const_iterator di = defines.begin();
+ di != defines.end(); ++di)
+ {
+ cmakefileStream
+ << " " << this->EscapeForCMake(*di) << "\n";
+ }
+ cmakefileStream
+ << " )\n";
+ }
+
+ // Target-specific include directories:
cmakefileStream
<< "\n"
- << "# Preprocessor definitions for this target.\n"
- << "set(CMAKE_TARGET_DEFINITIONS\n";
- for(std::set<std::string>::const_iterator di = defines.begin();
- di != defines.end(); ++di)
+ << "# The include file search paths:\n";
+ cmakefileStream
+ << "set(CMAKE_" << l->first << "_TARGET_INCLUDE_PATH\n";
+ std::vector<std::string> includes;
+
+ cmGeneratorTarget* gt = this->GetGlobalGenerator()
+ ->GetGeneratorTarget(&target);
+
+ const std::string& config =
+ this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
+ this->GetIncludeDirectories(includes, gt,
+ l->first, config);
+ for(std::vector<std::string>::iterator i = includes.begin();
+ i != includes.end(); ++i)
{
cmakefileStream
- << " " << this->EscapeForCMake(*di) << "\n";
+ << " \""
+ << this->Convert(*i, cmLocalGenerator::HOME_OUTPUT)
+ << "\"\n";
}
cmakefileStream
<< " )\n";
diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h
index 1ff5e7f..a2f4245 100644
--- a/Source/cmLocalUnixMakefileGenerator3.h
+++ b/Source/cmLocalUnixMakefileGenerator3.h
@@ -61,13 +61,6 @@ public:
const std::vector<std::string>& commands,
bool symbolic,
bool in_help = false);
- void WriteMakeRule(std::ostream& os,
- const char* comment,
- const std::vector<std::string>& outputs,
- const std::vector<std::string>& depends,
- const std::vector<std::string>& commands,
- bool symbolic,
- bool in_help = false);
// write the main variables used by the makefiles
void WriteMakeVariables(std::ostream& makefileStream);
@@ -161,9 +154,6 @@ public:
void SetBorlandMakeCurlyHack(bool b)
{ this->BorlandMakeCurlyHack = b; }
- void SetNoMultiOutputMultiDepRules(bool b)
- { this->NoMultiOutputMultiDepRules = b; }
-
// used in writing out Cmake files such as WriteDirectoryInformation
static void WriteCMakeArgument(std::ostream& os, const char* s);
@@ -349,7 +339,6 @@ private:
bool PassMakeflags;
bool MakeCommandEscapeTargetTwice;
bool BorlandMakeCurlyHack;
- bool NoMultiOutputMultiDepRules;
//==========================================================================
std::string HomeRelativeOutputPath;
diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx
index 1d62093..2b999eb 100644
--- a/Source/cmLocalVisualStudio6Generator.cxx
+++ b/Source/cmLocalVisualStudio6Generator.cxx
@@ -1701,15 +1701,15 @@ void cmLocalVisualStudio6Generator
= this->Makefile->GetDefinition("CMAKE_DEBUG_POSTFIX");
cmSystemTools::ReplaceString(line, "DEBUG_POSTFIX",
debugPostfix?debugPostfix:"");
- // store flags for each configuration
- std::string flags = " ";
- std::string flagsRelease = " ";
- std::string flagsMinSizeRel = " ";
- std::string flagsDebug = " ";
- std::string flagsRelWithDebInfo = " ";
if(target.GetType() >= cmTarget::EXECUTABLE &&
target.GetType() <= cmTarget::OBJECT_LIBRARY)
{
+ // store flags for each configuration
+ std::string flags = " ";
+ std::string flagsRelease = " ";
+ std::string flagsMinSizeRel = " ";
+ std::string flagsDebug = " ";
+ std::string flagsRelWithDebInfo = " ";
std::vector<std::string> configs;
target.GetMakefile()->GetConfigurations(configs);
std::vector<std::string>::const_iterator it = configs.begin();
@@ -1760,72 +1760,77 @@ void cmLocalVisualStudio6Generator
"MinSizeRel");
this->AddCompileOptions(flagsRelWithDebInfo, &target, linkLanguage,
"RelWithDebInfo");
- }
- // if _UNICODE and _SBCS are not found, then add -D_MBCS
- std::string defs = this->Makefile->GetDefineFlags();
- if(flags.find("D_UNICODE") == flags.npos &&
- defs.find("D_UNICODE") == flags.npos &&
- flags.find("D_SBCS") == flags.npos &&
- defs.find("D_SBCS") == flags.npos)
- {
- flags += " /D \"_MBCS\"";
- }
+ // if _UNICODE and _SBCS are not found, then add -D_MBCS
+ std::string defs = this->Makefile->GetDefineFlags();
+ if(flags.find("D_UNICODE") == flags.npos &&
+ defs.find("D_UNICODE") == flags.npos &&
+ flags.find("D_SBCS") == flags.npos &&
+ defs.find("D_SBCS") == flags.npos)
+ {
+ flags += " /D \"_MBCS\"";
+ }
- // Add per-target and per-configuration preprocessor definitions.
- std::set<std::string> definesSet;
- std::set<std::string> debugDefinesSet;
- std::set<std::string> releaseDefinesSet;
- std::set<std::string> minsizeDefinesSet;
- std::set<std::string> debugrelDefinesSet;
-
- this->AddCompileDefinitions(definesSet, &target, "");
- this->AddCompileDefinitions(debugDefinesSet, &target, "DEBUG");
- this->AddCompileDefinitions(releaseDefinesSet, &target, "RELEASE");
- this->AddCompileDefinitions(minsizeDefinesSet, &target, "MINSIZEREL");
- this->AddCompileDefinitions(debugrelDefinesSet, &target, "RELWITHDEBINFO");
-
- std::string defines = " ";
- std::string debugDefines = " ";
- std::string releaseDefines = " ";
- std::string minsizeDefines = " ";
- std::string debugrelDefines = " ";
-
- this->JoinDefines(definesSet, defines, "");
- this->JoinDefines(debugDefinesSet, debugDefines, "");
- this->JoinDefines(releaseDefinesSet, releaseDefines, "");
- this->JoinDefines(minsizeDefinesSet, minsizeDefines, "");
- this->JoinDefines(debugrelDefinesSet, debugrelDefines, "");
-
- flags += defines;
- flagsDebug += debugDefines;
- flagsRelease += releaseDefines;
- flagsMinSizeRel += minsizeDefines;
- flagsRelWithDebInfo += debugrelDefines;
-
- // The template files have CXX FLAGS in them, that need to be replaced.
- // There are not separate CXX and C template files, so we use the same
- // variable names. The previous code sets up flags* variables to contain
- // the correct C or CXX flags
- cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_MINSIZEREL",
- flagsMinSizeRel.c_str());
- cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_DEBUG",
- flagsDebug.c_str());
- cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_RELWITHDEBINFO",
- flagsRelWithDebInfo.c_str());
- cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_RELEASE",
- flagsRelease.c_str());
- cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS", flags.c_str());
-
- cmSystemTools::ReplaceString(line, "COMPILE_DEFINITIONS_MINSIZEREL",
- minsizeDefines.c_str());
- cmSystemTools::ReplaceString(line, "COMPILE_DEFINITIONS_DEBUG",
- debugDefines.c_str());
- cmSystemTools::ReplaceString(line, "COMPILE_DEFINITIONS_RELWITHDEBINFO",
- debugrelDefines.c_str());
- cmSystemTools::ReplaceString(line, "COMPILE_DEFINITIONS_RELEASE",
- releaseDefines.c_str());
- cmSystemTools::ReplaceString(line, "COMPILE_DEFINITIONS", defines.c_str());
+ // Add per-target and per-configuration preprocessor definitions.
+ std::set<std::string> definesSet;
+ std::set<std::string> debugDefinesSet;
+ std::set<std::string> releaseDefinesSet;
+ std::set<std::string> minsizeDefinesSet;
+ std::set<std::string> debugrelDefinesSet;
+
+ this->AddCompileDefinitions(definesSet, &target, "", linkLanguage);
+ this->AddCompileDefinitions(debugDefinesSet, &target,
+ "DEBUG", linkLanguage);
+ this->AddCompileDefinitions(releaseDefinesSet, &target,
+ "RELEASE", linkLanguage);
+ this->AddCompileDefinitions(minsizeDefinesSet, &target,
+ "MINSIZEREL", linkLanguage);
+ this->AddCompileDefinitions(debugrelDefinesSet, &target,
+ "RELWITHDEBINFO", linkLanguage);
+
+ std::string defines = " ";
+ std::string debugDefines = " ";
+ std::string releaseDefines = " ";
+ std::string minsizeDefines = " ";
+ std::string debugrelDefines = " ";
+
+ this->JoinDefines(definesSet, defines, "");
+ this->JoinDefines(debugDefinesSet, debugDefines, "");
+ this->JoinDefines(releaseDefinesSet, releaseDefines, "");
+ this->JoinDefines(minsizeDefinesSet, minsizeDefines, "");
+ this->JoinDefines(debugrelDefinesSet, debugrelDefines, "");
+
+ flags += defines;
+ flagsDebug += debugDefines;
+ flagsRelease += releaseDefines;
+ flagsMinSizeRel += minsizeDefines;
+ flagsRelWithDebInfo += debugrelDefines;
+
+ // The template files have CXX FLAGS in them, that need to be replaced.
+ // There are not separate CXX and C template files, so we use the same
+ // variable names. The previous code sets up flags* variables to
+ // contain the correct C or CXX flags
+ cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_MINSIZEREL",
+ flagsMinSizeRel.c_str());
+ cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_DEBUG",
+ flagsDebug.c_str());
+ cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_RELWITHDEBINFO",
+ flagsRelWithDebInfo.c_str());
+ cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_RELEASE",
+ flagsRelease.c_str());
+ cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS", flags.c_str());
+
+ cmSystemTools::ReplaceString(line, "COMPILE_DEFINITIONS_MINSIZEREL",
+ minsizeDefines.c_str());
+ cmSystemTools::ReplaceString(line, "COMPILE_DEFINITIONS_DEBUG",
+ debugDefines.c_str());
+ cmSystemTools::ReplaceString(line, "COMPILE_DEFINITIONS_RELWITHDEBINFO",
+ debugrelDefines.c_str());
+ cmSystemTools::ReplaceString(line, "COMPILE_DEFINITIONS_RELEASE",
+ releaseDefines.c_str());
+ cmSystemTools::ReplaceString(line, "COMPILE_DEFINITIONS",
+ defines.c_str());
+ }
fout << line.c_str() << std::endl;
}
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index ed560aa..c4abeb2 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -391,6 +391,13 @@ cmVS7FlagTable cmLocalVisualStudio7GeneratorFortranFlagTable[] =
{"OptimizeForProcessor", "QxT", "", "codeExclusivelyCore2Duo", 0},
{"OptimizeForProcessor", "QxO", "", "codeExclusivelyCore2StreamingSIMD", 0},
{"OptimizeForProcessor", "QxS", "", "codeExclusivelyCore2StreamingSIMD4", 0},
+ {"OpenMP", "Qopenmp", "", "OpenMPParallelCode", 0},
+ {"OpenMP", "Qopenmp-stubs", "", "OpenMPSequentialCode", 0},
+ {"Traceback", "traceback", "", "true", 0},
+ {"Traceback", "notraceback", "", "false", 0},
+ {"FloatingPointExceptionHandling", "fpe:0", "", "fpe0", 0},
+ {"FloatingPointExceptionHandling", "fpe:1", "", "fpe1", 0},
+ {"FloatingPointExceptionHandling", "fpe:3", "", "fpe3", 0},
{"ModulePath", "module:", "", "",
cmVS7FlagTable::UserValueRequired},
@@ -775,7 +782,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
cmGeneratorTarget* gt =
this->GlobalGenerator->GetGeneratorTarget(&target);
std::vector<std::string> targetDefines;
- target.GetCompileDefinitions(targetDefines, configName);
+ target.GetCompileDefinitions(targetDefines, configName, "CXX");
targetOptions.AddDefines(targetDefines);
targetOptions.SetVerboseMakefile(
this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));
diff --git a/Source/cmMacroCommand.cxx b/Source/cmMacroCommand.cxx
index 12c8576..b7cbae6 100644
--- a/Source/cmMacroCommand.cxx
+++ b/Source/cmMacroCommand.cxx
@@ -12,6 +12,7 @@
#include "cmMacroCommand.h"
#include "cmake.h"
+#include "cmAlgorithms.h"
// define the class for macro commands
class cmMacroHelperCommand : public cmCommand
diff --git a/Source/cmMakeDepend.cxx b/Source/cmMakeDepend.cxx
index 31bbb73..a6d4e58 100644
--- a/Source/cmMakeDepend.cxx
+++ b/Source/cmMakeDepend.cxx
@@ -12,6 +12,7 @@
#include "cmMakeDepend.h"
#include "cmSystemTools.h"
#include "cmGeneratorExpression.h"
+#include "cmAlgorithms.h"
#include <cmsys/RegularExpression.hxx>
#include <cmsys/FStream.hxx>
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index ccfe2b1..eeb9c72 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -30,6 +30,7 @@
#include "cmInstallGenerator.h"
#include "cmTestGenerator.h"
#include "cmDefinitions.h"
+#include "cmAlgorithms.h"
#include "cmake.h"
#include <stdlib.h> // required for atoi
@@ -985,6 +986,33 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
}
else
{
+ std::ostringstream e;
+ cmake::MessageType messageType = cmake::AUTHOR_WARNING;
+ bool issueMessage = false;
+
+ switch(this->GetPolicyStatus(cmPolicies::CMP0057))
+ {
+ case cmPolicies::WARN:
+ e << (this->GetPolicies()->
+ GetPolicyWarning(cmPolicies::CMP0057)) << "\n";
+ issueMessage = true;
+ case cmPolicies::OLD:
+ break;
+ case cmPolicies::NEW:
+ case cmPolicies::REQUIRED_IF_USED:
+ case cmPolicies::REQUIRED_ALWAYS:
+ issueMessage = true;
+ messageType = cmake::FATAL_ERROR;
+ break;
+ }
+
+ if(issueMessage)
+ {
+ e << "\"" << main_dependency << "\" can only be specified as a "
+ "custom command MAIN_DEPENDENCY once.";
+ IssueMessage(messageType, e.str());
+ }
+
// The existing custom command is different. We need to
// generate a rule file for this new command.
file = 0;
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index 84761cc..fcb76c3 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -769,9 +769,8 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
}
// Write the build rule.
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
- outputs, depends, commands, false);
-
+ this->WriteMakeRule(*this->BuildFileStream, 0, outputs,
+ depends, commands, false);
// Write the main driver rule to build everything in this target.
this->WriteTargetDriverRule(targetFullPath, relink);
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 20207f5..641cd23 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -329,7 +329,7 @@ std::string cmMakefileTargetGenerator::GetDefines(const std::string &l)
// Add preprocessor definitions for this target and configuration.
this->LocalGenerator->AddCompileDefinitions(defines, this->Target,
- this->LocalGenerator->ConfigurationName);
+ this->LocalGenerator->ConfigurationName, l);
std::string definesString;
this->LocalGenerator->JoinDefines(defines, definesString, lang);
@@ -769,8 +769,8 @@ cmMakefileTargetGenerator
}
// Write the rule.
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
- outputs, depends, commands, false);
+ this->WriteMakeRule(*this->BuildFileStream, 0, outputs,
+ depends, commands, false);
bool do_preprocess_rules = lang_has_preprocessor &&
this->LocalGenerator->GetCreatePreprocessedSourceRules();
@@ -991,6 +991,57 @@ void cmMakefileTargetGenerator::WriteTargetCleanRules()
depends, commands, true);
}
+//----------------------------------------------------------------------------
+void cmMakefileTargetGenerator::WriteMakeRule(
+ std::ostream& os,
+ const char* comment,
+ const std::vector<std::string>& outputs,
+ const std::vector<std::string>& depends,
+ const std::vector<std::string>& commands,
+ bool symbolic,
+ bool in_help)
+{
+ if (outputs.size() == 0)
+ {
+ return;
+ }
+
+ // We always attach the actual commands to the first output.
+ this->LocalGenerator->WriteMakeRule(os, comment, outputs[0], depends,
+ commands, symbolic, in_help);
+
+ // For single outputs, we are done.
+ if (outputs.size() == 1)
+ {
+ return;
+ }
+
+ // For multiple outputs, make the extra ones depend on the first one.
+ std::vector<std::string> const output_depends(1, outputs[0]);
+ for (std::vector<std::string>::const_iterator o = outputs.begin()+1;
+ o != outputs.end(); ++o)
+ {
+ // Touch the extra output so "make" knows that it was updated,
+ // but only if the output was acually created.
+ std::string const out = this->Convert(*o, cmLocalGenerator::HOME_OUTPUT,
+ cmLocalGenerator::SHELL);
+ std::vector<std::string> output_commands;
+ if (!symbolic)
+ {
+ output_commands.push_back("@$(CMAKE_COMMAND) -E touch_nocreate " + out);
+ }
+ this->LocalGenerator->WriteMakeRule(os, 0, *o, output_depends,
+ output_commands, symbolic, in_help);
+
+ if (!symbolic)
+ {
+ // At build time, remove the first output if this one does not exist
+ // so that "make" will rerun the real commands that create this one.
+ MultipleOutputPairsType::value_type p(*o, outputs[0]);
+ this->MultipleOutputPairs.insert(p);
+ }
+ }
+}
//----------------------------------------------------------------------------
void cmMakefileTargetGenerator::WriteTargetDependRules()
@@ -1011,6 +1062,25 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
this->LocalGenerator->
WriteDependLanguageInfo(*this->InfoFileStream,*this->Target);
+ // Store multiple output pairs in the depend info file.
+ if(!this->MultipleOutputPairs.empty())
+ {
+ *this->InfoFileStream
+ << "\n"
+ << "# Pairs of files generated by the same build rule.\n"
+ << "set(CMAKE_MULTIPLE_OUTPUT_PAIRS\n";
+ for(MultipleOutputPairsType::const_iterator pi =
+ this->MultipleOutputPairs.begin();
+ pi != this->MultipleOutputPairs.end(); ++pi)
+ {
+ *this->InfoFileStream
+ << " " << this->LocalGenerator->EscapeForCMake(pi->first)
+ << " " << this->LocalGenerator->EscapeForCMake(pi->second)
+ << "\n";
+ }
+ *this->InfoFileStream << " )\n\n";
+ }
+
// Store list of targets linked directly or transitively.
{
*this->InfoFileStream
@@ -1056,40 +1126,6 @@ void cmMakefileTargetGenerator::WriteTargetDependRules()
<< "set(CMAKE_Fortran_TARGET_MODULE_DIR \"" << mdir << "\")\n";
}
- // Target-specific include directories:
- *this->InfoFileStream
- << "\n"
- << "# The include file search paths:\n";
- *this->InfoFileStream
- << "set(CMAKE_C_TARGET_INCLUDE_PATH\n";
- std::vector<std::string> includes;
-
- const std::string& config =
- this->Makefile->GetSafeDefinition("CMAKE_BUILD_TYPE");
- this->LocalGenerator->GetIncludeDirectories(includes,
- this->GeneratorTarget,
- "C", config);
- for(std::vector<std::string>::iterator i = includes.begin();
- i != includes.end(); ++i)
- {
- *this->InfoFileStream
- << " \""
- << this->LocalGenerator->Convert(*i,
- cmLocalGenerator::HOME_OUTPUT)
- << "\"\n";
- }
- *this->InfoFileStream
- << " )\n";
- *this->InfoFileStream
- << "set(CMAKE_CXX_TARGET_INCLUDE_PATH "
- << "${CMAKE_C_TARGET_INCLUDE_PATH})\n";
- *this->InfoFileStream
- << "set(CMAKE_Fortran_TARGET_INCLUDE_PATH "
- << "${CMAKE_C_TARGET_INCLUDE_PATH})\n";
- *this->InfoFileStream
- << "set(CMAKE_ASM_TARGET_INCLUDE_PATH "
- << "${CMAKE_C_TARGET_INCLUDE_PATH})\n";
-
// and now write the rule to use it
std::vector<std::string> depends;
std::vector<std::string> commands;
@@ -1240,9 +1276,8 @@ void cmMakefileTargetGenerator
symbolic = sf->GetPropertyAsBool("SYMBOLIC");
}
}
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
- outputs, depends, commands,
- symbolic);
+ this->WriteMakeRule(*this->BuildFileStream, 0, outputs,
+ depends, commands, symbolic);
// If the rule has changed make sure the output is rebuilt.
if(!symbolic)
diff --git a/Source/cmMakefileTargetGenerator.h b/Source/cmMakefileTargetGenerator.h
index b072cfa..98017be 100644
--- a/Source/cmMakefileTargetGenerator.h
+++ b/Source/cmMakefileTargetGenerator.h
@@ -222,6 +222,16 @@ protected:
// Set of extra output files to be driven by the build.
std::set<std::string> ExtraFiles;
+ typedef std::map<std::string, std::string> MultipleOutputPairsType;
+ MultipleOutputPairsType MultipleOutputPairs;
+ void WriteMakeRule(std::ostream& os,
+ const char* comment,
+ const std::vector<std::string>& outputs,
+ const std::vector<std::string>& depends,
+ const std::vector<std::string>& commands,
+ bool symbolic,
+ bool in_help = false);
+
// Target name info.
std::string TargetNameOut;
std::string TargetNameSO;
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index c352c1a..155a30e 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -19,6 +19,7 @@
#include "cmOSXBundleGenerator.h"
#include "cmGeneratorTarget.h"
#include "cmCustomCommandGenerator.h"
+#include "cmAlgorithms.h"
#include <assert.h>
#include <algorithm>
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index cfd8937..92fccd3 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -231,7 +231,7 @@ ComputeDefines(cmSourceFile const* source, const std::string& language)
// Add preprocessor definitions for this target and configuration.
this->LocalGenerator->AddCompileDefinitions(defines, this->Target,
- this->GetConfigName());
+ this->GetConfigName(), language);
this->LocalGenerator->AppendDefines
(defines,
source->GetProperty("COMPILE_DEFINITIONS"));
diff --git a/Source/cmOrderDirectories.cxx b/Source/cmOrderDirectories.cxx
index 23f8526..a612437 100644
--- a/Source/cmOrderDirectories.cxx
+++ b/Source/cmOrderDirectories.cxx
@@ -14,6 +14,7 @@
#include "cmGlobalGenerator.h"
#include "cmSystemTools.h"
#include "cmake.h"
+#include "cmAlgorithms.h"
#include <assert.h>
diff --git a/Source/cmOutputRequiredFilesCommand.cxx b/Source/cmOutputRequiredFilesCommand.cxx
index 5016493..df531e7 100644
--- a/Source/cmOutputRequiredFilesCommand.cxx
+++ b/Source/cmOutputRequiredFilesCommand.cxx
@@ -11,6 +11,7 @@
============================================================================*/
#include "cmOutputRequiredFilesCommand.h"
#include "cmMakeDepend.h"
+#include "cmAlgorithms.h"
#include <cmsys/FStream.hxx>
class cmLBDepend : public cmMakeDepend
diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx
index 3a48101..720030b 100644
--- a/Source/cmPolicies.cxx
+++ b/Source/cmPolicies.cxx
@@ -4,6 +4,7 @@
#include "cmSourceFile.h"
#include "cmVersion.h"
#include "cmVersionMacros.h"
+#include "cmAlgorithms.h"
#include <map>
#include <set>
#include <queue>
@@ -374,6 +375,11 @@ cmPolicies::cmPolicies()
CMP0056, "CMP0056",
"Honor link flags in try_compile() source-file signature.",
3,2,0, cmPolicies::WARN);
+
+ this->DefinePolicy(
+ CMP0057, "CMP0057",
+ "Disallow multiple MAIN_DEPENDENCY specifications for the same file.",
+ 3,3,0, cmPolicies::WARN);
}
cmPolicies::~cmPolicies()
diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h
index c393c2f..854b132 100644
--- a/Source/cmPolicies.h
+++ b/Source/cmPolicies.h
@@ -113,6 +113,8 @@ public:
/// or keywords when unquoted.
CMP0055, ///< Strict checking for break() command.
CMP0056, ///< Honor link flags in try_compile() source-file signature.
+ CMP0057, ///< Disallow multiple MAIN_DEPENDENCY specifications
+ /// for the same file.
/** \brief Always the last entry.
*
diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx
index e18e757..42c18f7 100644
--- a/Source/cmQtAutoGenerators.cxx
+++ b/Source/cmQtAutoGenerators.cxx
@@ -16,6 +16,7 @@
#include "cmMakefile.h"
#include "cmSourceFile.h"
#include "cmSystemTools.h"
+#include "cmAlgorithms.h"
#if defined(_WIN32) && !defined(__CYGWIN__)
# include "cmLocalVisualStudioGenerator.h"
@@ -507,7 +508,7 @@ static void GetCompileDefinitionsAndDirectories(cmTarget const* target,
incs = cmJoin(includeDirs, ";");
std::set<std::string> defines;
- localGen->AddCompileDefinitions(defines, target, config);
+ localGen->AddCompileDefinitions(defines, target, config, "CXX");
defs += cmJoin(defines, ";");
}
diff --git a/Source/cmSearchPath.cxx b/Source/cmSearchPath.cxx
index 1e777ab..045c82e 100644
--- a/Source/cmSearchPath.cxx
+++ b/Source/cmSearchPath.cxx
@@ -12,6 +12,7 @@
#include "cmSearchPath.h"
#include "cmFindCommon.h"
+#include "cmAlgorithms.h"
//----------------------------------------------------------------------------
cmSearchPath::cmSearchPath(cmFindCommon* findCmd)
diff --git a/Source/cmSourceFileLocation.cxx b/Source/cmSourceFileLocation.cxx
index b81951d..9d67c1e 100644
--- a/Source/cmSourceFileLocation.cxx
+++ b/Source/cmSourceFileLocation.cxx
@@ -15,6 +15,7 @@
#include "cmLocalGenerator.h"
#include "cmGlobalGenerator.h"
#include "cmSystemTools.h"
+#include "cmAlgorithms.h"
#include "assert.h"
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index e046bef..b70f60d 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -19,6 +19,7 @@
#include "cmListFileCache.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionDAGChecker.h"
+#include "cmAlgorithms.h"
#include <cmsys/RegularExpression.hxx>
#include <map>
#include <set>
@@ -1979,7 +1980,8 @@ static void processIncludeDirectories(cmTarget const* tgt,
std::vector<std::string> &includes,
UNORDERED_SET<std::string> &uniqueIncludes,
cmGeneratorExpressionDAGChecker *dagChecker,
- const std::string& config, bool debugIncludes)
+ const std::string& config, bool debugIncludes,
+ const std::string& language)
{
cmMakefile *mf = tgt->GetMakefile();
@@ -1995,7 +1997,7 @@ static void processIncludeDirectories(cmTarget const* tgt,
config,
false,
tgt,
- dagChecker),
+ dagChecker, language),
entryIncludes);
std::string usedIncludes;
@@ -2106,7 +2108,8 @@ static void processIncludeDirectories(cmTarget const* tgt,
//----------------------------------------------------------------------------
std::vector<std::string>
-cmTarget::GetIncludeDirectories(const std::string& config) const
+cmTarget::GetIncludeDirectories(const std::string& config,
+ const std::string& language) const
{
std::vector<std::string> includes;
UNORDERED_SET<std::string> uniqueIncludes;
@@ -2139,7 +2142,8 @@ cmTarget::GetIncludeDirectories(const std::string& config) const
uniqueIncludes,
&dagChecker,
config,
- debugIncludes);
+ debugIncludes,
+ language);
std::vector<cmTargetInternals::TargetPropertyEntry*>
linkInterfaceIncludeDirectoriesEntries;
@@ -2179,7 +2183,8 @@ cmTarget::GetIncludeDirectories(const std::string& config) const
uniqueIncludes,
&dagChecker,
config,
- debugIncludes);
+ debugIncludes,
+ language);
deleteAndClear(linkInterfaceIncludeDirectoriesEntries);
@@ -2192,7 +2197,8 @@ static void processCompileOptionsInternal(cmTarget const* tgt,
std::vector<std::string> &options,
UNORDERED_SET<std::string> &uniqueOptions,
cmGeneratorExpressionDAGChecker *dagChecker,
- const std::string& config, bool debugOptions, const char *logName)
+ const std::string& config, bool debugOptions, const char *logName,
+ std::string const& language)
{
cmMakefile *mf = tgt->GetMakefile();
@@ -2204,7 +2210,8 @@ static void processCompileOptionsInternal(cmTarget const* tgt,
config,
false,
tgt,
- dagChecker),
+ dagChecker,
+ language),
entryOptions);
std::string usedOptions;
for(std::vector<std::string>::iterator
@@ -2238,10 +2245,12 @@ static void processCompileOptions(cmTarget const* tgt,
std::vector<std::string> &options,
UNORDERED_SET<std::string> &uniqueOptions,
cmGeneratorExpressionDAGChecker *dagChecker,
- const std::string& config, bool debugOptions)
+ const std::string& config, bool debugOptions,
+ std::string const& language)
{
processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
- dagChecker, config, debugOptions, "options");
+ dagChecker, config, debugOptions, "options",
+ language);
}
//----------------------------------------------------------------------------
@@ -2271,7 +2280,8 @@ void cmTarget::GetAutoUicOptions(std::vector<std::string> &result,
//----------------------------------------------------------------------------
void cmTarget::GetCompileOptions(std::vector<std::string> &result,
- const std::string& config) const
+ const std::string& config,
+ const std::string& language) const
{
UNORDERED_SET<std::string> uniqueOptions;
@@ -2303,7 +2313,8 @@ void cmTarget::GetCompileOptions(std::vector<std::string> &result,
uniqueOptions,
&dagChecker,
config,
- debugOptions);
+ debugOptions,
+ language);
std::vector<cmTargetInternals::TargetPropertyEntry*>
linkInterfaceCompileOptionsEntries;
@@ -2318,7 +2329,8 @@ void cmTarget::GetCompileOptions(std::vector<std::string> &result,
uniqueOptions,
&dagChecker,
config,
- debugOptions);
+ debugOptions,
+ language);
deleteAndClear(linkInterfaceCompileOptionsEntries);
}
@@ -2329,16 +2341,18 @@ static void processCompileDefinitions(cmTarget const* tgt,
std::vector<std::string> &options,
UNORDERED_SET<std::string> &uniqueOptions,
cmGeneratorExpressionDAGChecker *dagChecker,
- const std::string& config, bool debugOptions)
+ const std::string& config, bool debugOptions,
+ std::string const& language)
{
processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
dagChecker, config, debugOptions,
- "definitions");
+ "definitions", language);
}
//----------------------------------------------------------------------------
void cmTarget::GetCompileDefinitions(std::vector<std::string> &list,
- const std::string& config) const
+ const std::string& config,
+ const std::string& language) const
{
UNORDERED_SET<std::string> uniqueOptions;
@@ -2370,7 +2384,8 @@ void cmTarget::GetCompileDefinitions(std::vector<std::string> &list,
uniqueOptions,
&dagChecker,
config,
- debugDefines);
+ debugDefines,
+ language);
std::vector<cmTargetInternals::TargetPropertyEntry*>
linkInterfaceCompileDefinitionsEntries;
@@ -2417,7 +2432,8 @@ void cmTarget::GetCompileDefinitions(std::vector<std::string> &list,
uniqueOptions,
&dagChecker,
config,
- debugDefines);
+ debugDefines,
+ language);
deleteAndClear(linkInterfaceCompileDefinitionsEntries);
}
@@ -2431,7 +2447,8 @@ static void processCompileFeatures(cmTarget const* tgt,
const std::string& config, bool debugOptions)
{
processCompileOptionsInternal(tgt, entries, options, uniqueOptions,
- dagChecker, config, debugOptions, "features");
+ dagChecker, config, debugOptions, "features",
+ std::string());
}
//----------------------------------------------------------------------------
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index ddd9859..5170b31 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -496,7 +496,8 @@ public:
const char* GetExportMacro() const;
void GetCompileDefinitions(std::vector<std::string> &result,
- const std::string& config) const;
+ const std::string& config,
+ const std::string& language) const;
// Compute the set of languages compiled by the target. This is
// computed every time it is called because the languages can change
@@ -567,7 +568,8 @@ public:
bool contentOnly) const;
std::vector<std::string> GetIncludeDirectories(
- const std::string& config) const;
+ const std::string& config,
+ const std::string& language) const;
void InsertInclude(const cmValueWithOrigin &entry,
bool before = false);
void InsertCompileOption(const cmValueWithOrigin &entry,
@@ -577,7 +579,8 @@ public:
void AppendBuildInterfaceIncludes();
void GetCompileOptions(std::vector<std::string> &result,
- const std::string& config) const;
+ const std::string& config,
+ const std::string& language) const;
void GetAutoUicOptions(std::vector<std::string> &result,
const std::string& config) const;
void GetCompileFeatures(std::vector<std::string> &features,
diff --git a/Source/cmTargetCompileDefinitionsCommand.cxx b/Source/cmTargetCompileDefinitionsCommand.cxx
index dc19720..394a166 100644
--- a/Source/cmTargetCompileDefinitionsCommand.cxx
+++ b/Source/cmTargetCompileDefinitionsCommand.cxx
@@ -11,6 +11,8 @@
============================================================================*/
#include "cmTargetCompileDefinitionsCommand.h"
+#include "cmAlgorithms.h"
+
bool cmTargetCompileDefinitionsCommand
::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
{
diff --git a/Source/cmTargetCompileFeaturesCommand.cxx b/Source/cmTargetCompileFeaturesCommand.cxx
index 6ebc31e..823afa1 100644
--- a/Source/cmTargetCompileFeaturesCommand.cxx
+++ b/Source/cmTargetCompileFeaturesCommand.cxx
@@ -11,6 +11,8 @@
============================================================================*/
#include "cmTargetCompileFeaturesCommand.h"
+#include "cmAlgorithms.h"
+
bool cmTargetCompileFeaturesCommand::InitialPass(
std::vector<std::string> const& args,
cmExecutionStatus &)
diff --git a/Source/cmTargetCompileOptionsCommand.cxx b/Source/cmTargetCompileOptionsCommand.cxx
index 8c6fc06..a85153d 100644
--- a/Source/cmTargetCompileOptionsCommand.cxx
+++ b/Source/cmTargetCompileOptionsCommand.cxx
@@ -11,6 +11,8 @@
============================================================================*/
#include "cmTargetCompileOptionsCommand.h"
+#include "cmAlgorithms.h"
+
bool cmTargetCompileOptionsCommand
::InitialPass(std::vector<std::string> const& args, cmExecutionStatus &)
{
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 04d1487..19444ed 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -1876,7 +1876,8 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
clOptions.Parse(flags.c_str());
clOptions.Parse(defineFlags.c_str());
std::vector<std::string> targetDefines;
- this->Target->GetCompileDefinitions(targetDefines, configName.c_str());
+ this->Target->GetCompileDefinitions(targetDefines,
+ configName.c_str(), "CXX");
clOptions.AddDefines(targetDefines);
if(this->MSTools)
{
diff --git a/Source/cmake.cxx b/Source/cmake.cxx
index 80e90a8..11196e4 100644
--- a/Source/cmake.cxx
+++ b/Source/cmake.cxx
@@ -20,6 +20,7 @@
#include "cmSourceFile.h"
#include "cmTest.h"
#include "cmDocumentationFormatter.h"
+#include "cmAlgorithms.h"
#if defined(CMAKE_BUILD_WITH_CMAKE)
# include "cmGraphVizWriter.h"
diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx
index e0bd55b..ac73ad0 100644
--- a/Source/cmakemain.cxx
+++ b/Source/cmakemain.cxx
@@ -24,6 +24,7 @@
#include "cmGlobalGenerator.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
+#include "cmAlgorithms.h"
#include <cmsys/Encoding.hxx>
#ifdef CMAKE_BUILD_WITH_CMAKE
diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx
index 7d67bd8..9f2ea46 100644
--- a/Source/cmcmd.cxx
+++ b/Source/cmcmd.cxx
@@ -15,6 +15,7 @@
#include "cmGlobalGenerator.h"
#include "cmQtAutoGenerators.h"
#include "cmVersion.h"
+#include "cmAlgorithms.h"
#if defined(CMAKE_BUILD_WITH_CMAKE)
# include "cmDependsFortran.h" // For -E cmake_copy_f90_mod callback.
diff --git a/Source/kwsys/Glob.cxx b/Source/kwsys/Glob.cxx
index 1476c25..11bfd16 100644
--- a/Source/kwsys/Glob.cxx
+++ b/Source/kwsys/Glob.cxx
@@ -19,6 +19,7 @@
#include KWSYS_HEADER(Directory.hxx)
#include KWSYS_HEADER(stl/string)
#include KWSYS_HEADER(stl/vector)
+#include KWSYS_HEADER(stl/algorithm)
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
@@ -30,6 +31,8 @@
# include "SystemTools.hxx.in"
# include "kwsys_stl.hxx.in"
# include "kwsys_stl_string.hxx.in"
+# include "kwsys_stl_vector.hxx.in"
+# include "kwsys_stl_algorithm.hxx.in"
#endif
#include <ctype.h>
@@ -66,6 +69,10 @@ Glob::Glob()
// RecurseThroughSymlinks is true by default for backwards compatibility,
// not because it's a good idea...
this->FollowedSymlinkCount = 0;
+
+ // Keep separate variables for directory listing for back compatibility
+ this->ListDirs = true;
+ this->RecurseListDirs = false;
}
//----------------------------------------------------------------------------
@@ -214,13 +221,13 @@ kwsys_stl::string Glob::PatternToRegex(const kwsys_stl::string& pattern,
}
//----------------------------------------------------------------------------
-void Glob::RecurseDirectory(kwsys_stl::string::size_type start,
- const kwsys_stl::string& dir)
+bool Glob::RecurseDirectory(kwsys_stl::string::size_type start,
+ const kwsys_stl::string& dir, GlobMessages* messages)
{
kwsys::Directory d;
if ( !d.Load(dir) )
{
- return;
+ return true;
}
unsigned long cc;
kwsys_stl::string realname;
@@ -255,8 +262,67 @@ void Glob::RecurseDirectory(kwsys_stl::string::size_type start,
if (isSymLink)
{
++this->FollowedSymlinkCount;
+ kwsys_stl::string realPathErrorMessage;
+ kwsys_stl::string canonicalPath(SystemTools::GetRealPath(dir,
+ &realPathErrorMessage));
+
+ if(!realPathErrorMessage.empty())
+ {
+ if(messages)
+ {
+ messages->push_back(Message(
+ Glob::error, "Canonical path generation from path '"
+ + dir + "' failed! Reason: '" + realPathErrorMessage + "'"));
+ }
+ return false;
+ }
+
+ if(kwsys_stl::find(this->VisitedSymlinks.begin(),
+ this->VisitedSymlinks.end(),
+ canonicalPath) == this->VisitedSymlinks.end())
+ {
+ if(this->RecurseListDirs)
+ {
+ // symlinks are treated as directories
+ this->AddFile(this->Internals->Files, realname);
+ }
+
+ this->VisitedSymlinks.push_back(canonicalPath);
+ if(!this->RecurseDirectory(start+1, realname, messages))
+ {
+ this->VisitedSymlinks.pop_back();
+
+ return false;
+ }
+ this->VisitedSymlinks.pop_back();
+ }
+ // else we have already visited this symlink - prevent cyclic recursion
+ else if(messages)
+ {
+ kwsys_stl::string message;
+ for(kwsys_stl::vector<kwsys_stl::string>::const_iterator
+ pathIt = kwsys_stl::find(this->VisitedSymlinks.begin(),
+ this->VisitedSymlinks.end(),
+ canonicalPath);
+ pathIt != this->VisitedSymlinks.end(); ++pathIt)
+ {
+ message += *pathIt + "\n";
+ }
+ message += canonicalPath + "/" + fname;
+ messages->push_back(Message(Glob::cyclicRecursion, message));
+ }
+ }
+ else
+ {
+ if(this->RecurseListDirs)
+ {
+ this->AddFile(this->Internals->Files, realname);
+ }
+ if(!this->RecurseDirectory(start+1, realname, messages))
+ {
+ return false;
+ }
}
- this->RecurseDirectory(start+1, realname);
}
else
{
@@ -267,17 +333,19 @@ void Glob::RecurseDirectory(kwsys_stl::string::size_type start,
}
}
}
+
+ return true;
}
//----------------------------------------------------------------------------
void Glob::ProcessDirectory(kwsys_stl::string::size_type start,
- const kwsys_stl::string& dir)
+ const kwsys_stl::string& dir, GlobMessages* messages)
{
//kwsys_ios::cout << "ProcessDirectory: " << dir << kwsys_ios::endl;
bool last = ( start == this->Internals->Expressions.size()-1 );
if ( last && this->Recurse )
{
- this->RecurseDirectory(start, dir);
+ this->RecurseDirectory(start, dir, messages);
return;
}
@@ -321,8 +389,9 @@ void Glob::ProcessDirectory(kwsys_stl::string::size_type start,
// << this->Internals->TextExpressions[start].c_str() << kwsys_ios::endl;
//kwsys_ios::cout << "Real name: " << realname << kwsys_ios::endl;
- if ( !last &&
- !kwsys::SystemTools::FileIsDirectory(realname) )
+ if( (!last && !kwsys::SystemTools::FileIsDirectory(realname))
+ || (!this->ListDirs && last &&
+ kwsys::SystemTools::FileIsDirectory(realname)) )
{
continue;
}
@@ -335,14 +404,14 @@ void Glob::ProcessDirectory(kwsys_stl::string::size_type start,
}
else
{
- this->ProcessDirectory(start+1, realname);
+ this->ProcessDirectory(start+1, realname, messages);
}
}
}
}
//----------------------------------------------------------------------------
-bool Glob::FindFiles(const kwsys_stl::string& inexpr)
+bool Glob::FindFiles(const kwsys_stl::string& inexpr, GlobMessages* messages)
{
kwsys_stl::string cexpr;
kwsys_stl::string::size_type cc;
@@ -438,11 +507,11 @@ bool Glob::FindFiles(const kwsys_stl::string& inexpr)
// Handle network paths
if ( skip > 0 )
{
- this->ProcessDirectory(0, fexpr.substr(0, skip) + "/");
+ this->ProcessDirectory(0, fexpr.substr(0, skip) + "/", messages);
}
else
{
- this->ProcessDirectory(0, "/");
+ this->ProcessDirectory(0, "/", messages);
}
return true;
}
diff --git a/Source/kwsys/Glob.hxx.in b/Source/kwsys/Glob.hxx.in
index d8b8491..39b7ce7 100644
--- a/Source/kwsys/Glob.hxx.in
+++ b/Source/kwsys/Glob.hxx.in
@@ -40,11 +40,36 @@ class GlobInternals;
class @KWSYS_NAMESPACE@_EXPORT Glob
{
public:
+ enum MessageType
+ {
+ error,
+ cyclicRecursion
+ };
+
+ struct Message
+ {
+ MessageType type;
+ kwsys_stl::string content;
+
+ Message(MessageType t, const kwsys_stl::string& c) :
+ type(t),
+ content(c)
+ {}
+ Message(const Message& msg) :
+ type(msg.type),
+ content(msg.content)
+ {}
+ };
+
+ typedef kwsys_stl::vector<Message> GlobMessages;
+ typedef kwsys_stl::vector<Message>::iterator GlobMessagesIterator;
+public:
Glob();
~Glob();
//! Find all files that match the pattern.
- bool FindFiles(const kwsys_stl::string& inexpr);
+ bool FindFiles(const kwsys_stl::string& inexpr,
+ GlobMessages* messages = 0);
//! Return the list of files that matched.
kwsys_stl::vector<kwsys_stl::string>& GetFiles();
@@ -80,15 +105,26 @@ public:
bool require_whole_string = true,
bool preserve_case = false);
+ /** Getters and setters for enabling and disabling directory
+ listing in recursive and non recursive globbing mode.
+ If listing is enabled in recursive mode it also lists
+ directory symbolic links even if follow symlinks is enabled. */
+ void SetListDirs(bool list) { this->ListDirs=list; }
+ bool GetListDirs() const { return this->ListDirs; }
+ void SetRecurseListDirs(bool list) { this->RecurseListDirs=list; }
+ bool GetRecurseListDirs() const { return this->RecurseListDirs; }
+
protected:
//! Process directory
void ProcessDirectory(kwsys_stl::string::size_type start,
- const kwsys_stl::string& dir);
+ const kwsys_stl::string& dir,
+ GlobMessages* messages);
//! Process last directory, but only when recurse flags is on. That is
// effectively like saying: /path/to/file/**/file
- void RecurseDirectory(kwsys_stl::string::size_type start,
- const kwsys_stl::string& dir);
+ bool RecurseDirectory(kwsys_stl::string::size_type start,
+ const kwsys_stl::string& dir,
+ GlobMessages* messages);
//! Add regular expression
void AddExpression(const kwsys_stl::string& expr);
@@ -101,6 +137,9 @@ protected:
kwsys_stl::string Relative;
bool RecurseThroughSymlinks;
unsigned int FollowedSymlinkCount;
+ kwsys_stl::vector<kwsys_stl::string> VisitedSymlinks;
+ bool ListDirs;
+ bool RecurseListDirs;
private:
Glob(const Glob&); // Not implemented.
diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx
index 9c7ceee..b0434f4 100644
--- a/Source/kwsys/SystemInformation.cxx
+++ b/Source/kwsys/SystemInformation.cxx
@@ -1234,6 +1234,7 @@ void StacktraceSignalHandler(
case ILL_ILLTRP:
oss << "illegal trap";
+ break;
case ILL_PRVOPC:
oss << "privileged opcode";
@@ -1823,6 +1824,7 @@ const char * SystemInformationImplementation::GetVendorID()
return "Motorola";
case HP:
return "Hewlett-Packard";
+ case UnknownManufacturer:
default:
return "Unknown Manufacturer";
}
@@ -3064,6 +3066,12 @@ bool SystemInformationImplementation::RetrieveClassicalCPUIdentity()
case NSC:
this->ChipID.ProcessorName = "Cx486SLC \\ DLC \\ Cx486S A-Step";
break;
+
+ case Sun:
+ case IBM:
+ case Motorola:
+ case HP:
+ case UnknownManufacturer:
default:
this->ChipID.ProcessorName = "Unknown family"; // We cannot identify the processor.
return false;
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index bf6f458..8a481d6 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -2375,6 +2375,10 @@ bool SystemTools::CopyFileAlways(const kwsys_stl::string& source, const kwsys_st
{
fout.write(buffer, fin.gcount());
}
+ else
+ {
+ break;
+ }
}
// Make sure the operating system has finished writing the file
diff --git a/Source/kwsys/hashtable.hxx.in b/Source/kwsys/hashtable.hxx.in
index 307f6bc..7e7dc42 100644
--- a/Source/kwsys/hashtable.hxx.in
+++ b/Source/kwsys/hashtable.hxx.in
@@ -423,7 +423,7 @@ static const unsigned long _stl_prime_list[_stl_num_primes] =
return &_stl_prime_list[0]; }
-inline size_t _stl_next_prime(size_t __n)
+static inline size_t _stl_next_prime(size_t __n)
{
const unsigned long* __first = get_stl_prime_list();
const unsigned long* __last = get_stl_prime_list() + (int)_stl_num_primes;
diff --git a/Source/kwsys/testHashSTL.cxx b/Source/kwsys/testHashSTL.cxx
index b861a5b..ac5cf74 100644
--- a/Source/kwsys/testHashSTL.cxx
+++ b/Source/kwsys/testHashSTL.cxx
@@ -34,7 +34,7 @@
template class kwsys::hash_map<const char*, int>;
template class kwsys::hash_set<int>;
-bool test_hash_map()
+static bool test_hash_map()
{
typedef kwsys::hash_map<const char*, int> mtype;
mtype m;
@@ -51,7 +51,7 @@ bool test_hash_map()
return sum == 3;
}
-bool test_hash_set()
+static bool test_hash_set()
{
typedef kwsys::hash_set<int> stype;
stype s;