summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Modules/CheckIncludeFiles.cmake2
-rw-r--r--Modules/CheckSymbolExists.cmake2
-rw-r--r--Modules/DartConfiguration.tcl.in1
-rw-r--r--Modules/FindCURL.cmake4
-rw-r--r--Modules/FindMPI.cmake5
-rw-r--r--Modules/FindPackageHandleStandardArgs.cmake3
-rw-r--r--Modules/readme.txt5
-rw-r--r--Source/CMakeLists.txt7
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/CTest/cmCTestSVN.cxx79
-rw-r--r--Source/CTest/cmCTestSVN.h3
-rw-r--r--Source/CTest/cmCTestUpdateCommand.cxx2
-rw-r--r--Source/cmAddTestCommand.h2
-rw-r--r--Source/cmDocumentGeneratorExpressions.h19
-rw-r--r--Source/cmDocumentVariables.cxx15
-rw-r--r--Source/cmExportBuildFileGenerator.cxx23
-rw-r--r--Source/cmExportBuildFileGenerator.h10
-rw-r--r--Source/cmExportFileGenerator.cxx56
-rw-r--r--Source/cmExportFileGenerator.h19
-rw-r--r--Source/cmExportInstallFileGenerator.cxx124
-rw-r--r--Source/cmExportInstallFileGenerator.h59
-rw-r--r--Source/cmExportSet.cxx32
-rw-r--r--Source/cmExportSet.h46
-rw-r--r--Source/cmExportSetMap.cxx34
-rw-r--r--Source/cmExportSetMap.h33
-rw-r--r--Source/cmExtraCodeBlocksGenerator.cxx93
-rw-r--r--Source/cmFindPackageCommand.cxx12
-rw-r--r--Source/cmGeneratorExpression.cxx8
-rw-r--r--Source/cmGeneratorExpression.h12
-rw-r--r--Source/cmGeneratorExpressionDAGChecker.cxx106
-rw-r--r--Source/cmGeneratorExpressionDAGChecker.h44
-rw-r--r--Source/cmGeneratorExpressionEvaluator.cxx169
-rw-r--r--Source/cmGeneratorExpressionEvaluator.h19
-rw-r--r--Source/cmGeneratorTarget.cxx60
-rw-r--r--Source/cmGeneratorTarget.h2
-rw-r--r--Source/cmGlobalGenerator.cxx56
-rw-r--r--Source/cmGlobalGenerator.h30
-rw-r--r--Source/cmGlobalXCodeGenerator.cxx17
-rw-r--r--Source/cmIncludeDirectoryCommand.cxx16
-rw-r--r--Source/cmInstallCommand.cxx19
-rw-r--r--Source/cmInstallExportGenerator.cxx18
-rw-r--r--Source/cmInstallExportGenerator.h18
-rw-r--r--Source/cmLocalGenerator.cxx11
-rw-r--r--Source/cmLocalGenerator.h5
-rw-r--r--Source/cmLocalVisualStudio7Generator.cxx21
-rw-r--r--Source/cmMakefileExecutableTargetGenerator.cxx7
-rw-r--r--Source/cmMakefileLibraryTargetGenerator.cxx6
-rw-r--r--Source/cmMakefileTargetGenerator.cxx2
-rw-r--r--Source/cmNinjaTargetGenerator.cxx11
-rw-r--r--Source/cmTarget.cxx157
-rw-r--r--Source/cmTarget.h7
-rw-r--r--Source/cmTargetExport.h39
-rw-r--r--Source/cmTargetLinkLibrariesCommand.cxx4
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx21
-rw-r--r--Tests/CMakeLists.txt1
-rw-r--r--Tests/CompileDefinitions/compiletest.cpp9
-rw-r--r--Tests/CompileDefinitions/target_prop/CMakeLists.txt6
-rw-r--r--Tests/ExportImport/Export/CMakeLists.txt12
-rw-r--r--Tests/ExportImport/Export/testLibDepends.c4
-rw-r--r--Tests/ExportImport/Export/testLibRequired.c1
-rw-r--r--Tests/ExportImport/Import/A/CMakeLists.txt4
-rw-r--r--Tests/GeneratorExpression/CMakeLists.txt17
-rw-r--r--Tests/GeneratorExpression/check.cmake17
-rw-r--r--Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt8
-rw-r--r--Tests/IncludeDirectories/TargetIncludeDirectories/main.cpp4
-rw-r--r--Tests/IncludeDirectories/TargetIncludeDirectories/sing/ting/ting.h1
-rw-r--r--Tests/PDBDirectoryAndName/CMakeLists.txt79
-rw-r--r--Tests/PDBDirectoryAndName/check_pdbs.cmake10
-rw-r--r--Tests/PDBDirectoryAndName/myexe.c5
-rw-r--r--Tests/PDBDirectoryAndName/myexe2.c3
-rw-r--r--Tests/PDBDirectoryAndName/mylibA.c1
-rw-r--r--Tests/PDBDirectoryAndName/mylibB.c1
-rw-r--r--Tests/PDBDirectoryAndName/mylibC.c1
-rw-r--r--Tests/PDBDirectoryAndName/mylibD.c1
-rw-r--r--Tests/RunCMake/CMakeLists.txt1
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1-result.txt1
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1-stderr.txt6
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1.cmake7
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2-result.txt1
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2-stderr.txt6
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2.cmake9
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3-result.txt1
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3-stderr.txt6
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3.cmake8
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4-result.txt1
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4-stderr.txt6
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4.cmake10
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5-result.txt1
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5-stderr.txt6
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5.cmake10
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6-result.txt1
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6-stderr.txt6
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6.cmake10
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/CMakeLists.txt8
-rw-r--r--Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake8
-rwxr-xr-xbootstrap3
96 files changed, 1518 insertions, 360 deletions
diff --git a/Modules/CheckIncludeFiles.cmake b/Modules/CheckIncludeFiles.cmake
index 70ab9be..daf2dd0 100644
--- a/Modules/CheckIncludeFiles.cmake
+++ b/Modules/CheckIncludeFiles.cmake
@@ -71,7 +71,7 @@ macro(CHECK_INCLUDE_FILES INCLUDE VARIABLE)
"exist passed with the following output:\n"
"${OUTPUT}\n\n")
else()
- message(STATUS "Looking for ${_description} - not found.")
+ message(STATUS "Looking for ${_description} - not found")
set(${VARIABLE} "" CACHE INTERNAL "Have includes ${INCLUDE}")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Determining if files ${INCLUDE} "
diff --git a/Modules/CheckSymbolExists.cmake b/Modules/CheckSymbolExists.cmake
index 59b9942..5a8597f 100644
--- a/Modules/CheckSymbolExists.cmake
+++ b/Modules/CheckSymbolExists.cmake
@@ -89,7 +89,7 @@ macro(_CHECK_SYMBOL_EXISTS SOURCEFILE SYMBOL FILES VARIABLE)
"${OUTPUT}\nFile ${SOURCEFILE}:\n"
"${CMAKE_CONFIGURABLE_FILE_CONTENT}\n")
else()
- message(STATUS "Looking for ${SYMBOL} - not found.")
+ message(STATUS "Looking for ${SYMBOL} - not found")
set(${VARIABLE} "" CACHE INTERNAL "Have symbol ${SYMBOL}")
file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log
"Determining if the ${SYMBOL} "
diff --git a/Modules/DartConfiguration.tcl.in b/Modules/DartConfiguration.tcl.in
index ad7f805..9e49ac7 100644
--- a/Modules/DartConfiguration.tcl.in
+++ b/Modules/DartConfiguration.tcl.in
@@ -44,6 +44,7 @@ CVSUpdateOptions: @CVS_UPDATE_OPTIONS@
# Subversion options
SVNCommand: @SVNCOMMAND@
+SVNOptions: @CTEST_SVN_OPTIONS@
SVNUpdateOptions: @SVN_UPDATE_OPTIONS@
# Git options
diff --git a/Modules/FindCURL.cmake b/Modules/FindCURL.cmake
index e080f1a..0fb8f45 100644
--- a/Modules/FindCURL.cmake
+++ b/Modules/FindCURL.cmake
@@ -24,13 +24,15 @@
find_path(CURL_INCLUDE_DIR NAMES curl/curl.h)
mark_as_advanced(CURL_INCLUDE_DIR)
-# Look for the library.
+# Look for the library (sorted from most current/relevant entry to least).
find_library(CURL_LIBRARY NAMES
curl
# Windows MSVC prebuilts:
curllib
libcurl_imp
curllib_static
+ # Windows older "Win32 - MSVC" prebuilts (libcurl.lib, e.g. libcurl-7.15.5-win32-msvc.zip):
+ libcurl
)
mark_as_advanced(CURL_LIBRARY)
diff --git a/Modules/FindMPI.cmake b/Modules/FindMPI.cmake
index ae50ca7..4ce4de9 100644
--- a/Modules/FindMPI.cmake
+++ b/Modules/FindMPI.cmake
@@ -576,6 +576,11 @@ foreach (lang C CXX Fortran)
try_regular_compiler(${lang} regular_compiler_worked)
endif()
+ set(MPI_${lang}_FIND_QUIETLY ${MPI_FIND_QUIETLY})
+ set(MPI_${lang}_FIND_REQUIRED ${MPI_FIND_REQUIRED})
+ set(MPI_${lang}_FIND_VERSION ${MPI_FIND_VERSION})
+ set(MPI_${lang}_FIND_VERSION_EXACT ${MPI_FIND_VERSION_EXACT})
+
if (regular_compiler_worked)
find_package_handle_standard_args(MPI_${lang} DEFAULT_MSG MPI_${lang}_COMPILER)
else()
diff --git a/Modules/FindPackageHandleStandardArgs.cmake b/Modules/FindPackageHandleStandardArgs.cmake
index 888e109..25d8df3 100644
--- a/Modules/FindPackageHandleStandardArgs.cmake
+++ b/Modules/FindPackageHandleStandardArgs.cmake
@@ -120,6 +120,9 @@ macro(_FPHSA_HANDLE_FAILURE_CONFIG_MODE)
list(GET ${_NAME}_CONSIDERED_VERSIONS ${currentConfigIndex} version)
set(configsText "${configsText} ${filename} (version ${version})\n")
endforeach()
+ if (${_NAME}_NOT_FOUND_MESSAGE)
+ set(configsText "${configsText} Reason given by package: ${${_NAME}_NOT_FOUND_MESSAGE}\n")
+ endif()
_FPHSA_FAILURE_MESSAGE("${FPHSA_FAIL_MESSAGE} ${VERSION_MSG}, checked the following files:\n${configsText}")
else()
diff --git a/Modules/readme.txt b/Modules/readme.txt
index 7d61d8d..4818031 100644
--- a/Modules/readme.txt
+++ b/Modules/readme.txt
@@ -18,6 +18,9 @@ XXX_VERSION_YY Expect Version YY if true. Make sure at most one of thes
XXX_WRAP_YY If False, do not try to use the relevent CMake wrapping command.
XXX_YY_FOUND If False, optional YY part of XXX sytem is not available.
XXX_FOUND Set to false, or undefined, if we haven't found, or don't want to use XXX.
+XXX_NOT_FOUND_MESSAGE Should be set by config-files in the case that it has set XXX_FOUND to FALSE.
+ The contained message will be printed by the find_package() command and by
+ find_package_handle_standard_args() to inform the user about the problem.
XXX_RUNTIME_LIBRARY_DIRS Optionally, the runtime library search path for use when running an executable linked to shared libraries.
The list should be used by user code to create the PATH on windows or LD_LIBRARY_PATH on unix.
This should not be a cache entry.
@@ -124,7 +127,7 @@ If neither the QUIET nor REQUIRED options are given then the
FindXXX.cmake module should look for the package and complain without
error if the module is not found.
-A package can be provide sub-components.
+A package can provide sub-components.
Those components can be listed after the COMPONENTS (or REQUIRED)
or OPTIONAL_COMPONENTS keywords. The set of all listed components will be
specified in a XXX_FIND_COMPONENTS variable.
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index 354f123..8bf6c40 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -176,6 +176,10 @@ set(SRCS
cmExportFileGenerator.cxx
cmExportInstallFileGenerator.h
cmExportInstallFileGenerator.cxx
+ cmExportSet.h
+ cmExportSet.cxx
+ cmExportSetMap.h
+ cmExportSetMap.cxx
cmExtraCodeBlocksGenerator.cxx
cmExtraCodeBlocksGenerator.h
cmExtraEclipseCDT4Generator.cxx
@@ -183,6 +187,8 @@ set(SRCS
cmFileTimeComparison.cxx
cmFileTimeComparison.h
cmGeneratedFileStream.cxx
+ cmGeneratorExpressionDAGChecker.cxx
+ cmGeneratorExpressionDAGChecker.h
cmGeneratorExpressionEvaluator.cxx
cmGeneratorExpressionEvaluator.h
cmGeneratorExpressionLexer.cxx
@@ -257,6 +263,7 @@ set(SRCS
cmSystemTools.h
cmTarget.cxx
cmTarget.h
+ cmTargetExport.h
cmTest.cxx
cmTest.h
cmTestGenerator.cxx
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 31b2bf2..84cc45b 100644
--- a/Source/CMakeVersion.cmake
+++ b/Source/CMakeVersion.cmake
@@ -2,5 +2,5 @@
set(CMake_VERSION_MAJOR 2)
set(CMake_VERSION_MINOR 8)
set(CMake_VERSION_PATCH 9)
-set(CMake_VERSION_TWEAK 20120928)
+set(CMake_VERSION_TWEAK 20121002)
#set(CMake_VERSION_RC 1)
diff --git a/Source/CTest/cmCTestSVN.cxx b/Source/CTest/cmCTestSVN.cxx
index 49cea2e..2668c8e 100644
--- a/Source/CTest/cmCTestSVN.cxx
+++ b/Source/CTest/cmCTestSVN.cxx
@@ -38,11 +38,11 @@ cmCTestSVN::~cmCTestSVN()
//----------------------------------------------------------------------------
void cmCTestSVN::CleanupImpl()
{
- const char* svn = this->CommandLineTool.c_str();
- const char* svn_cleanup[] = {svn, "cleanup", 0};
+ std::vector<const char*> svn_cleanup;
+ svn_cleanup.push_back("cleanup");
OutputLogger out(this->Log, "cleanup-out> ");
OutputLogger err(this->Log, "cleanup-err> ");
- this->RunChild(svn_cleanup, &out, &err);
+ this->RunSVNCommand(svn_cleanup, &out, &err);
}
//----------------------------------------------------------------------------
@@ -106,12 +106,13 @@ static bool cmCTestSVNPathStarts(std::string const& p1, std::string const& p2)
std::string cmCTestSVN::LoadInfo(SVNInfo& svninfo)
{
// Run "svn info" to get the repository info from the work tree.
- const char* svn = this->CommandLineTool.c_str();
- const char* svn_info[] = {svn, "info", svninfo.LocalPath.c_str(), 0};
+ std::vector<const char*> svn_info;
+ svn_info.push_back("info");
+ svn_info.push_back(svninfo.LocalPath.c_str());
std::string rev;
InfoParser out(this, "info-out> ", rev, svninfo);
OutputLogger err(this->Log, "info-err> ");
- this->RunChild(svn_info, &out, &err);
+ this->RunSVNCommand(svn_info, &out, &err);
return rev;
}
@@ -285,19 +286,52 @@ bool cmCTestSVN::UpdateImpl()
}
std::vector<char const*> svn_update;
- svn_update.push_back(this->CommandLineTool.c_str());
svn_update.push_back("update");
- svn_update.push_back("--non-interactive");
for(std::vector<cmStdString>::const_iterator ai = args.begin();
ai != args.end(); ++ai)
{
svn_update.push_back(ai->c_str());
}
- svn_update.push_back(0);
UpdateParser out(this, "up-out> ");
OutputLogger err(this->Log, "up-err> ");
- return this->RunUpdateCommand(&svn_update[0], &out, &err);
+ return this->RunSVNCommand(svn_update, &out, &err);
+}
+
+//----------------------------------------------------------------------------
+bool cmCTestSVN::RunSVNCommand(std::vector<char const*> const& parameters,
+ OutputParser* out, OutputParser* err)
+{
+ if(parameters.empty()) return false;
+
+ std::vector<char const*> args;
+ args.push_back(this->CommandLineTool.c_str());
+
+ args.insert(args.end(), parameters.begin(), parameters.end());
+
+ args.push_back("--non-interactive");
+
+ std::string userOptions =
+ this->CTest->GetCTestConfiguration("SVNOptions");
+
+ std::vector<cmStdString> parsedUserOptions =
+ cmSystemTools::ParseArguments(userOptions.c_str());
+ for(std::vector<cmStdString>::iterator i = parsedUserOptions.begin();
+ i != parsedUserOptions.end(); ++i)
+ {
+ args.push_back(i->c_str());
+ }
+
+ args.push_back(0);
+
+ if(strcmp(parameters[0], "update") == 0)
+ {
+ return RunUpdateCommand(&args[0], out, err);
+ }
+ else
+ {
+ return RunChild(&args[0], out, err);
+ }
}
//----------------------------------------------------------------------------
@@ -417,14 +451,15 @@ void cmCTestSVN::LoadRevisions(SVNInfo &svninfo)
}
// Run "svn log" to get all global revisions of interest.
- const char* svn = this->CommandLineTool.c_str();
- const char* svn_log[] = {svn, "log", "--xml", "-v", revs.c_str(),
- svninfo.LocalPath.c_str(), 0};
- {
+ std::vector<const char*> svn_log;
+ svn_log.push_back("log");
+ svn_log.push_back("--xml");
+ svn_log.push_back("-v");
+ svn_log.push_back(revs.c_str());
+ svn_log.push_back(svninfo.LocalPath.c_str());
LogParser out(this, "log-out> ", svninfo);
OutputLogger err(this->Log, "log-err> ");
- this->RunChild(svn_log, &out, &err);
- }
+ this->RunSVNCommand(svn_log, &out, &err);
}
//----------------------------------------------------------------------------
@@ -492,11 +527,11 @@ private:
void cmCTestSVN::LoadModifications()
{
// Run "svn status" which reports local modifications.
- const char* svn = this->CommandLineTool.c_str();
- const char* svn_status[] = {svn, "status", "--non-interactive", 0};
+ std::vector<const char*> svn_status;
+ svn_status.push_back("status");
StatusParser out(this, "status-out> ");
OutputLogger err(this->Log, "status-err> ");
- this->RunChild(svn_status, &out, &err);
+ this->RunSVNCommand(svn_status, &out, &err);
}
//----------------------------------------------------------------------------
@@ -550,11 +585,11 @@ private:
void cmCTestSVN::LoadExternals()
{
// Run "svn status" to get the list of external repositories
- const char* svn = this->CommandLineTool.c_str();
- const char* svn_status[] = {svn, "status", 0};
+ std::vector<const char*> svn_status;
+ svn_status.push_back("status");
ExternalParser out(this, "external-out> ");
OutputLogger err(this->Log, "external-err> ");
- this->RunChild(svn_status, &out, &err);
+ this->RunSVNCommand(svn_status, &out, &err);
}
//----------------------------------------------------------------------------
diff --git a/Source/CTest/cmCTestSVN.h b/Source/CTest/cmCTestSVN.h
index 56265d0..73d676e 100644
--- a/Source/CTest/cmCTestSVN.h
+++ b/Source/CTest/cmCTestSVN.h
@@ -33,6 +33,9 @@ private:
virtual void NoteNewRevision();
virtual bool UpdateImpl();
+ bool RunSVNCommand(std::vector<char const*> const& parameters,
+ OutputParser* out, OutputParser* err);
+
// Information about an SVN repository (root repository or external)
struct SVNInfo {
diff --git a/Source/CTest/cmCTestUpdateCommand.cxx b/Source/CTest/cmCTestUpdateCommand.cxx
index 8414349..2ca9f6c 100644
--- a/Source/CTest/cmCTestUpdateCommand.cxx
+++ b/Source/CTest/cmCTestUpdateCommand.cxx
@@ -44,6 +44,8 @@ cmCTestGenericHandler* cmCTestUpdateCommand::InitializeHandler()
this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
"SVNUpdateOptions", "CTEST_SVN_UPDATE_OPTIONS");
this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
+ "SVNOptions", "CTEST_SVN_OPTIONS");
+ this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
"BZRCommand", "CTEST_BZR_COMMAND");
this->CTest->SetCTestConfigurationFromCMakeVariable(this->Makefile,
"BZRUpdateOptions", "CTEST_BZR_UPDATE_OPTIONS");
diff --git a/Source/cmAddTestCommand.h b/Source/cmAddTestCommand.h
index b11bff9..6a0cd9d 100644
--- a/Source/cmAddTestCommand.h
+++ b/Source/cmAddTestCommand.h
@@ -81,7 +81,7 @@ public:
"\n"
"Arguments after COMMAND may use \"generator expressions\" with the "
"syntax \"$<...>\". "
- CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
+ CM_DOCUMENT_ADD_TEST_GENERATOR_EXPRESSIONS
"Example usage:\n"
" add_test(NAME mytest\n"
" COMMAND testDriver --config $<CONFIGURATION>\n"
diff --git a/Source/cmDocumentGeneratorExpressions.h b/Source/cmDocumentGeneratorExpressions.h
index 74c673a..445fd0e 100644
--- a/Source/cmDocumentGeneratorExpressions.h
+++ b/Source/cmDocumentGeneratorExpressions.h
@@ -12,7 +12,7 @@
#ifndef cmDocumentGeneratorExpressions_h
#define cmDocumentGeneratorExpressions_h
-#define CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS \
+#define CM_DOCUMENT_ADD_TEST_GENERATOR_EXPRESSIONS \
"Generator expressions are evaluted during build system generation " \
"to produce information specific to each build configuration. " \
"Valid expressions are:\n" \
@@ -20,6 +20,12 @@
" $<1:...> = content of \"...\"\n" \
" $<CONFIG:cfg> = '1' if config is \"cfg\", else '0'\n" \
" $<CONFIGURATION> = configuration name\n" \
+ " $<BOOL:...> = '1' if the '...' is true, else '0'\n" \
+ " $<STREQUAL:a,b> = '1' if a is STREQUAL b, else '0'\n" \
+ " $<ANGLE-R> = A literal '>'. Used to compare " \
+ "strings which contain a '>' for example.\n" \
+ " $<COMMA> = A literal ','. Used to compare " \
+ "strings which contain a ',' for example.\n" \
" $<TARGET_FILE:tgt> = main file (.exe, .so.1.2, .a)\n" \
" $<TARGET_LINKER_FILE:tgt> = file used to link (.a, .lib, .so)\n" \
" $<TARGET_SONAME_FILE:tgt> = file with soname (.so.3)\n" \
@@ -29,6 +35,10 @@
" $<TARGET_FILE_DIR:tgt>/$<TARGET_FILE_NAME:tgt>\n" \
" $<TARGET_LINKER_FILE_DIR:tgt>/$<TARGET_LINKER_FILE_NAME:tgt>\n" \
" $<TARGET_SONAME_FILE_DIR:tgt>/$<TARGET_SONAME_FILE_NAME:tgt>\n" \
+ "\n" \
+ " $<TARGET_PROPERTY:tgt,prop> = The value of the property prop\n" \
+ "on the target tgt. Note that tgt is not added as a dependency of\n" \
+ "the target this expression is evaluated on.\n" \
"Boolean expressions:\n" \
" $<AND:?[,?]...> = '1' if all '?' are '1', else '0'\n" \
" $<OR:?[,?]...> = '0' if all '?' are '0', else '1'\n" \
@@ -36,4 +46,11 @@
"where '?' is always either '0' or '1'.\n" \
""
+#define CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS \
+ CM_DOCUMENT_ADD_TEST_GENERATOR_EXPRESSIONS \
+ "Expressions with an implicit 'this' target:\n" \
+ " $<TARGET_PROPERTY:prop> = The value of the property prop on\n" \
+ "the target on which the generator expression is evaluated.\n" \
+ ""
+
#endif
diff --git a/Source/cmDocumentVariables.cxx b/Source/cmDocumentVariables.cxx
index 5e7e081..8db0e8f 100644
--- a/Source/cmDocumentVariables.cxx
+++ b/Source/cmDocumentVariables.cxx
@@ -701,7 +701,8 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
cm->DefineProperty
("CMAKE_SYSTEM_IGNORE_PATH", cmProperty::VARIABLE,
"Path to be ignored by FIND_XXX() commands.",
- "Specifies directories to be ignored by searches in FIND_XXX() commands "
+ "Specifies directories to be ignored by searches in FIND_XXX() "
+ "commands. "
"This is useful in cross-compiled environments where some system "
"directories contain incompatible but possibly linkable libraries. For "
"example, on cross-compiled cluster environments, this allows a user to "
@@ -716,7 +717,8 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
cm->DefineProperty
("CMAKE_IGNORE_PATH", cmProperty::VARIABLE,
"Path to be ignored by FIND_XXX() commands.",
- "Specifies directories to be ignored by searches in FIND_XXX() commands "
+ "Specifies directories to be ignored by searches in FIND_XXX() "
+ "commands. "
"This is useful in cross-compiled environments where some system "
"directories contain incompatible but possibly linkable libraries. For "
"example, on cross-compiled cluster environments, this allows a user to "
@@ -1211,6 +1213,15 @@ void cmDocumentVariables::DefineVariables(cmake* cm)
"Variables that Control the Build");
cm->DefineProperty
+ ("CMAKE_PDB_OUTPUT_DIRECTORY", cmProperty::VARIABLE,
+ "Where to put all the MS debug symbol files.",
+ "This variable is used to initialize the "
+ "PDB_OUTPUT_DIRECTORY property on all the targets. "
+ "See that target property for additional information.",
+ false,
+ "Variables that Control the Build");
+
+ cm->DefineProperty
("CMAKE_AUTOMOC", cmProperty::VARIABLE,
"Whether to handle moc automatically for Qt targets.",
"This variable is used to initialize the "
diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx
index 32595ee..fb3f39f 100644
--- a/Source/cmExportBuildFileGenerator.cxx
+++ b/Source/cmExportBuildFileGenerator.cxx
@@ -72,8 +72,9 @@ cmExportBuildFileGenerator
if(!properties.empty())
{
// Get the rest of the target details.
+ std::vector<std::string> missingTargets;
this->SetImportDetailProperties(config, suffix,
- target, properties);
+ target, properties, missingTargets);
// TOOD: PUBLIC_HEADER_LOCATION
// This should wait until the build feature propagation stuff
@@ -82,6 +83,7 @@ cmExportBuildFileGenerator
// properties);
// Generate code in the export file.
+ this->GenerateMissingTargetsCheckCode(os, missingTargets);
this->GenerateImportPropertyCode(os, config, target, properties);
}
}
@@ -133,6 +135,25 @@ cmExportBuildFileGenerator
//----------------------------------------------------------------------------
void
+cmExportBuildFileGenerator::HandleMissingTarget(
+ std::string& link_libs, std::vector<std::string>&,
+ cmMakefile*, cmTarget* depender, cmTarget* dependee)
+{
+ // The target is not in the export.
+ if(!this->AppendMode)
+ {
+ // We are not appending, so all exported targets should be
+ // known here. This is probably user-error.
+ this->ComplainAboutMissingTarget(depender, dependee);
+ }
+ // Assume the target will be exported by another command.
+ // Append it with the export namespace.
+ link_libs += this->Namespace;
+ link_libs += dependee->GetName();
+}
+
+//----------------------------------------------------------------------------
+void
cmExportBuildFileGenerator
::ComplainAboutMissingTarget(cmTarget* depender,
cmTarget* dependee)
diff --git a/Source/cmExportBuildFileGenerator.h b/Source/cmExportBuildFileGenerator.h
index 0f37626..726537b 100644
--- a/Source/cmExportBuildFileGenerator.h
+++ b/Source/cmExportBuildFileGenerator.h
@@ -45,8 +45,14 @@ protected:
virtual void GenerateImportTargetsConfig(std::ostream& os,
const char* config,
std::string const& suffix);
- virtual void ComplainAboutMissingTarget(cmTarget* depender,
- cmTarget* dependee);
+ virtual void HandleMissingTarget(std::string& link_libs,
+ std::vector<std::string>& missingTargets,
+ cmMakefile* mf,
+ cmTarget* depender,
+ cmTarget* dependee);
+
+ void ComplainAboutMissingTarget(cmTarget* depender,
+ cmTarget* dependee);
/** Fill in properties indicating built file locations. */
void SetImportLocationProperty(const char* config,
diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx
index eb19df5e..8dffae4 100644
--- a/Source/cmExportFileGenerator.cxx
+++ b/Source/cmExportFileGenerator.cxx
@@ -11,10 +11,15 @@
============================================================================*/
#include "cmExportFileGenerator.h"
+#include "cmExportSet.h"
#include "cmGeneratedFileStream.h"
+#include "cmGlobalGenerator.h"
+#include "cmInstallExportGenerator.h"
+#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
+#include "cmTargetExport.h"
#include "cmVersion.h"
#include <cmsys/auto_ptr.hxx>
@@ -123,7 +128,9 @@ void cmExportFileGenerator::GenerateImportConfig(std::ostream& os,
void
cmExportFileGenerator
::SetImportDetailProperties(const char* config, std::string const& suffix,
- cmTarget* target, ImportPropertyMap& properties)
+ cmTarget* target, ImportPropertyMap& properties,
+ std::vector<std::string>& missingTargets
+ )
{
// Get the makefile in which to lookup target information.
cmMakefile* mf = target->GetMakefile();
@@ -159,13 +166,13 @@ cmExportFileGenerator
{
this->SetImportLinkProperty(suffix, target,
"IMPORTED_LINK_INTERFACE_LANGUAGES",
- iface->Languages, properties);
+ iface->Languages, properties, missingTargets);
this->SetImportLinkProperty(suffix, target,
"IMPORTED_LINK_INTERFACE_LIBRARIES",
- iface->Libraries, properties);
+ iface->Libraries, properties, missingTargets);
this->SetImportLinkProperty(suffix, target,
"IMPORTED_LINK_DEPENDENT_LIBRARIES",
- iface->SharedDeps, properties);
+ iface->SharedDeps, properties, missingTargets);
if(iface->Multiplicity > 0)
{
std::string prop = "IMPORTED_LINK_INTERFACE_MULTIPLICITY";
@@ -184,7 +191,9 @@ cmExportFileGenerator
cmTarget* target,
const char* propName,
std::vector<std::string> const& libs,
- ImportPropertyMap& properties)
+ ImportPropertyMap& properties,
+ std::vector<std::string>& missingTargets
+ )
{
// Skip the property if there are no libraries.
if(libs.empty())
@@ -224,17 +233,7 @@ cmExportFileGenerator
}
else
{
- // The target is not in the export.
- if(!this->AppendMode)
- {
- // We are not appending, so all exported targets should be
- // known here. This is probably user-error.
- this->ComplainAboutMissingTarget(target, tgt);
- }
- // Assume the target will be exported by another command.
- // Append it with the export namespace.
- link_libs += this->Namespace;
- link_libs += *li;
+ this->HandleMissingTarget(link_libs, missingTargets, mf, target, tgt);
}
}
else
@@ -250,6 +249,7 @@ cmExportFileGenerator
properties[prop] = link_libs;
}
+
//----------------------------------------------------------------------------
void cmExportFileGenerator::GenerateImportHeaderCode(std::ostream& os,
const char* config)
@@ -381,6 +381,30 @@ cmExportFileGenerator
//----------------------------------------------------------------------------
+void cmExportFileGenerator::GenerateMissingTargetsCheckCode(std::ostream& os,
+ const std::vector<std::string>& missingTargets)
+{
+ os << "# Make sure the targets which have been exported in some other \n"
+ "# export set exist.\n";
+ for(unsigned int i=0; i<missingTargets.size(); ++i)
+ {
+ os << "IF(NOT TARGET \"" << missingTargets[i] << "\" )\n"
+ << " IF(CMAKE_FIND_PACKAGE_NAME)\n"
+ << " SET( ${CMAKE_FIND_PACKAGE_NAME}_FOUND FALSE)\n"
+ << " SET( ${CMAKE_FIND_PACKAGE_NAME}_NOT_FOUND_MESSAGE "
+ << "\"Required imported target \\\"" << missingTargets[i]
+ << "\\\" not found ! \")\n"
+ << " ELSE()\n"
+ << " MESSAGE(FATAL_ERROR \"Required imported target \\\""
+ << missingTargets[i] << "\\\" not found ! \")\n"
+ << " ENDIF()\n"
+ << "ENDIF()\n";
+ }
+ os << "\n";
+}
+
+
+//----------------------------------------------------------------------------
void
cmExportFileGenerator::GenerateImportedFileCheckLoop(std::ostream& os)
{
diff --git a/Source/cmExportFileGenerator.h b/Source/cmExportFileGenerator.h
index f271e55..70bc65d 100644
--- a/Source/cmExportFileGenerator.h
+++ b/Source/cmExportFileGenerator.h
@@ -60,17 +60,21 @@ protected:
ImportPropertyMap const& properties,
const std::set<std::string>& importedLocations);
void GenerateImportedFileCheckLoop(std::ostream& os);
+ void GenerateMissingTargetsCheckCode(std::ostream& os,
+ const std::vector<std::string>& missingTargets);
// Collect properties with detailed information about targets beyond
// their location on disk.
void SetImportDetailProperties(const char* config,
std::string const& suffix, cmTarget* target,
- ImportPropertyMap& properties);
+ ImportPropertyMap& properties,
+ std::vector<std::string>& missingTargets);
void SetImportLinkProperty(std::string const& suffix,
cmTarget* target, const char* propName,
std::vector<std::string> const& libs,
- ImportPropertyMap& properties);
+ ImportPropertyMap& properties,
+ std::vector<std::string>& missingTargets);
/** Each subclass knows how to generate its kind of export file. */
virtual bool GenerateMainFile(std::ostream& os) = 0;
@@ -80,10 +84,13 @@ protected:
const char* config,
std::string const& suffix) = 0;
- /** Each subclass knows how to complain about a target that is
- missing from an export set. */
- virtual void ComplainAboutMissingTarget(cmTarget* depender,
- cmTarget* dependee) = 0;
+ /** Each subclass knows how to deal with a target that is missing from an
+ * export set. */
+ virtual void HandleMissingTarget(std::string& link_libs,
+ std::vector<std::string>& missingTargets,
+ cmMakefile* mf,
+ cmTarget* depender,
+ cmTarget* dependee) = 0;
// The namespace in which the exports are placed in the generated file.
std::string Namespace;
diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx
index da14dd7..7841731 100644
--- a/Source/cmExportInstallFileGenerator.cxx
+++ b/Source/cmExportInstallFileGenerator.cxx
@@ -11,14 +11,19 @@
============================================================================*/
#include "cmExportInstallFileGenerator.h"
+#include "cmExportSet.h"
+#include "cmExportSetMap.h"
#include "cmGeneratedFileStream.h"
+#include "cmGlobalGenerator.h"
+#include "cmLocalGenerator.h"
#include "cmInstallExportGenerator.h"
#include "cmInstallTargetGenerator.h"
+#include "cmTargetExport.h"
//----------------------------------------------------------------------------
cmExportInstallFileGenerator
::cmExportInstallFileGenerator(cmInstallExportGenerator* iegen):
- InstallExportGenerator(iegen)
+ IEGen(iegen)
{
}
@@ -36,10 +41,10 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
{
// Create all the imported targets.
for(std::vector<cmTargetExport*>::const_iterator
- tei = this->ExportSet->begin();
- tei != this->ExportSet->end(); ++tei)
+ tei = this->IEGen->GetExportSet()->GetTargetExports()->begin();
+ tei != this->IEGen->GetExportSet()->GetTargetExports()->end(); ++tei)
{
- cmTargetExport* te = *tei;
+ cmTargetExport const* te = *tei;
if(this->ExportedTargets.insert(te->Target).second)
{
this->GenerateImportTargetCode(os, te->Target);
@@ -47,8 +52,9 @@ bool cmExportInstallFileGenerator::GenerateMainFile(std::ostream& os)
else
{
cmOStringStream e;
- e << "INSTALL(EXPORT \"" << this->Name << "\" ...) "
- << "includes target \"" << te->Target->GetName()
+ e << "INSTALL(EXPORT \""
+ << this->IEGen->GetExportSet()->GetName()
+ << "\" ...) " << "includes target \"" << te->Target->GetName()
<< "\" more than once in the export set.";
cmSystemTools::Error(e.str().c_str());
return false;
@@ -84,7 +90,7 @@ bool
cmExportInstallFileGenerator::GenerateImportFileConfig(const char* config)
{
// Skip configurations not enabled for this export.
- if(!this->InstallExportGenerator->InstallsForConfig(config))
+ if(!this->IEGen->InstallsForConfig(config))
{
return true;
}
@@ -140,7 +146,7 @@ cmExportInstallFileGenerator
{
// Add code to compute the installation prefix relative to the
// import file location.
- const char* installDest = this->InstallExportGenerator->GetDestination();
+ const char* installDest = this->IEGen->GetDestination();
if(!cmSystemTools::FileIsFullPath(installDest))
{
std::string dest = installDest;
@@ -161,11 +167,11 @@ cmExportInstallFileGenerator
// Add each target in the set to the export.
for(std::vector<cmTargetExport*>::const_iterator
- tei = this->ExportSet->begin();
- tei != this->ExportSet->end(); ++tei)
+ tei = this->IEGen->GetExportSet()->GetTargetExports()->begin();
+ tei != this->IEGen->GetExportSet()->GetTargetExports()->end(); ++tei)
{
// Collect import properties for this target.
- cmTargetExport* te = *tei;
+ cmTargetExport const* te = *tei;
ImportPropertyMap properties;
std::set<std::string> importedLocations;
this->SetImportLocationProperty(config, suffix, te->ArchiveGenerator,
@@ -185,8 +191,9 @@ cmExportInstallFileGenerator
if(!properties.empty())
{
// Get the rest of the target details.
+ std::vector<std::string> missingTargets;
this->SetImportDetailProperties(config, suffix,
- te->Target, properties);
+ te->Target, properties, missingTargets);
// TOOD: PUBLIC_HEADER_LOCATION
// This should wait until the build feature propagation stuff
@@ -195,6 +202,7 @@ cmExportInstallFileGenerator
// properties);
// Generate code in the export file.
+ this->GenerateMissingTargetsCheckCode(os, missingTargets);
this->GenerateImportPropertyCode(os, config, te->Target, properties);
this->GenerateImportedFileChecksCode(os, te->Target, properties,
importedLocations);
@@ -306,12 +314,80 @@ cmExportInstallFileGenerator
//----------------------------------------------------------------------------
void
+cmExportInstallFileGenerator::HandleMissingTarget(
+ std::string& link_libs, std::vector<std::string>& missingTargets,
+ cmMakefile* mf, cmTarget* depender, cmTarget* dependee)
+{
+ std::string name = dependee->GetName();
+ std::vector<std::string> namespaces = this->FindNamespaces(mf, name);
+ int targetOccurrences = (int)namespaces.size();
+ if (targetOccurrences == 1)
+ {
+ std::string missingTarget = namespaces[0];
+ missingTarget += name;
+ link_libs += missingTarget;
+ missingTargets.push_back(missingTarget);
+ }
+ else
+ {
+ // We are not appending, so all exported targets should be
+ // known here. This is probably user-error.
+ this->ComplainAboutMissingTarget(depender, dependee, targetOccurrences);
+ }
+}
+
+//----------------------------------------------------------------------------
+std::vector<std::string>
+cmExportInstallFileGenerator
+::FindNamespaces(cmMakefile* mf, const std::string& name)
+{
+ std::vector<std::string> namespaces;
+ cmGlobalGenerator* gg = mf->GetLocalGenerator()->GetGlobalGenerator();
+ const cmExportSetMap& exportSets = gg->GetExportSets();
+
+ for(cmExportSetMap::const_iterator expIt = exportSets.begin();
+ expIt != exportSets.end();
+ ++expIt)
+ {
+ const cmExportSet* exportSet = expIt->second;
+ std::vector<cmTargetExport*> const* targets =
+ exportSet->GetTargetExports();
+
+ bool containsTarget = false;
+ for(unsigned int i=0; i<targets->size(); i++)
+ {
+ if (name == (*targets)[i]->Target->GetName())
+ {
+ containsTarget = true;
+ break;
+ }
+ }
+
+ if (containsTarget)
+ {
+ std::vector<cmInstallExportGenerator const*> const* installs =
+ exportSet->GetInstallations();
+ for(unsigned int i=0; i<installs->size(); i++)
+ {
+ namespaces.push_back((*installs)[i]->GetNamespace());
+ }
+ }
+ }
+
+ return namespaces;
+}
+
+
+//----------------------------------------------------------------------------
+void
cmExportInstallFileGenerator
::ComplainAboutImportPrefix(cmInstallTargetGenerator* itgen)
{
- const char* installDest = this->InstallExportGenerator->GetDestination();
+ const char* installDest = this->IEGen->GetDestination();
cmOStringStream e;
- e << "INSTALL(EXPORT \"" << this->Name << "\") given absolute "
+ e << "INSTALL(EXPORT \""
+ << this->IEGen->GetExportSet()->GetName()
+ << "\") given absolute "
<< "DESTINATION \"" << installDest << "\" but the export "
<< "references an installation of target \""
<< itgen->GetTarget()->GetName() << "\" which has relative "
@@ -322,12 +398,24 @@ cmExportInstallFileGenerator
//----------------------------------------------------------------------------
void
cmExportInstallFileGenerator
-::ComplainAboutMissingTarget(cmTarget* depender, cmTarget* dependee)
+::ComplainAboutMissingTarget(cmTarget* depender,
+ cmTarget* dependee,
+ int occurrences)
{
cmOStringStream e;
- e << "INSTALL(EXPORT \"" << this->Name << "\" ...) "
+ e << "INSTALL(EXPORT \""
+ << this->IEGen->GetExportSet()->GetName()
+ << "\" ...) "
<< "includes target \"" << depender->GetName()
- << "\" which requires target \"" << dependee->GetName()
- << "\" that is not in the export set.";
+ << "\" which requires target \"" << dependee->GetName() << "\" ";
+ if (occurrences == 0)
+ {
+ e << "that is not in the export set.";
+ }
+ else
+ {
+ e << "that is not in this export set, but " << occurrences
+ << " times in others.";
+ }
cmSystemTools::Error(e.str().c_str());
}
diff --git a/Source/cmExportInstallFileGenerator.h b/Source/cmExportInstallFileGenerator.h
index fb678e8..e719ecc 100644
--- a/Source/cmExportInstallFileGenerator.h
+++ b/Source/cmExportInstallFileGenerator.h
@@ -18,6 +18,7 @@ class cmInstallExportGenerator;
class cmInstallFilesGenerator;
class cmInstallTargetGenerator;
class cmTargetExport;
+class cmExportSet;
/** \class cmExportInstallFileGenerator
* \brief Generate a file exporting targets from an install tree.
@@ -40,15 +41,6 @@ public:
files. */
cmExportInstallFileGenerator(cmInstallExportGenerator* iegen);
- /** Set the name of the export associated with the files. This is
- the name given to the install(EXPORT) command mode. */
- void SetName(const char* name) { this->Name = name; }
-
- /** Set the set of targets to be exported. These are the targets
- associated with the export name. */
- void SetExportSet(std::vector<cmTargetExport*> const* eSet)
- { this->ExportSet = eSet; }
-
/** Get the per-config file generated for each configuraiton. This
maps from the configuration name to the file temporary location
for installation. */
@@ -65,8 +57,19 @@ protected:
virtual void GenerateImportTargetsConfig(std::ostream& os,
const char* config,
std::string const& suffix);
- virtual void ComplainAboutMissingTarget(cmTarget* depender,
- cmTarget* dependee);
+ virtual void HandleMissingTarget(std::string& link_libs,
+ std::vector<std::string>& missingTargets,
+ cmMakefile* mf,
+ cmTarget* depender,
+ cmTarget* dependee);
+
+ void ComplainAboutMissingTarget(cmTarget* depender,
+ cmTarget* dependee,
+ int occurrences);
+
+ std::vector<std::string> FindNamespaces(cmMakefile* mf,
+ const std::string& name);
+
/** Generate a per-configuration file for the targets. */
bool GenerateImportFileConfig(const char* config);
@@ -81,9 +84,7 @@ protected:
void ComplainAboutImportPrefix(cmInstallTargetGenerator* itgen);
- cmInstallExportGenerator* InstallExportGenerator;
- std::string Name;
- std::vector<cmTargetExport*> const* ExportSet;
+ cmInstallExportGenerator* IEGen;
std::string ImportPrefix;
@@ -91,34 +92,4 @@ protected:
std::map<cmStdString, cmStdString> ConfigImportFiles;
};
-/*
- cmTargetExport is used in cmGlobalGenerator to collect the install
- generators for targets associated with an export.
-*/
-class cmTargetExport
-{
-public:
- cmTargetExport(cmTarget* tgt,
- cmInstallTargetGenerator* archive,
- cmInstallTargetGenerator* runtime,
- cmInstallTargetGenerator* library,
- cmInstallTargetGenerator* framework,
- cmInstallTargetGenerator* bundle,
- cmInstallFilesGenerator* headers
- ) : Target(tgt), ArchiveGenerator(archive),
- RuntimeGenerator(runtime), LibraryGenerator(library),
- FrameworkGenerator(framework), BundleGenerator(bundle),
- HeaderGenerator(headers) {}
-
- cmTarget* Target;
- cmInstallTargetGenerator* ArchiveGenerator;
- cmInstallTargetGenerator* RuntimeGenerator;
- cmInstallTargetGenerator* LibraryGenerator;
- cmInstallTargetGenerator* FrameworkGenerator;
- cmInstallTargetGenerator* BundleGenerator;
- cmInstallFilesGenerator* HeaderGenerator;
-private:
- cmTargetExport();
-};
-
#endif
diff --git a/Source/cmExportSet.cxx b/Source/cmExportSet.cxx
new file mode 100644
index 0000000..33b0630
--- /dev/null
+++ b/Source/cmExportSet.cxx
@@ -0,0 +1,32 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2012 Kitware, Inc., Insight Software Consortium
+
+ 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 "cmExportSet.h"
+#include "cmTargetExport.h"
+
+cmExportSet::~cmExportSet()
+{
+ for(unsigned int i = 0; i < this->TargetExports.size(); ++ i)
+ {
+ delete this->TargetExports[i];
+ }
+}
+
+void cmExportSet::AddTargetExport(cmTargetExport* te)
+{
+ this->TargetExports.push_back(te);
+}
+
+void cmExportSet::AddInstallation(cmInstallExportGenerator const* installation)
+{
+ this->Installations.push_back(installation);
+}
diff --git a/Source/cmExportSet.h b/Source/cmExportSet.h
new file mode 100644
index 0000000..a57aa12
--- /dev/null
+++ b/Source/cmExportSet.h
@@ -0,0 +1,46 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+
+ 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 cmExportSet_h
+#define cmExportSet_h
+
+#include "cmSystemTools.h"
+class cmTargetExport;
+class cmInstallExportGenerator;
+
+/// A set of targets that were installed with the same EXPORT parameter.
+class cmExportSet
+{
+public:
+ /// Construct an empty export set named \a name
+ cmExportSet(const std::string &name) : Name(name) {}
+ /// Destructor
+ ~cmExportSet();
+
+ void AddTargetExport(cmTargetExport* tgt);
+
+ void AddInstallation(cmInstallExportGenerator const* installation);
+
+ std::string const& GetName() const { return this->Name; }
+
+ std::vector<cmTargetExport*> const* GetTargetExports() const
+ { return &this->TargetExports; }
+
+ std::vector<cmInstallExportGenerator const*> const* GetInstallations() const
+ { return &this->Installations; }
+
+private:
+ std::vector<cmTargetExport*> TargetExports;
+ std::string Name;
+ std::vector<cmInstallExportGenerator const*> Installations;
+};
+
+#endif
diff --git a/Source/cmExportSetMap.cxx b/Source/cmExportSetMap.cxx
new file mode 100644
index 0000000..96fdb3e
--- /dev/null
+++ b/Source/cmExportSetMap.cxx
@@ -0,0 +1,34 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2012 Kitware, Inc., Insight Software Consortium
+
+ 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 "cmExportSetMap.h"
+#include "cmExportSet.h"
+
+cmExportSet* cmExportSetMap::operator[](const std::string &name)
+{
+ std::map<std::string, cmExportSet*>::iterator it = this->find(name);
+ if (it == this->end()) // Export set not found
+ {
+ it = this->insert(std::make_pair(name, new cmExportSet(name))).first;
+ }
+ return it->second;
+}
+
+cmExportSetMap::~cmExportSetMap()
+{
+ for(std::map<std::string, cmExportSet*>::iterator it = this->begin();
+ it != this->end();
+ ++ it)
+ {
+ delete it->second;
+ }
+}
diff --git a/Source/cmExportSetMap.h b/Source/cmExportSetMap.h
new file mode 100644
index 0000000..4663c55
--- /dev/null
+++ b/Source/cmExportSetMap.h
@@ -0,0 +1,33 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
+
+ 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 cmExportSetMap_h
+#define cmExportSetMap_h
+
+#include "cmSystemTools.h"
+class cmExportSet;
+
+/// A name -> cmExportSet map with overloaded operator[].
+class cmExportSetMap : public std::map<std::string, cmExportSet*>
+{
+public:
+ /** \brief Overloaded operator[].
+ *
+ * The operator is overloaded because cmExportSet has no default constructor:
+ * we do not want unnamed export sets.
+ */
+ cmExportSet* operator[](const std::string &name);
+
+ /// Overloaded destructor deletes all member export sets.
+ ~cmExportSetMap();
+};
+
+#endif
diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx
index b1bbd90..8b2daba 100644
--- a/Source/cmExtraCodeBlocksGenerator.cxx
+++ b/Source/cmExtraCodeBlocksGenerator.cxx
@@ -617,14 +617,17 @@ void cmExtraCodeBlocksGenerator::AppendTarget(cmGeneratedFileStream& fout,
" <Option compiler=\"" << compiler << "\" />\n"
" <Compiler>\n";
+ cmGeneratorTarget *gtgt = this->GlobalGenerator
+ ->GetGeneratorTarget(target);
+
// the compilerdefines for this target
- const char* cdefs = target->GetMakefile()->GetProperty(
- "COMPILE_DEFINITIONS");
- if(cdefs)
+ std::string cdefs = gtgt->GetCompileDefinitions();
+
+ if(cdefs.empty())
{
// Expand the list.
std::vector<std::string> defs;
- cmSystemTools::ExpandListArgument(cdefs, defs);
+ cmSystemTools::ExpandListArgument(cdefs.c_str(), defs);
for(std::vector<std::string>::const_iterator di = defs.begin();
di != defs.end(); ++di)
{
@@ -633,59 +636,57 @@ void cmExtraCodeBlocksGenerator::AppendTarget(cmGeneratedFileStream& fout,
}
}
- // the include directories for this target
- std::set<std::string> uniqIncludeDirs;
+ // the include directories for this target
+ std::set<std::string> uniqIncludeDirs;
+
+ std::vector<std::string> includes;
+ target->GetMakefile()->GetLocalGenerator()->
+ GetIncludeDirectories(includes, gtgt);
+ for(std::vector<std::string>::const_iterator dirIt=includes.begin();
+ dirIt != includes.end();
+ ++dirIt)
+ {
+ uniqIncludeDirs.insert(*dirIt);
+ }
- cmGeneratorTarget *gtgt = this->GlobalGenerator
- ->GetGeneratorTarget(target);
- std::vector<std::string> includes;
- target->GetMakefile()->GetLocalGenerator()->
- GetIncludeDirectories(includes, gtgt);
- for(std::vector<std::string>::const_iterator dirIt=includes.begin();
- dirIt != includes.end();
+ std::string systemIncludeDirs = makefile->GetSafeDefinition(
+ "CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS");
+ if (!systemIncludeDirs.empty())
+ {
+ std::vector<std::string> dirs;
+ cmSystemTools::ExpandListArgument(systemIncludeDirs.c_str(), dirs);
+ for(std::vector<std::string>::const_iterator dirIt=dirs.begin();
+ dirIt != dirs.end();
++dirIt)
{
uniqIncludeDirs.insert(*dirIt);
}
+ }
- std::string systemIncludeDirs = makefile->GetSafeDefinition(
- "CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS");
- if (!systemIncludeDirs.empty())
- {
- std::vector<std::string> dirs;
- cmSystemTools::ExpandListArgument(systemIncludeDirs.c_str(), dirs);
- for(std::vector<std::string>::const_iterator dirIt=dirs.begin();
- dirIt != dirs.end();
- ++dirIt)
- {
- uniqIncludeDirs.insert(*dirIt);
- }
- }
-
- systemIncludeDirs = makefile->GetSafeDefinition(
- "CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS");
- if (!systemIncludeDirs.empty())
- {
- std::vector<std::string> dirs;
- cmSystemTools::ExpandListArgument(systemIncludeDirs.c_str(), dirs);
- for(std::vector<std::string>::const_iterator dirIt=dirs.begin();
- dirIt != dirs.end();
- ++dirIt)
- {
- uniqIncludeDirs.insert(*dirIt);
- }
- }
-
- for(std::set<std::string>::const_iterator dirIt=uniqIncludeDirs.begin();
- dirIt != uniqIncludeDirs.end();
+ systemIncludeDirs = makefile->GetSafeDefinition(
+ "CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS");
+ if (!systemIncludeDirs.empty())
+ {
+ std::vector<std::string> dirs;
+ cmSystemTools::ExpandListArgument(systemIncludeDirs.c_str(), dirs);
+ for(std::vector<std::string>::const_iterator dirIt=dirs.begin();
+ dirIt != dirs.end();
++dirIt)
{
- fout <<" <Add directory=\"" << dirIt->c_str() << "\" />\n";
+ uniqIncludeDirs.insert(*dirIt);
}
+ }
- fout<<" </Compiler>\n";
+ for(std::set<std::string>::const_iterator dirIt=uniqIncludeDirs.begin();
+ dirIt != uniqIncludeDirs.end();
+ ++dirIt)
+ {
+ fout <<" <Add directory=\"" << dirIt->c_str() << "\" />\n";
}
- else // e.g. all and the GLOBAL and UTILITY targets
+
+ fout<<" </Compiler>\n";
+ }
+ else // e.g. all and the GLOBAL and UTILITY targets
{
fout<<" <Option working_dir=\""
<< makefile->GetStartOutputDirectory() << "\" />\n"
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index be47f95..470ceca 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -840,6 +840,8 @@ bool cmFindPackageCommand
//----------------------------------------------------------------------------
void cmFindPackageCommand::SetModuleVariables(const std::string& components)
{
+ this->AddFindDefinition("CMAKE_FIND_PACKAGE_NAME", this->Name.c_str());
+
// Store the list of components.
std::string components_var = this->Name + "_FIND_COMPONENTS";
this->AddFindDefinition(components_var.c_str(), components.c_str());
@@ -1016,6 +1018,9 @@ bool cmFindPackageCommand::HandlePackageMode()
std::string foundVar = this->Name;
foundVar += "_FOUND";
+ std::string notFoundMessageVar = this->Name;
+ notFoundMessageVar += "_NOT_FOUND_MESSAGE";
+ std::string notFoundMessage;
// If the directory for the config file was found, try to read the file.
bool result = true;
@@ -1033,6 +1038,7 @@ bool cmFindPackageCommand::HandlePackageMode()
// has set Foo_FOUND to FALSE itself:
this->Makefile->RemoveDefinition(foundVar.c_str());
}
+ this->Makefile->RemoveDefinition(notFoundMessageVar.c_str());
// Set the version variables before loading the config file.
// It may override them.
@@ -1051,6 +1057,8 @@ bool cmFindPackageCommand::HandlePackageMode()
// we get here if the Config file has set Foo_FOUND actively to FALSE
found = false;
configFileSetFOUNDFalse = true;
+ notFoundMessage = this->Makefile->GetSafeDefinition(
+ notFoundMessageVar.c_str());
}
}
else
@@ -1071,6 +1079,10 @@ bool cmFindPackageCommand::HandlePackageMode()
" " << this->FileFound << "\n"
"but it set " << foundVar << " to FALSE so package \"" <<
this->Name << "\" is considered to be NOT FOUND.";
+ if (!notFoundMessage.empty())
+ {
+ e << " Reason given by package: \n" << notFoundMessage << "\n";
+ }
}
// If there are files in ConsideredConfigs, it means that FooConfig.cmake
// have been found, but they didn't have appropriate versions.
diff --git a/Source/cmGeneratorExpression.cxx b/Source/cmGeneratorExpression.cxx
index 0885616..3f8e962 100644
--- a/Source/cmGeneratorExpression.cxx
+++ b/Source/cmGeneratorExpression.cxx
@@ -19,6 +19,7 @@
#include "cmGeneratorExpressionEvaluator.h"
#include "cmGeneratorExpressionLexer.h"
#include "cmGeneratorExpressionParser.h"
+#include "cmGeneratorExpressionDAGChecker.h"
//----------------------------------------------------------------------------
cmGeneratorExpression::cmGeneratorExpression(
@@ -65,7 +66,9 @@ cmGeneratorExpression::~cmGeneratorExpression()
//----------------------------------------------------------------------------
const char *cmCompiledGeneratorExpression::Evaluate(
- cmMakefile* mf, const char* config, bool quiet) const
+ cmMakefile* mf, const char* config, bool quiet,
+ cmGeneratorTarget *target,
+ cmGeneratorExpressionDAGChecker *dagChecker) const
{
if (!this->NeedsParsing)
{
@@ -84,11 +87,12 @@ const char *cmCompiledGeneratorExpression::Evaluate(
context.Config = config;
context.Quiet = quiet;
context.HadError = false;
+ context.Target = target;
context.Backtrace = this->Backtrace;
for ( ; it != end; ++it)
{
- this->Output += (*it)->Evaluate(&context);
+ this->Output += (*it)->Evaluate(&context, dagChecker);
if (context.HadError)
{
this->Output = "";
diff --git a/Source/cmGeneratorExpression.h b/Source/cmGeneratorExpression.h
index b8467c2..d37ce97 100644
--- a/Source/cmGeneratorExpression.h
+++ b/Source/cmGeneratorExpression.h
@@ -9,6 +9,10 @@
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the License for more information.
============================================================================*/
+
+#ifndef cmGeneratorExpression_h
+#define cmGeneratorExpression_h
+
#include "cmStandardIncludes.h"
#include <stack>
@@ -16,10 +20,12 @@
#include <cmsys/RegularExpression.hxx>
class cmTarget;
+class cmGeneratorTarget;
class cmMakefile;
class cmListFileBacktrace;
struct cmGeneratorExpressionEvaluator;
+struct cmGeneratorExpressionDAGChecker;
class cmCompiledGeneratorExpression;
@@ -54,7 +60,9 @@ class cmCompiledGeneratorExpression
{
public:
const char* Evaluate(cmMakefile* mf, const char* config,
- bool quiet = false) const;
+ bool quiet = false,
+ cmGeneratorTarget *target = 0,
+ cmGeneratorExpressionDAGChecker *dagChecker = 0) const;
/** Get set of targets found during evaluations. */
std::set<cmTarget*> const& GetTargets() const
@@ -80,3 +88,5 @@ private:
mutable std::set<cmTarget*> Targets;
mutable std::string Output;
};
+
+#endif
diff --git a/Source/cmGeneratorExpressionDAGChecker.cxx b/Source/cmGeneratorExpressionDAGChecker.cxx
new file mode 100644
index 0000000..bfb0ddf
--- /dev/null
+++ b/Source/cmGeneratorExpressionDAGChecker.cxx
@@ -0,0 +1,106 @@
+/*============================================================================
+ 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 "cmGeneratorExpressionDAGChecker.h"
+
+#include "cmMakefile.h"
+
+//----------------------------------------------------------------------------
+cmGeneratorExpressionDAGChecker::cmGeneratorExpressionDAGChecker(
+ const cmListFileBacktrace &backtrace,
+ const std::string &target,
+ const std::string &property,
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *parent)
+ : Parent(parent), Target(target), Property(property),
+ Content(content), Backtrace(backtrace)
+{
+ this->IsDAG = this->isDAG();
+}
+
+//----------------------------------------------------------------------------
+bool cmGeneratorExpressionDAGChecker::check() const
+{
+ return this->IsDAG;
+}
+
+//----------------------------------------------------------------------------
+void cmGeneratorExpressionDAGChecker::reportError(
+ cmGeneratorExpressionContext *context,
+ const std::string &expr)
+{
+ if (this->IsDAG)
+ {
+ return;
+ }
+
+ context->HadError = true;
+ if (context->Quiet)
+ {
+ return;
+ }
+
+ const cmGeneratorExpressionDAGChecker *parent = this->Parent;
+
+ if (parent && !parent->Parent)
+ {
+ cmOStringStream e;
+ e << "Error evaluating generator expression:\n"
+ << " " << expr << "\n"
+ << "Self reference on target \""
+ << context->Target->GetName() << "\".\n";
+ context->Makefile->GetCMakeInstance()
+ ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(),
+ parent->Backtrace);
+ return;
+ }
+
+ {
+ cmOStringStream e;
+ e << "Error evaluating generator expression:\n"
+ << " " << expr << "\n"
+ << "Dependency loop found.";
+ context->Makefile->GetCMakeInstance()
+ ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(),
+ context->Backtrace);
+ }
+
+ int loopStep = 1;
+ while (parent)
+ {
+ cmOStringStream e;
+ e << "Loop step " << loopStep << "\n"
+ << " "
+ << (parent->Content ? parent->Content->GetOriginalExpression() : expr)
+ << "\n";
+ context->Makefile->GetCMakeInstance()
+ ->IssueMessage(cmake::FATAL_ERROR, e.str().c_str(),
+ parent->Backtrace);
+ parent = parent->Parent;
+ ++loopStep;
+ }
+}
+
+//----------------------------------------------------------------------------
+bool cmGeneratorExpressionDAGChecker::isDAG() const
+{
+ const cmGeneratorExpressionDAGChecker *parent = this->Parent;
+ while (parent)
+ {
+ if (this->Target == parent->Target && this->Property == parent->Property)
+ {
+ return false;
+ }
+ parent = parent->Parent;
+ }
+ return true;
+}
diff --git a/Source/cmGeneratorExpressionDAGChecker.h b/Source/cmGeneratorExpressionDAGChecker.h
new file mode 100644
index 0000000..ffc84f8
--- /dev/null
+++ b/Source/cmGeneratorExpressionDAGChecker.h
@@ -0,0 +1,44 @@
+/*============================================================================
+ 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 cmGeneratorExpressionDAGChecker_h
+#define cmGeneratorExpressionDAGChecker_h
+
+#include "cmStandardIncludes.h"
+
+#include "cmGeneratorExpressionEvaluator.h"
+
+//----------------------------------------------------------------------------
+struct cmGeneratorExpressionDAGChecker
+{
+ cmGeneratorExpressionDAGChecker(const cmListFileBacktrace &backtrace,
+ const std::string &target,
+ const std::string &property,
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *parent);
+
+ bool check() const;
+
+ void reportError(cmGeneratorExpressionContext *context,
+ const std::string &expr);
+private:
+ bool isDAG() const;
+
+private:
+ const cmGeneratorExpressionDAGChecker * const Parent;
+ const std::string Target;
+ const std::string Property;
+ const GeneratorExpressionContent * const Content;
+ const cmListFileBacktrace Backtrace;
+ bool IsDAG;
+};
+
+#endif
diff --git a/Source/cmGeneratorExpressionEvaluator.cxx b/Source/cmGeneratorExpressionEvaluator.cxx
index 9f84ed2..22f60d4 100644
--- a/Source/cmGeneratorExpressionEvaluator.cxx
+++ b/Source/cmGeneratorExpressionEvaluator.cxx
@@ -13,6 +13,8 @@
#include "cmGeneratorExpressionEvaluator.h"
#include "cmGeneratorExpressionParser.h"
+#include "cmGeneratorExpressionDAGChecker.h"
+#include "cmGeneratorExpression.h"
//----------------------------------------------------------------------------
static void reportError(cmGeneratorExpressionContext *context,
@@ -47,7 +49,8 @@ struct cmGeneratorExpressionNode
virtual std::string Evaluate(const std::vector<std::string> &parameters,
cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *dagChecker
) const = 0;
};
@@ -60,7 +63,8 @@ static const struct ZeroNode : public cmGeneratorExpressionNode
std::string Evaluate(const std::vector<std::string> &,
cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *) const
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *) const
{
// Unreachable
return std::string();
@@ -76,7 +80,8 @@ static const struct OneNode : public cmGeneratorExpressionNode
std::string Evaluate(const std::vector<std::string> &,
cmGeneratorExpressionContext *,
- const GeneratorExpressionContent *) const
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *) const
{
// Unreachable
return std::string();
@@ -93,7 +98,8 @@ static const struct OP ## Node : public cmGeneratorExpressionNode \
\
std::string Evaluate(const std::vector<std::string> &parameters, \
cmGeneratorExpressionContext *context, \
- const GeneratorExpressionContent *content) const \
+ const GeneratorExpressionContent *content, \
+ cmGeneratorExpressionDAGChecker *) const \
{ \
std::vector<std::string>::const_iterator it = parameters.begin(); \
const std::vector<std::string>::const_iterator end = parameters.end(); \
@@ -123,9 +129,11 @@ BOOLEAN_OP_NODE(orNode, OR, 0, 1)
static const struct NotNode : public cmGeneratorExpressionNode
{
NotNode() {}
+
std::string Evaluate(const std::vector<std::string> &parameters,
cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content) const
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *) const
{
if (*parameters.begin() != "0" && *parameters.begin() != "1")
{
@@ -138,14 +146,80 @@ static const struct NotNode : public cmGeneratorExpressionNode
} 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.at(1) ? "1" : "0";
+ }
+} strEqualNode;
+
+//----------------------------------------------------------------------------
+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 ConfigurationNode : public cmGeneratorExpressionNode
{
ConfigurationNode() {}
+
virtual int NumExpectedParameters() const { return 0; }
std::string Evaluate(const std::vector<std::string> &,
cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *) const
+ const GeneratorExpressionContent *,
+ cmGeneratorExpressionDAGChecker *) const
{
return context->Config ? context->Config : "";
}
@@ -160,7 +234,8 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
std::string Evaluate(const std::vector<std::string> &parameters,
cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content) const
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *) const
{
if (!context->Config)
{
@@ -180,6 +255,61 @@ static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
} configurationTestNode;
//----------------------------------------------------------------------------
+static const struct TargetPropertyNode : public cmGeneratorExpressionNode
+{
+ TargetPropertyNode() {}
+
+ // This node handles errors on parameter count itself.
+ virtual int NumExpectedParameters() const { return -1; }
+
+ 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();
+ }
+ cmGeneratorTarget* target = context->Target;
+ std::string propertyName = *parameters.begin();
+ if (parameters.size() == 2)
+ {
+ target = context->Makefile->FindGeneratorTargetToUse(
+ parameters.begin()->c_str());
+
+ if (!target)
+ {
+ cmOStringStream e;
+ e << "Target \""
+ << target
+ << "\" not found.";
+ reportError(context, content->GetOriginalExpression(), e.str());
+ }
+ propertyName = parameters.at(1);
+ }
+
+ cmGeneratorExpressionDAGChecker dagChecker(context->Backtrace,
+ target->GetName(),
+ propertyName,
+ content,
+ dagCheckerParent);
+
+ if (!dagChecker.check())
+ {
+ dagChecker.reportError(context, content->GetOriginalExpression());
+ return std::string();
+ }
+
+ const char *prop = target->GetProperty(propertyName.c_str());
+ return prop ? prop : "";
+ }
+} targetPropertyNode;
+
+//----------------------------------------------------------------------------
template<bool linker, bool soname>
struct TargetFilesystemArtifactResultCreator
{
@@ -293,7 +423,8 @@ struct TargetFilesystemArtifact : public cmGeneratorExpressionNode
std::string Evaluate(const std::vector<std::string> &parameters,
cmGeneratorExpressionContext *context,
- const GeneratorExpressionContent *content) const
+ const GeneratorExpressionContent *content,
+ cmGeneratorExpressionDAGChecker *) const
{
// Lookup the referenced target.
std::string name = *parameters.begin();
@@ -392,7 +523,18 @@ cmGeneratorExpressionNode* GetNode(const std::string &identifier)
return &targetLinkerFileDirNode;
else if (identifier == "TARGET_SONAME_FILE_DIR")
return &targetSoNameFileDirNode;
+ else if (identifier == "STREQUAL")
+ return &strEqualNode;
+ else if (identifier == "BOOL")
+ return &boolNode;
+ else if (identifier == "ANGLE-R")
+ return &angle_rNode;
+ else if (identifier == "COMMA")
+ return &commaNode;
+ else if (identifier == "TARGET_PROPERTY")
+ return &targetPropertyNode;
return 0;
+
}
//----------------------------------------------------------------------------
@@ -412,7 +554,8 @@ std::string GeneratorExpressionContent::GetOriginalExpression() const
//----------------------------------------------------------------------------
std::string GeneratorExpressionContent::Evaluate(
- cmGeneratorExpressionContext *context) const
+ cmGeneratorExpressionContext *context,
+ cmGeneratorExpressionDAGChecker *dagChecker) const
{
std::string identifier;
{
@@ -422,7 +565,7 @@ std::string GeneratorExpressionContent::Evaluate(
= this->IdentifierChildren.end();
for ( ; it != end; ++it)
{
- identifier += (*it)->Evaluate(context);
+ identifier += (*it)->Evaluate(context, dagChecker);
if (context->HadError)
{
return std::string();
@@ -465,7 +608,7 @@ std::string GeneratorExpressionContent::Evaluate(
= pit->end();
for ( ; it != end; ++it)
{
- result += (*it)->Evaluate(context);
+ result += (*it)->Evaluate(context, dagChecker);
if (context->HadError)
{
return std::string();
@@ -491,7 +634,7 @@ std::string GeneratorExpressionContent::Evaluate(
pit->end();
for ( ; it != end; ++it)
{
- parameter += (*it)->Evaluate(context);
+ parameter += (*it)->Evaluate(context, dagChecker);
if (context->HadError)
{
return std::string();
@@ -534,7 +677,7 @@ std::string GeneratorExpressionContent::Evaluate(
return std::string();
}
- return node->Evaluate(parameters, context, this);
+ return node->Evaluate(parameters, context, this, dagChecker);
}
//----------------------------------------------------------------------------
diff --git a/Source/cmGeneratorExpressionEvaluator.h b/Source/cmGeneratorExpressionEvaluator.h
index 5163ca0..04a2acd 100644
--- a/Source/cmGeneratorExpressionEvaluator.h
+++ b/Source/cmGeneratorExpressionEvaluator.h
@@ -15,6 +15,11 @@
#include <vector>
#include <string>
+#include "cmListFileCache.h"
+
+class cmTarget;
+class cmGeneratorTarget;
+
//----------------------------------------------------------------------------
struct cmGeneratorExpressionContext
{
@@ -22,11 +27,13 @@ struct cmGeneratorExpressionContext
std::set<cmTarget*> Targets;
cmMakefile *Makefile;
const char *Config;
- cmTarget *Target;
+ cmGeneratorTarget *Target;
bool Quiet;
bool HadError;
};
+struct cmGeneratorExpressionDAGChecker;
+
//----------------------------------------------------------------------------
struct cmGeneratorExpressionEvaluator
{
@@ -41,8 +48,8 @@ struct cmGeneratorExpressionEvaluator
virtual Type GetType() const = 0;
- virtual std::string Evaluate(cmGeneratorExpressionContext *context
- ) const = 0;
+ virtual std::string Evaluate(cmGeneratorExpressionContext *context,
+ cmGeneratorExpressionDAGChecker *) const = 0;
private:
cmGeneratorExpressionEvaluator(const cmGeneratorExpressionEvaluator &);
@@ -57,7 +64,8 @@ struct TextContent : public cmGeneratorExpressionEvaluator
}
- std::string Evaluate(cmGeneratorExpressionContext *) const
+ std::string Evaluate(cmGeneratorExpressionContext *,
+ cmGeneratorExpressionDAGChecker *) const
{
return std::string(this->Content, this->Length);
}
@@ -102,7 +110,8 @@ struct GeneratorExpressionContent : public cmGeneratorExpressionEvaluator
return cmGeneratorExpressionEvaluator::Generator;
}
- std::string Evaluate(cmGeneratorExpressionContext *context) const;
+ std::string Evaluate(cmGeneratorExpressionContext *context,
+ cmGeneratorExpressionDAGChecker *) const;
std::string GetOriginalExpression() const;
diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx
index 91f16d1..d4b57f4 100644
--- a/Source/cmGeneratorTarget.cxx
+++ b/Source/cmGeneratorTarget.cxx
@@ -17,6 +17,8 @@
#include "cmComputeLinkInformation.h"
#include "cmGlobalGenerator.h"
#include "cmSourceFile.h"
+#include "cmGeneratorExpression.h"
+#include "cmGeneratorExpressionDAGChecker.h"
#include <assert.h>
@@ -289,19 +291,40 @@ std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories()
{
std::vector<std::string> includes;
const char *prop = this->Target->GetProperty("INCLUDE_DIRECTORIES");
- if(prop)
+ if(!prop)
{
- cmSystemTools::ExpandListArgument(prop, includes);
+ return includes;
}
+ const char *config = this->Makefile->GetDefinition("CMAKE_BUILD_TYPE");
+ cmListFileBacktrace lfbt;
+ cmGeneratorExpression ge(lfbt);
+
+ cmGeneratorExpressionDAGChecker dagChecker(lfbt,
+ this->GetName(),
+ "INCLUDE_DIRECTORIES", 0, 0);
+
+ cmSystemTools::ExpandListArgument(ge.Parse(prop)
+ .Evaluate(this->Makefile,
+ config,
+ false,
+ this,
+ &dagChecker),
+ includes);
+
std::set<std::string> uniqueIncludes;
std::vector<std::string> orderedAndUniqueIncludes;
for(std::vector<std::string>::const_iterator
li = includes.begin(); li != includes.end(); ++li)
{
- if(uniqueIncludes.insert(*li).second)
+ std::string inc = *li;
+ if (!cmSystemTools::IsOff(inc.c_str()))
+ {
+ cmSystemTools::ConvertToUnixSlashes(inc);
+ }
+ if(uniqueIncludes.insert(inc).second)
{
- orderedAndUniqueIncludes.push_back(*li);
+ orderedAndUniqueIncludes.push_back(inc);
}
}
@@ -309,15 +332,30 @@ std::vector<std::string> cmGeneratorTarget::GetIncludeDirectories()
}
//----------------------------------------------------------------------------
-const char *cmGeneratorTarget::GetCompileDefinitions(const char *config)
+std::string cmGeneratorTarget::GetCompileDefinitions(const char *config)
{
- if (!config)
+ std::string defPropName = "COMPILE_DEFINITIONS";
+ if (config)
{
- return this->Target->GetProperty("COMPILE_DEFINITIONS");
+ defPropName += "_" + cmSystemTools::UpperCase(config);
}
- std::string defPropName = "COMPILE_DEFINITIONS_";
- defPropName +=
- cmSystemTools::UpperCase(config);
- return this->Target->GetProperty(defPropName.c_str());
+ const char *prop = this->Target->GetProperty(defPropName.c_str());
+
+ if (!prop)
+ {
+ return "";
+ }
+
+ cmListFileBacktrace lfbt;
+ cmGeneratorExpression ge(lfbt);
+
+ cmGeneratorExpressionDAGChecker dagChecker(lfbt,
+ this->GetName(),
+ defPropName, 0, 0);
+ return ge.Parse(prop).Evaluate(this->Makefile,
+ config,
+ false,
+ this,
+ &dagChecker);
}
diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h
index 4487c11..8ea17d7 100644
--- a/Source/cmGeneratorTarget.h
+++ b/Source/cmGeneratorTarget.h
@@ -74,7 +74,7 @@ public:
/** Get the include directories for this target. */
std::vector<std::string> GetIncludeDirectories();
- const char *GetCompileDefinitions(const char *config = 0);
+ std::string GetCompileDefinitions(const char *config = 0);
private:
void ClassifySources();
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index ac75933..09588f9 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -21,7 +21,7 @@
#include "cmQtAutomoc.h"
#include "cmSourceFile.h"
#include "cmVersion.h"
-#include "cmExportInstallFileGenerator.h"
+#include "cmTargetExport.h"
#include "cmComputeTargetDepends.h"
#include "cmGeneratedFileStream.h"
#include "cmGeneratorTarget.h"
@@ -76,12 +76,12 @@ cmGlobalGenerator::~cmGlobalGenerator()
}
this->ClearGeneratorTargets();
- this->ClearExportSets();
}
void cmGlobalGenerator::ResolveLanguageCompiler(const std::string &lang,
cmMakefile *mf,
- bool optional) {
+ bool optional)
+{
std::string langComp = "CMAKE_";
langComp += lang;
langComp += "_COMPILER";
@@ -817,7 +817,7 @@ void cmGlobalGenerator::Configure()
{
this->FirstTimeProgress = 0.0f;
this->ClearGeneratorTargets();
- this->ClearExportSets();
+ this->ExportSets.clear();
// Delete any existing cmLocalGenerators
unsigned int i;
for (i = 0; i < this->LocalGenerators.size(); ++i)
@@ -893,7 +893,7 @@ bool cmGlobalGenerator::CheckALLOW_DUPLICATE_CUSTOM_TARGETS()
<< "The \"" << this->GetName() << "\" generator does not support "
<< "duplicate custom targets. "
<< "Consider using a Makefiles generator or fix the project to not "
- << "use duplicat target names.";
+ << "use duplicate target names.";
cmSystemTools::Error(e.str().c_str());
return false;
}
@@ -1489,52 +1489,6 @@ void cmGlobalGenerator::AddInstallComponent(const char* component)
}
}
-void cmGlobalGenerator::AddTargetToExports(const char* exportSetName,
- cmTarget* target,
- cmInstallTargetGenerator* archive,
- cmInstallTargetGenerator* runTime,
- cmInstallTargetGenerator* library,
- cmInstallTargetGenerator* framework,
- cmInstallTargetGenerator* bundle,
- cmInstallFilesGenerator* headers)
-{
- if ((exportSetName) && (*exportSetName) && (target))
- {
- cmTargetExport* te = new cmTargetExport(target, archive, runTime, library,
- framework, bundle, headers);
- this->ExportSets[exportSetName].push_back(te);
- }
-}
-
-//----------------------------------------------------------------------------
-void cmGlobalGenerator::ClearExportSets()
-{
- for(std::map<cmStdString, std::vector<cmTargetExport*> >::iterator
- setIt = this->ExportSets.begin();
- setIt != this->ExportSets.end(); ++setIt)
- {
- for(unsigned int i = 0; i < setIt->second.size(); ++i)
- {
- delete setIt->second[i];
- }
- }
- this->ExportSets.clear();
-}
-
-const std::vector<cmTargetExport*>* cmGlobalGenerator::GetExportSet(
- const char* name) const
-{
- std::map<cmStdString, std::vector<cmTargetExport*> >::const_iterator
- exportSetIt = this->ExportSets.find(name);
- if (exportSetIt != this->ExportSets.end())
- {
- return &exportSetIt->second;
- }
-
- return 0;
-}
-
-
void cmGlobalGenerator::EnableInstallTarget()
{
this->InstallTargetEnabled = true;
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 2f4ebc3..0aab2d6 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -18,14 +18,15 @@
#include "cmTarget.h" // For cmTargets
#include "cmTargetDepend.h" // For cmTargetDependSet
#include "cmSystemTools.h" // for cmSystemTools::OutputOption
+#include "cmExportSetMap.h" // For cmExportSetMap
#include "cmGeneratorTarget.h"
+
class cmake;
class cmGeneratorTarget;
class cmMakefile;
class cmLocalGenerator;
class cmExternalMakefileProjectGenerator;
class cmTarget;
-class cmTargetExport;
class cmInstallTargetGenerator;
class cmInstallFilesGenerator;
@@ -128,8 +129,8 @@ public:
void SetCMakeInstance(cmake *cm);
///! Get the CMake instance
- cmake *GetCMakeInstance() { return this->CMakeInstance; };
- const cmake *GetCMakeInstance() const { return this->CMakeInstance; };
+ cmake *GetCMakeInstance() { return this->CMakeInstance; }
+ const cmake *GetCMakeInstance() const { return this->CMakeInstance; }
void SetConfiguredFilesPath(cmGlobalGenerator* gen);
const std::vector<cmLocalGenerator *>& GetLocalGenerators() const {
@@ -152,18 +153,9 @@ public:
void AddInstallComponent(const char* component);
const std::set<cmStdString>* GetInstallComponents() const
- { return &InstallComponents; }
-
- ///! Add one installed target to the sets of the exports
- void AddTargetToExports(const char* exportSet, cmTarget* target,
- cmInstallTargetGenerator* archive,
- cmInstallTargetGenerator* runTime,
- cmInstallTargetGenerator* library,
- cmInstallTargetGenerator* framework,
- cmInstallTargetGenerator* bundle,
- cmInstallFilesGenerator* publicHeaders);
- ///! Get the export target set with the given name
- const std::vector<cmTargetExport*>* GetExportSet(const char* name) const;
+ { return &this->InstallComponents; }
+
+ cmExportSetMap& GetExportSets() {return this->ExportSets;}
/** Add a file to the manifest of generated targets for a configuration. */
void AddToManifest(const char* config, std::string const& f);
@@ -223,7 +215,7 @@ public:
/** Get the manifest of all targets that will be built for each
configuration. This is valid during generation only. */
cmTargetManifest const& GetTargetManifest() const
- { return this->TargetManifest; }
+ { return this->TargetManifest; }
/** Get the content of a directory. Directory listings are loaded
from disk at most once and cached. During the generation step
@@ -329,15 +321,13 @@ protected:
cmLocalGenerator* CurrentLocalGenerator;
// map from project name to vector of local generators in that project
std::map<cmStdString, std::vector<cmLocalGenerator*> > ProjectMap;
- std::map<cmLocalGenerator*, std::set<cmTarget *> >
- LocalGeneratorToTargetMap;
+ std::map<cmLocalGenerator*, std::set<cmTarget *> > LocalGeneratorToTargetMap;
// Set of named installation components requested by the project.
std::set<cmStdString> InstallComponents;
bool InstallTargetEnabled;
// Sets of named target exports
- std::map<cmStdString, std::vector<cmTargetExport*> > ExportSets;
- void ClearExportSets();
+ cmExportSetMap ExportSets;
// Manifest of all targets that will be built for each configuration.
// This is computed just before local generators generate.
diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx
index 39b0ffe..95c6807 100644
--- a/Source/cmGlobalXCodeGenerator.cxx
+++ b/Source/cmGlobalXCodeGenerator.cxx
@@ -1647,16 +1647,12 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
// Add the export symbol definition for shared library objects.
this->AppendDefines(ppDefs, exportMacro);
}
- this->AppendDefines
- (ppDefs, this->CurrentMakefile->GetProperty("COMPILE_DEFINITIONS"));
- this->AppendDefines(ppDefs, target.GetProperty("COMPILE_DEFINITIONS"));
+ cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&target);
+ this->AppendDefines(ppDefs, gtgt->GetCompileDefinitions().c_str());
if(configName)
{
- std::string defVarName = "COMPILE_DEFINITIONS_";
- defVarName += cmSystemTools::UpperCase(configName);
- this->AppendDefines
- (ppDefs, this->CurrentMakefile->GetProperty(defVarName.c_str()));
- this->AppendDefines(ppDefs, target.GetProperty(defVarName.c_str()));
+ this->AppendDefines(ppDefs,
+ gtgt->GetCompileDefinitions(configName).c_str());
}
buildSettings->AddAttribute
("GCC_PREPROCESSOR_DEFINITIONS", ppDefs.CreateList());
@@ -1713,10 +1709,8 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
// Set target-specific architectures.
std::vector<std::string> archs;
- {
- cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&target);
gtgt->GetAppleArchs(configName, archs);
- }
+
if(!archs.empty())
{
// Enable ARCHS attribute.
@@ -1953,7 +1947,6 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmTarget& target,
BuildObjectListOrString dirs(this, this->XcodeVersion >= 30);
BuildObjectListOrString fdirs(this, this->XcodeVersion >= 30);
std::vector<std::string> includes;
- cmGeneratorTarget *gtgt = this->GetGeneratorTarget(&target);
this->CurrentLocalGenerator->GetIncludeDirectories(includes, gtgt);
std::set<cmStdString> emitted;
emitted.insert("/System/Library/Frameworks");
diff --git a/Source/cmIncludeDirectoryCommand.cxx b/Source/cmIncludeDirectoryCommand.cxx
index 4dd98a1..ba81849 100644
--- a/Source/cmIncludeDirectoryCommand.cxx
+++ b/Source/cmIncludeDirectoryCommand.cxx
@@ -55,6 +55,11 @@ bool cmIncludeDirectoryCommand
return true;
}
+static bool StartsWithGeneratorExpression(const std::string &input)
+{
+ return input[0] == '$' && input[1] == '<';
+}
+
// do a lot of cleanup on the arguments because this is one place where folks
// sometimes take the output of a program and pass it directly into this
// command not thinking that a single argument could be filled with spaces
@@ -105,10 +110,13 @@ void cmIncludeDirectoryCommand::AddDirectory(const char *i,
cmSystemTools::ConvertToUnixSlashes(ret);
if(!cmSystemTools::FileIsFullPath(ret.c_str()))
{
- std::string tmp = this->Makefile->GetStartDirectory();
- tmp += "/";
- tmp += ret;
- ret = tmp;
+ if(!StartsWithGeneratorExpression(ret))
+ {
+ std::string tmp = this->Makefile->GetStartDirectory();
+ tmp += "/";
+ tmp += ret;
+ ret = tmp;
+ }
}
}
this->Makefile->AddIncludeDirectory(ret.c_str(), before);
diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx
index 4016734..dcd418b 100644
--- a/Source/cmInstallCommand.cxx
+++ b/Source/cmInstallCommand.cxx
@@ -17,6 +17,8 @@
#include "cmInstallTargetGenerator.h"
#include "cmInstallExportGenerator.h"
#include "cmInstallCommandArguments.h"
+#include "cmTargetExport.h"
+#include "cmExportSet.h"
#include <cmsys/Glob.hxx>
@@ -735,11 +737,16 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args)
// this is not a namelink-only rule.
if(!exports.GetString().empty() && !namelinkOnly)
{
+ cmTargetExport *te = new cmTargetExport;
+ te->Target = &target;
+ te->ArchiveGenerator = archiveGenerator;
+ te->BundleGenerator = bundleGenerator;
+ te->FrameworkGenerator = frameworkGenerator;
+ te->HeaderGenerator = publicHeaderGenerator;
+ te->LibraryGenerator = libraryGenerator;
+ te->RuntimeGenerator = runtimeGenerator;
this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
- ->AddTargetToExports(exports.GetCString(), &target,
- archiveGenerator, runtimeGenerator,
- libraryGenerator, frameworkGenerator,
- bundleGenerator, publicHeaderGenerator);
+ ->GetExportSets()[exports.GetString()]->AddTargetExport(te);
}
}
@@ -1264,7 +1271,9 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args)
// Create the export install generator.
cmInstallExportGenerator* exportGenerator =
new cmInstallExportGenerator(
- exp.GetCString(), ica.GetDestination().c_str(),
+ this->Makefile->GetLocalGenerator()
+ ->GetGlobalGenerator()->GetExportSets()[exp.GetString()],
+ ica.GetDestination().c_str(),
ica.GetPermissions().c_str(), ica.GetConfigurations(),
ica.GetComponent().c_str(), fname.c_str(),
name_space.GetCString(), this->Makefile);
diff --git a/Source/cmInstallExportGenerator.cxx b/Source/cmInstallExportGenerator.cxx
index 28a19d7..0a645a8 100644
--- a/Source/cmInstallExportGenerator.cxx
+++ b/Source/cmInstallExportGenerator.cxx
@@ -23,10 +23,11 @@
#include "cmInstallFilesGenerator.h"
#include "cmExportInstallFileGenerator.h"
+#include "cmExportSet.h"
//----------------------------------------------------------------------------
cmInstallExportGenerator::cmInstallExportGenerator(
- const char* name,
+ cmExportSet* exportSet,
const char* destination,
const char* file_permissions,
std::vector<std::string> const& configurations,
@@ -34,13 +35,14 @@ cmInstallExportGenerator::cmInstallExportGenerator(
const char* filename, const char* name_space,
cmMakefile* mf)
:cmInstallGenerator(destination, configurations, component)
- ,Name(name)
+ ,ExportSet(exportSet)
,FilePermissions(file_permissions)
,FileName(filename)
,Namespace(name_space)
,Makefile(mf)
{
this->EFGen = new cmExportInstallFileGenerator(this);
+ exportSet->AddInstallation(this);
}
//----------------------------------------------------------------------------
@@ -113,16 +115,12 @@ void cmInstallExportGenerator::ComputeTempDir()
//----------------------------------------------------------------------------
void cmInstallExportGenerator::GenerateScript(std::ostream& os)
{
- // Get the export set requested.
- ExportSet const* exportSet =
- this->Makefile->GetLocalGenerator()->GetGlobalGenerator()
- ->GetExportSet(this->Name.c_str());
-
// Skip empty sets.
- if(!exportSet)
+ if(ExportSet->GetTargetExports()->empty())
{
cmOStringStream e;
- e << "INSTALL(EXPORT) given unknown export \"" << this->Name << "\"";
+ e << "INSTALL(EXPORT) given unknown export \""
+ << ExportSet->GetName() << "\"";
cmSystemTools::Error(e.str().c_str());
return;
}
@@ -137,8 +135,6 @@ void cmInstallExportGenerator::GenerateScript(std::ostream& os)
this->MainImportFile += this->FileName;
// Generate the import file for this export set.
- this->EFGen->SetName(this->Name.c_str());
- this->EFGen->SetExportSet(exportSet);
this->EFGen->SetExportFile(this->MainImportFile.c_str());
this->EFGen->SetNamespace(this->Namespace.c_str());
if(this->ConfigurationTypes->empty())
diff --git a/Source/cmInstallExportGenerator.h b/Source/cmInstallExportGenerator.h
index 1ff6e38..ee92906 100644
--- a/Source/cmInstallExportGenerator.h
+++ b/Source/cmInstallExportGenerator.h
@@ -17,8 +17,7 @@
class cmExportInstallFileGenerator;
class cmInstallFilesGenerator;
class cmInstallTargetGenerator;
-class cmTarget;
-class cmTargetExport;
+class cmExportSet;
class cmMakefile;
/** \class cmInstallExportGenerator
@@ -27,24 +26,27 @@ class cmMakefile;
class cmInstallExportGenerator: public cmInstallGenerator
{
public:
- cmInstallExportGenerator(const char* name,
+ cmInstallExportGenerator(cmExportSet* exportSet,
const char* dest, const char* file_permissions,
const std::vector<std::string>& configurations,
const char* component,
const char* filename, const char* name_space,
cmMakefile* mf);
~cmInstallExportGenerator();
-protected:
- typedef std::vector<cmTargetExport*> ExportSet;
+ cmExportSet* GetExportSet() {return this->ExportSet;}
+
+ const std::string& GetNamespace() const { return this->Namespace; }
+
+protected:
virtual void GenerateScript(std::ostream& os);
virtual void GenerateScriptConfigs(std::ostream& os, Indent const& indent);
virtual void GenerateScriptActions(std::ostream& os, Indent const& indent);
- void GenerateImportFile(ExportSet const* exportSet);
- void GenerateImportFile(const char* config, ExportSet const* exportSet);
+ void GenerateImportFile(cmExportSet const* exportSet);
+ void GenerateImportFile(const char* config, cmExportSet const* exportSet);
void ComputeTempDir();
- std::string Name;
+ cmExportSet* ExportSet;
std::string FilePermissions;
std::string FileName;
std::string Namespace;
diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx
index 2b36ad0..c7995a3 100644
--- a/Source/cmLocalGenerator.cxx
+++ b/Source/cmLocalGenerator.cxx
@@ -1394,6 +1394,11 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
}
}
+ if(!target)
+ {
+ return;
+ }
+
// Load implicit include directories for this language.
std::string impDirVar = "CMAKE_";
impDirVar += lang;
@@ -1411,10 +1416,8 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs,
// Get the target-specific include directories.
std::vector<std::string> includes;
- if(target)
- {
- includes = target->GetIncludeDirectories();
- }
+
+ includes = target->GetIncludeDirectories();
// 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 51d5924..49bce38 100644
--- a/Source/cmLocalGenerator.h
+++ b/Source/cmLocalGenerator.h
@@ -157,6 +157,11 @@ public:
*/
void AppendDefines(std::set<std::string>& defines,
const char* defines_list);
+ void AppendDefines(std::set<std::string>& defines,
+ std::string defines_list)
+ {
+ this->AppendDefines(defines, defines_list.c_str());
+ }
/**
* Join a set of defines into a definesString with a space separator.
*/
diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx
index 2ededfe..33d6e05 100644
--- a/Source/cmLocalVisualStudio7Generator.cxx
+++ b/Source/cmLocalVisualStudio7Generator.cxx
@@ -724,10 +724,6 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
flags += targetFlags;
}
- std::string configUpper = cmSystemTools::UpperCase(configName);
- std::string defPropName = "COMPILE_DEFINITIONS_";
- defPropName += configUpper;
-
// Get preprocessor definitions for this directory.
std::string defineFlags = this->Makefile->GetDefineFlags();
Options::Tool t = Options::Compiler;
@@ -744,11 +740,10 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
targetOptions.Parse(flags.c_str());
targetOptions.Parse(defineFlags.c_str());
targetOptions.ParseFinish();
- targetOptions.AddDefines
- (this->Makefile->GetProperty("COMPILE_DEFINITIONS"));
- targetOptions.AddDefines(target.GetProperty("COMPILE_DEFINITIONS"));
- targetOptions.AddDefines(this->Makefile->GetProperty(defPropName.c_str()));
- targetOptions.AddDefines(target.GetProperty(defPropName.c_str()));
+ cmGeneratorTarget* gt =
+ this->GlobalGenerator->GetGeneratorTarget(&target);
+ targetOptions.AddDefines(gt->GetCompileDefinitions().c_str());
+ targetOptions.AddDefines(gt->GetCompileDefinitions(configName).c_str());
targetOptions.SetVerboseMakefile(
this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));
@@ -819,8 +814,6 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
targetOptions.OutputAdditionalOptions(fout, "\t\t\t\t", "\n");
fout << "\t\t\t\tAdditionalIncludeDirectories=\"";
std::vector<std::string> includes;
- cmGeneratorTarget* gt =
- this->GlobalGenerator->GetGeneratorTarget(&target);
this->GetIncludeDirectories(includes, gt);
std::vector<std::string>::iterator i = includes.begin();
for(;i != includes.end(); ++i)
@@ -849,7 +842,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout,
// non-debug configurations because VS still creates .idb files.
fout << "\t\t\t\tProgramDataBaseFileName=\""
<< this->ConvertToXMLOutputPathSingle(
- target.GetDirectory(configName).c_str())
+ target.GetPDBDirectory(configName).c_str())
<< "/"
<< target.GetPDBName(configName) << "\"\n";
}
@@ -1129,7 +1122,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
fout << "\t\t\t\tAdditionalLibraryDirectories=\"";
this->OutputLibraryDirectories(fout, cli.GetDirectories());
fout << "\"\n";
- temp = target.GetDirectory(configName);
+ temp = target.GetPDBDirectory(configName);
temp += "/";
temp += targetNamePDB;
fout << "\t\t\t\tProgramDatabaseFile=\"" <<
@@ -1217,7 +1210,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout,
this->OutputLibraryDirectories(fout, cli.GetDirectories());
fout << "\"\n";
std::string path = this->ConvertToXMLOutputPathSingle(
- target.GetDirectory(configName).c_str());
+ target.GetPDBDirectory(configName).c_str());
fout << "\t\t\t\tProgramDatabaseFile=\""
<< path << "/" << targetNamePDB
<< "\"\n";
diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx
index da66656..b7a454b 100644
--- a/Source/cmMakefileExecutableTargetGenerator.cxx
+++ b/Source/cmMakefileExecutableTargetGenerator.cxx
@@ -131,9 +131,14 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink)
outpathImp += "/";
}
}
+
+ std::string pdbOutputPath = this->Target->GetPDBDirectory();
+ cmSystemTools::MakeDirectory(pdbOutputPath.c_str());
+ pdbOutputPath += "/";
+
std::string targetFullPath = outpath + targetName;
std::string targetFullPathReal = outpath + targetNameReal;
- std::string targetFullPathPDB = outpath + targetNamePDB;
+ std::string targetFullPathPDB = pdbOutputPath + targetNamePDB;
std::string targetFullPathImport = outpathImp + targetNameImport;
std::string targetOutPathPDB =
this->Convert(targetFullPathPDB.c_str(),
diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx
index d39e7fa..e7004d6 100644
--- a/Source/cmMakefileLibraryTargetGenerator.cxx
+++ b/Source/cmMakefileLibraryTargetGenerator.cxx
@@ -328,8 +328,12 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules
}
}
+ std::string pdbOutputPath = this->Target->GetPDBDirectory();
+ cmSystemTools::MakeDirectory(pdbOutputPath.c_str());
+ pdbOutputPath += "/";
+
std::string targetFullPath = outpath + targetName;
- std::string targetFullPathPDB = outpath + targetNamePDB;
+ std::string targetFullPathPDB = pdbOutputPath + targetNamePDB;
std::string targetFullPathSO = outpath + targetNameSO;
std::string targetFullPathReal = outpath + targetNameReal;
std::string targetFullPathImport = outpathImp + targetNameImport;
diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx
index 9560c10..5cc67e2 100644
--- a/Source/cmMakefileTargetGenerator.cxx
+++ b/Source/cmMakefileTargetGenerator.cxx
@@ -647,7 +647,7 @@ cmMakefileTargetGenerator
this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
this->Target->GetType() == cmTarget::MODULE_LIBRARY)
{
- targetFullPathPDB = this->Target->GetDirectory(this->ConfigName);
+ targetFullPathPDB = this->Target->GetPDBDirectory(this->ConfigName);
targetFullPathPDB += "/";
targetFullPathPDB += this->Target->GetPDBName(this->ConfigName);
}
diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx
index 57997ee..612e047 100644
--- a/Source/cmNinjaTargetGenerator.cxx
+++ b/Source/cmNinjaTargetGenerator.cxx
@@ -329,10 +329,10 @@ bool cmNinjaTargetGenerator::SetMsvcTargetPdbVariable(cmNinjaVars& vars) const
this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
this->Target->GetType() == cmTarget::MODULE_LIBRARY)
{
- pdbPath = this->Target->GetDirectory(this->GetConfigName());
+ pdbPath = this->Target->GetPDBDirectory(this->GetConfigName());
pdbPath += "/";
pdbPath += this->Target->GetPDBName(this->GetConfigName());
- }
+ }
vars["TARGET_PDB"] = this->GetLocalGenerator()->ConvertToOutputFormat(
ConvertToNinjaPath(pdbPath.c_str()).c_str(),
@@ -508,8 +508,6 @@ void
cmNinjaTargetGenerator
::WriteObjectBuildStatement(cmSourceFile* source)
{
- cmNinjaDeps emptyDeps;
-
std::string comment;
const std::string language = source->GetLanguage();
std::string rule = this->LanguageCompilerRule(language);
@@ -533,11 +531,12 @@ cmNinjaTargetGenerator
cmNinjaDeps orderOnlyDeps;
this->GetLocalGenerator()->AppendTargetDepends(this->Target, orderOnlyDeps);
+ cmNinjaDeps implicitDeps;
if(const char* objectDeps = source->GetProperty("OBJECT_DEPENDS")) {
std::vector<std::string> depList;
cmSystemTools::ExpandListArgument(objectDeps, depList);
std::transform(depList.begin(), depList.end(),
- std::back_inserter(orderOnlyDeps), MapToNinjaPath());
+ std::back_inserter(implicitDeps), MapToNinjaPath());
}
// Add order-only dependencies on custom command outputs.
@@ -619,7 +618,7 @@ cmNinjaTargetGenerator
rule,
outputs,
explicitDeps,
- emptyDeps,
+ implicitDeps,
orderOnlyDeps,
vars);
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx
index 532d482..423b350 100644
--- a/Source/cmTarget.cxx
+++ b/Source/cmTarget.cxx
@@ -16,6 +16,7 @@
#include "cmLocalGenerator.h"
#include "cmGlobalGenerator.h"
#include "cmDocumentCompileDefinitions.h"
+#include "cmDocumentGeneratorExpressions.h"
#include "cmDocumentLocationUndefined.h"
#include "cmListFileCache.h"
#include "cmGeneratorExpression.h"
@@ -56,6 +57,7 @@ struct cmTarget::OutputInfo
{
std::string OutDir;
std::string ImpDir;
+ std::string PdbDir;
};
//----------------------------------------------------------------------------
@@ -204,6 +206,9 @@ void cmTarget::DefineProperties(cmake *cm)
"are not supported by the native build tool. "
"The VS6 IDE does not support definition values with spaces "
"(but NMake does).\n"
+ "Contents of COMPILE_DEFINITIONS may use \"generator expressions\" with "
+ "the syntax \"$<...>\". "
+ CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS
CM_DOCUMENT_COMPILE_DEFINITIONS_DISCLAIMER);
cm->DefineProperty
@@ -497,8 +502,11 @@ void cmTarget::DefineProperties(cmake *cm)
"to the include_directories command."
"\n"
"The target property values are used by the generators to set "
- "the include paths for the compiler. "
- "See also the include_directories command.");
+ "the include paths for the compiler. "
+ "See also the include_directories command.\n"
+ "Contents of INCLUDE_DIRECTORIES may use \"generator expressions\" with "
+ "the syntax \"$<...>\". "
+ CM_DOCUMENT_COMMAND_GENERATOR_EXPRESSIONS);
cm->DefineProperty
("INSTALL_NAME_DIR", cmProperty::TARGET,
@@ -740,6 +748,22 @@ void cmTarget::DefineProperties(cmake *cm)
"Use OUTPUT_NAME_<CONFIG> instead.");
cm->DefineProperty
+ ("PDB_NAME", cmProperty::TARGET,
+ "Output name for MS debug symbols .pdb file.",
+ "Set the base name for debug symbols file created for an "
+ "executable or library target. "
+ "If not set, the logical target name is used by default. "
+ "\n"
+ "This property is not implemented by the Visual Studio 6 generator.");
+
+ cm->DefineProperty
+ ("PDB_NAME_<CONFIG>", cmProperty::TARGET,
+ "Per-configuration name for MS debug symbols .pdb file. ",
+ "This is the configuration-specific version of PDB_NAME. "
+ "\n"
+ "This property is not implemented by the Visual Studio 6 generator.");
+
+ cm->DefineProperty
("PRE_INSTALL_SCRIPT", cmProperty::TARGET,
"Deprecated install support.",
"The PRE_INSTALL_SCRIPT and POST_INSTALL_SCRIPT properties are the "
@@ -1189,6 +1213,27 @@ void cmTarget::DefineProperties(cmake *cm)
CM_TARGET_OUTDIR_CONFIG_DOC(RUNTIME));
cm->DefineProperty
+ ("PDB_OUTPUT_DIRECTORY", cmProperty::TARGET,
+ "Output directory for MS debug symbols .pdb files.",
+ "This property specifies the directory into which the MS debug symbols "
+ "will be placed. "
+ "This property is initialized by the value of the variable "
+ "CMAKE_PDB_OUTPUT_DIRECTORY if it is set when a target is created."
+ "\n"
+ "This property is not implemented by the Visual Studio 6 generator.");
+ cm->DefineProperty
+ ("PDB_OUTPUT_DIRECTORY_<CONFIG>", cmProperty::TARGET,
+ "Per-configuration output directory for MS debug symbols .pdb files.",
+ "This is a per-configuration version of PDB_OUTPUT_DIRECTORY, "
+ "but multi-configuration generators (VS, Xcode) do NOT append "
+ "a per-configuration subdirectory to the specified directory. "
+ "This property is initialized by the value of the variable "
+ "CMAKE_PDB_OUTPUT_DIRECTORY_<CONFIG> "
+ "if it is set when a target is created."
+ "\n"
+ "This property is not implemented by the Visual Studio 6 generator.");
+
+ cm->DefineProperty
("ARCHIVE_OUTPUT_NAME", cmProperty::TARGET,
"Output name for ARCHIVE target files.",
"This property specifies the base name for archive target files. "
@@ -1262,6 +1307,7 @@ void cmTarget::SetMakefile(cmMakefile* mf)
this->SetPropertyDefault("ARCHIVE_OUTPUT_DIRECTORY", 0);
this->SetPropertyDefault("LIBRARY_OUTPUT_DIRECTORY", 0);
this->SetPropertyDefault("RUNTIME_OUTPUT_DIRECTORY", 0);
+ this->SetPropertyDefault("PDB_OUTPUT_DIRECTORY", 0);
this->SetPropertyDefault("Fortran_FORMAT", 0);
this->SetPropertyDefault("Fortran_MODULE_DIRECTORY", 0);
this->SetPropertyDefault("GNUtoMS", 0);
@@ -1281,6 +1327,7 @@ void cmTarget::SetMakefile(cmMakefile* mf)
"ARCHIVE_OUTPUT_DIRECTORY_",
"LIBRARY_OUTPUT_DIRECTORY_",
"RUNTIME_OUTPUT_DIRECTORY_",
+ "PDB_OUTPUT_DIRECTORY_",
0};
for(std::vector<std::string>::iterator ci = configNames.begin();
ci != configNames.end(); ++ci)
@@ -2013,9 +2060,8 @@ bool cmTarget::NameResolvesToFramework(const std::string& libname)
}
//----------------------------------------------------------------------------
-bool cmTarget::AddFramework(const std::string& libname, LinkLibraryType llt)
+bool cmTarget::AddFramework(const std::string& libname, LinkLibraryType)
{
- (void)llt; // TODO: What is this?
if(this->NameResolvesToFramework(libname.c_str()))
{
std::string frameworkDir = libname;
@@ -2295,7 +2341,7 @@ void cmTarget::Emit(const LibraryID lib,
// be preserved.
// This variable will keep track of the libraries that were
- // emitted directory from the current node, and not from a
+ // emitted directly from the current node, and not from a
// recursive call. This way, if we come across a library that
// has already been emitted, we repeat it iff it has been
// emitted here.
@@ -2413,7 +2459,7 @@ void cmTarget::AppendProperty(const char* prop, const char* value,
//----------------------------------------------------------------------------
void cmTarget::MaybeInvalidatePropertyCache(const char* prop)
{
- // Wipe wipe out maps caching information affected by this property.
+ // Wipe out maps caching information affected by this property.
if(this->IsImported() && strncmp(prop, "IMPORTED", 8) == 0)
{
this->Internal->ImportInfoMap.clear();
@@ -2538,6 +2584,7 @@ cmTarget::OutputInfo const* cmTarget::GetOutputInfo(const char* config)
OutputInfo info;
this->ComputeOutputDir(config, false, info.OutDir);
this->ComputeOutputDir(config, true, info.ImpDir);
+ this->ComputePDBOutputDir(config, info.PdbDir);
OutputInfoMapType::value_type entry(config_upper, info);
i = this->Internal->OutputInfoMap.insert(entry).first;
}
@@ -2563,6 +2610,17 @@ std::string cmTarget::GetDirectory(const char* config, bool implib)
}
//----------------------------------------------------------------------------
+std::string cmTarget::GetPDBDirectory(const char* config)
+{
+ if(OutputInfo const* info = this->GetOutputInfo(config))
+ {
+ // Return the directory in which the target will be built.
+ return info->PdbDir;
+ }
+ return "";
+}
+
+//----------------------------------------------------------------------------
const char* cmTarget::GetLocation(const char* config)
{
if (this->IsImported())
@@ -3008,6 +3066,28 @@ std::string cmTarget::GetPDBName(const char* config)
std::string base;
std::string suffix;
this->GetFullNameInternal(config, false, prefix, base, suffix);
+
+ std::vector<std::string> props;
+ std::string configUpper =
+ cmSystemTools::UpperCase(config? config : "");
+ if(!configUpper.empty())
+ {
+ // PDB_NAME_<CONFIG>
+ props.push_back("PDB_NAME_" + configUpper);
+ }
+
+ // PDB_NAME
+ props.push_back("PDB_NAME");
+
+ for(std::vector<std::string>::const_iterator i = props.begin();
+ i != props.end(); ++i)
+ {
+ if(const char* outName = this->GetProperty(i->c_str()))
+ {
+ base = outName;
+ break;
+ }
+ }
return prefix+base+".pdb";
}
@@ -3392,7 +3472,7 @@ void cmTarget::GetLibraryNames(std::string& name,
}
// The program database file name.
- pdbName = prefix+base+".pdb";
+ pdbName = this->GetPDBName(config);
}
//----------------------------------------------------------------------------
@@ -3471,7 +3551,7 @@ void cmTarget::GetExecutableNames(std::string& name,
impName = this->GetFullNameInternal(config, true);
// The program database file name.
- pdbName = prefix+base+".pdb";
+ pdbName = this->GetPDBName(config);
}
//----------------------------------------------------------------------------
@@ -3550,7 +3630,7 @@ void cmTarget::GenerateTargetManifest(const char* config)
}
if(!pdbName.empty())
{
- f = dir;
+ f = this->GetPDBDirectory(config);
f += "/";
f += pdbName;
gg->AddToManifest(config? config:"", f);
@@ -3860,6 +3940,65 @@ bool cmTarget::ComputeOutputDir(const char* config,
}
//----------------------------------------------------------------------------
+void cmTarget::ComputePDBOutputDir(const char* config, std::string& out)
+{
+ // Look for a target property defining the target output directory
+ // based on the target type.
+ std::string targetTypeName = "PDB";
+ const char* propertyName = 0;
+ std::string propertyNameStr = targetTypeName;
+ if(!propertyNameStr.empty())
+ {
+ propertyNameStr += "_OUTPUT_DIRECTORY";
+ propertyName = propertyNameStr.c_str();
+ }
+
+ // Check for a per-configuration output directory target property.
+ std::string configUpper = cmSystemTools::UpperCase(config? config : "");
+ const char* configProp = 0;
+ std::string configPropStr = targetTypeName;
+ if(!configPropStr.empty())
+ {
+ configPropStr += "_OUTPUT_DIRECTORY_";
+ configPropStr += configUpper;
+ configProp = configPropStr.c_str();
+ }
+
+ // Select an output directory.
+ if(const char* config_outdir = this->GetProperty(configProp))
+ {
+ // Use the user-specified per-configuration output directory.
+ out = config_outdir;
+
+ // Skip per-configuration subdirectory.
+ config = 0;
+ }
+ else if(const char* outdir = this->GetProperty(propertyName))
+ {
+ // Use the user-specified output directory.
+ out = outdir;
+ }
+ if(out.empty())
+ {
+ // Default to the current output directory.
+ out = ".";
+ }
+
+ // Convert the output path to a full path in case it is
+ // specified as a relative path. Treat a relative path as
+ // relative to the current output directory for this makefile.
+ out = (cmSystemTools::CollapseFullPath
+ (out.c_str(), this->Makefile->GetStartOutputDirectory()));
+
+ // The generator may add the configuration's subdirectory.
+ if(config && *config)
+ {
+ this->Makefile->GetLocalGenerator()->GetGlobalGenerator()->
+ AppendDirectoryForConfig("/", config, "", out);
+ }
+}
+
+//----------------------------------------------------------------------------
bool cmTarget::UsesDefaultOutputDir(const char* config, bool implib)
{
std::string dir;
diff --git a/Source/cmTarget.h b/Source/cmTarget.h
index 1f6bb46..558bfab 100644
--- a/Source/cmTarget.h
+++ b/Source/cmTarget.h
@@ -291,6 +291,12 @@ public:
output directory is given. */
std::string GetDirectory(const char* config = 0, bool implib = false);
+ /** Get the directory in which this targets .pdb files will be placed.
+ If the configuration name is given then the generator will add its
+ subdirectory for that configuration. Otherwise just the canonical
+ pdb output directory is given. */
+ std::string GetPDBDirectory(const char* config = 0);
+
/** Get the location of the target in the build tree for the given
configuration. This location is suitable for use as the LOCATION
target property. */
@@ -571,6 +577,7 @@ private:
struct OutputInfo;
OutputInfo const* GetOutputInfo(const char* config);
bool ComputeOutputDir(const char* config, bool implib, std::string& out);
+ void ComputePDBOutputDir(const char* config, std::string& out);
// Cache import information from properties for each configuration.
struct ImportInfo;
diff --git a/Source/cmTargetExport.h b/Source/cmTargetExport.h
new file mode 100644
index 0000000..c9d87fb
--- /dev/null
+++ b/Source/cmTargetExport.h
@@ -0,0 +1,39 @@
+/*============================================================================
+ CMake - Cross Platform Makefile Generator
+ Copyright 2000-2012 Kitware, Inc., Insight Software Consortium
+
+ 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 cmTargetExport_h
+#define cmTargetExport_h
+
+class cmTarget;
+class cmInstallTargetGenerator;
+class cmInstallFilesGenerator;
+
+/** \brief A member of an ExportSet
+ *
+ * This struct holds pointers to target and all relevant generators.
+ */
+class cmTargetExport
+{
+public:
+ cmTarget* Target; ///< The target
+
+ ///@name Generators
+ ///@{
+ cmInstallTargetGenerator* ArchiveGenerator;
+ cmInstallTargetGenerator* RuntimeGenerator;
+ cmInstallTargetGenerator* LibraryGenerator;
+ cmInstallTargetGenerator* FrameworkGenerator;
+ cmInstallTargetGenerator* BundleGenerator;
+ cmInstallFilesGenerator* HeaderGenerator;
+ ///@}
+};
+
+#endif
diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx
index dbea1c3..f42b0f6 100644
--- a/Source/cmTargetLinkLibrariesCommand.cxx
+++ b/Source/cmTargetLinkLibrariesCommand.cxx
@@ -108,8 +108,8 @@ bool cmTargetLinkLibrariesCommand
// specification if the keyword is encountered as the first argument.
this->CurrentProcessingState = ProcessingLinkLibraries;
- // add libraries, nothe that there is an optional prefix
- // of debug and optimized than can be used
+ // add libraries, note that there is an optional prefix
+ // of debug and optimized that can be used
for(unsigned int i=1; i < args.size(); ++i)
{
if(args[i] == "LINK_INTERFACE_LIBRARIES")
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index fea117a..ab57a32 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -1225,21 +1225,16 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions(
flags += " ";
flags += targetFlags;
}
- std::string configUpper = cmSystemTools::UpperCase(configName);
- std::string defPropName = "COMPILE_DEFINITIONS_";
- defPropName += configUpper;
-
// Get preprocessor definitions for this directory.
std::string defineFlags = this->Target->GetMakefile()->GetDefineFlags();
clOptions.FixExceptionHandlingDefault();
clOptions.AddFlag("PrecompiledHeader", "NotUsing");
clOptions.Parse(flags.c_str());
clOptions.Parse(defineFlags.c_str());
- clOptions.AddDefines
- (this->Makefile->GetProperty("COMPILE_DEFINITIONS"));
- clOptions.AddDefines(this->Target->GetProperty("COMPILE_DEFINITIONS"));
- clOptions.AddDefines(this->Makefile->GetProperty(defPropName.c_str()));
- clOptions.AddDefines(this->Target->GetProperty(defPropName.c_str()));
+ clOptions.AddDefines(
+ this->GeneratorTarget->GetCompileDefinitions().c_str());
+ clOptions.AddDefines(this->GeneratorTarget->GetCompileDefinitions(
+ configName.c_str()).c_str());
clOptions.SetVerboseMakefile(
this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"));
@@ -1284,9 +1279,8 @@ void cmVisualStudio10TargetGenerator::WriteClOptions(
this->WriteString("<ObjectFileName>$(IntDir)</ObjectFileName>\n", 3);
if(this->Target->GetType() != cmTarget::OBJECT_LIBRARY)
{
- // TODO: PDB for object library?
this->WriteString("<ProgramDataBaseFileName>", 3);
- *this->BuildFileStream << this->Target->GetDirectory(configName.c_str())
+ *this->BuildFileStream << this->Target->GetPDBDirectory(configName.c_str())
<< "/"
<< this->Target->GetPDBName(configName.c_str())
<< "</ProgramDataBaseFileName>\n";
@@ -1511,9 +1505,8 @@ void cmVisualStudio10TargetGenerator::WriteLinkOptions(std::string const&
config.c_str());
}
- std::string dir = this->Target->GetDirectory(config.c_str());
- dir += "/";
- std::string pdb = dir;
+ std::string pdb = this->Target->GetPDBDirectory(config.c_str());
+ pdb += "/";
pdb += targetNamePDB;
std::string imLib = this->Target->GetDirectory(config.c_str(), true);
imLib += "/";
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index e03b926..ae69ce8 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -1254,6 +1254,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DVERSION=master -P ${CMake_SOURCE_DIR}/Utilities/
if(CMAKE_TEST_MSVC)
ADD_TEST_MACRO(ForceInclude foo)
+ ADD_TEST_MACRO(PDBDirectoryAndName myexe)
ADD_TEST_MACRO(PrecompiledHeader foo)
endif()
if(CMAKE_TEST_MSVC OR
diff --git a/Tests/CompileDefinitions/compiletest.cpp b/Tests/CompileDefinitions/compiletest.cpp
index 6db6f3f..4a68a07 100644
--- a/Tests/CompileDefinitions/compiletest.cpp
+++ b/Tests/CompileDefinitions/compiletest.cpp
@@ -27,6 +27,15 @@ enum {
#endif
};
+#ifdef TEST_GENERATOR_EXPRESSIONS
+#ifndef CMAKE_IS_DECLARATIVE
+#error Expect declarative definition
+#endif
+#ifdef GE_NOT_DEFINED
+#error Expect not defined generator expression
+#endif
+#endif
+
int main(int argc, char **argv)
{
return 0;
diff --git a/Tests/CompileDefinitions/target_prop/CMakeLists.txt b/Tests/CompileDefinitions/target_prop/CMakeLists.txt
index e2b6ba9..fcb22b0 100644
--- a/Tests/CompileDefinitions/target_prop/CMakeLists.txt
+++ b/Tests/CompileDefinitions/target_prop/CMakeLists.txt
@@ -7,3 +7,9 @@ set_target_properties(target_prop_executable PROPERTIES COMPILE_DEFINITIONS CMAK
set_property(TARGET target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS CMAKE_IS_REALLY="Very Fun" CMAKE_IS=Fun)
set_property(TARGET target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS CMAKE_IS_FUN CMAKE_IS_="Fun")
+
+set_property(TARGET target_prop_executable APPEND PROPERTY COMPILE_DEFINITIONS
+ TEST_GENERATOR_EXPRESSIONS
+ "$<1:CMAKE_IS_DECLARATIVE>"
+ "$<0:GE_NOT_DEFINED>"
+)
diff --git a/Tests/ExportImport/Export/CMakeLists.txt b/Tests/ExportImport/Export/CMakeLists.txt
index f118c30..e19ab88 100644
--- a/Tests/ExportImport/Export/CMakeLists.txt
+++ b/Tests/ExportImport/Export/CMakeLists.txt
@@ -87,6 +87,18 @@ target_link_libraries(testLibCycleA testLibCycleB)
target_link_libraries(testLibCycleB testLibCycleA)
set_property(TARGET testLibCycleA PROPERTY LINK_INTERFACE_MULTIPLICITY 3)
+# Test exporting dependent libraries into different exports
+add_library(testLibRequired testLibRequired.c)
+add_library(testLibDepends testLibDepends.c)
+target_link_libraries(testLibDepends testLibRequired)
+
+install(TARGETS testLibRequired EXPORT RequiredExp DESTINATION lib )
+install(EXPORT RequiredExp NAMESPACE Req:: FILE testLibRequiredConfig.cmake DESTINATION lib/cmake/testLibRequired)
+
+install(TARGETS testLibDepends EXPORT DependsExp DESTINATION lib )
+install(EXPORT DependsExp FILE testLibDependsConfig.cmake DESTINATION lib/cmake/testLibDepends)
+
+
# Install and export from install tree.
install(
TARGETS
diff --git a/Tests/ExportImport/Export/testLibDepends.c b/Tests/ExportImport/Export/testLibDepends.c
new file mode 100644
index 0000000..2849b33
--- /dev/null
+++ b/Tests/ExportImport/Export/testLibDepends.c
@@ -0,0 +1,4 @@
+
+extern int testLibRequired(void);
+
+int testLibDepends(void) { return testLibRequired(); }
diff --git a/Tests/ExportImport/Export/testLibRequired.c b/Tests/ExportImport/Export/testLibRequired.c
new file mode 100644
index 0000000..e126d44
--- /dev/null
+++ b/Tests/ExportImport/Export/testLibRequired.c
@@ -0,0 +1 @@
+int testLibRequired(void) { return 0; }
diff --git a/Tests/ExportImport/Import/A/CMakeLists.txt b/Tests/ExportImport/Import/A/CMakeLists.txt
index 650af6a..8841792 100644
--- a/Tests/ExportImport/Import/A/CMakeLists.txt
+++ b/Tests/ExportImport/Import/A/CMakeLists.txt
@@ -4,6 +4,10 @@ include(${Import_BINARY_DIR}/../Export/ExportBuildTree.cmake)
# Import targets from the exported install tree.
include(${CMAKE_INSTALL_PREFIX}/lib/exp/exp.cmake)
+# Import two exports, where the Depends one depends on an exported target from the Required one:
+include(${CMAKE_INSTALL_PREFIX}/lib/cmake/testLibRequired/testLibRequiredConfig.cmake)
+include(${CMAKE_INSTALL_PREFIX}/lib/cmake/testLibDepends/testLibDependsConfig.cmake)
+
# Try referencing an executable imported from the install tree.
add_custom_command(
OUTPUT ${Import_BINARY_DIR}/exp_generated.c
diff --git a/Tests/GeneratorExpression/CMakeLists.txt b/Tests/GeneratorExpression/CMakeLists.txt
index 2b135dc..79a8abb 100644
--- a/Tests/GeneratorExpression/CMakeLists.txt
+++ b/Tests/GeneratorExpression/CMakeLists.txt
@@ -22,6 +22,23 @@ add_custom_target(check ALL
-Dtest_or_1=$<OR:1>
-Dtest_or_1_0=$<OR:1,0>
-Dtest_or_1_1=$<OR:1,1>
+ -Dtest_bool_notfound=$<BOOL:NOTFOUND>
+ -Dtest_bool_foo_notfound=$<BOOL:Foo-NOTFOUND>
+ -Dtest_bool_true=$<BOOL:True>
+ -Dtest_bool_false=$<BOOL:False>
+ -Dtest_bool_on=$<BOOL:On>
+ -Dtest_bool_off=$<BOOL:Off>
+ -Dtest_bool_no=$<BOOL:No>
+ -Dtest_bool_n=$<BOOL:N>
+ -Dtest_strequal_yes_yes=$<STREQUAL:Yes,Yes>
+ -Dtest_strequal_yes_yes_cs=$<STREQUAL:Yes,yes>
+ -Dtest_strequal_yes_no=$<STREQUAL:Yes,No>
+ -Dtest_strequal_no_yes=$<STREQUAL:No,Yes>
+ -Dtest_strequal_angle_r=$<STREQUAL:$<ANGLE-R>,$<ANGLE-R>>
+ -Dtest_strequal_comma=$<STREQUAL:$<COMMA>,$<COMMA>>
+ -Dtest_strequal_angle_r_comma=$<STREQUAL:$<ANGLE-R>,$<COMMA>>
+ -Dtest_angle_r=$<ANGLE-R>
+ -Dtest_comma=$<COMMA>
-P ${CMAKE_CURRENT_SOURCE_DIR}/check.cmake
COMMAND ${CMAKE_COMMAND} -E echo "check done"
VERBATIM
diff --git a/Tests/GeneratorExpression/check.cmake b/Tests/GeneratorExpression/check.cmake
index e243d85..6fb87a2 100644
--- a/Tests/GeneratorExpression/check.cmake
+++ b/Tests/GeneratorExpression/check.cmake
@@ -23,3 +23,20 @@ check(test_or_0_1 "1")
check(test_or_1 "1")
check(test_or_1_0 "1")
check(test_or_1_1 "1")
+check(test_bool_notfound "0")
+check(test_bool_foo_notfound "0")
+check(test_bool_true "1")
+check(test_bool_false "0")
+check(test_bool_on "1")
+check(test_bool_off "0")
+check(test_bool_no "0")
+check(test_bool_n "0")
+check(test_strequal_yes_yes "1")
+check(test_strequal_yes_yes_cs "0")
+check(test_strequal_yes_no "0")
+check(test_strequal_no_yes "0")
+check(test_strequal_angle_r "1")
+check(test_strequal_comma "1")
+check(test_strequal_angle_r_comma "0")
+check(test_angle_r ">")
+check(test_comma ",")
diff --git a/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt b/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt
index 334b8be..4b6f682 100644
--- a/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt
+++ b/Tests/IncludeDirectories/TargetIncludeDirectories/CMakeLists.txt
@@ -12,13 +12,21 @@ create_header(bar)
create_header(bat)
create_header(foo)
create_header(baz)
+create_header(bang)
+create_header(bing)
+create_header(bung)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
include_directories("${CMAKE_CURRENT_BINARY_DIR}/bar")
+include_directories("$<1:${CMAKE_CURRENT_BINARY_DIR}/bang>")
add_executable(TargetIncludeDirectories main.cpp)
set_property(TARGET TargetIncludeDirectories APPEND PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/bat")
set_property(TARGET TargetIncludeDirectories APPEND PROPERTY INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/foo")
+set_property(TARGET TargetIncludeDirectories APPEND PROPERTY
+ INCLUDE_DIRECTORIES "$<1:${CMAKE_CURRENT_BINARY_DIR}/bing>")
include_directories("${CMAKE_CURRENT_BINARY_DIR}/baz")
+include_directories("$<1:${CMAKE_CURRENT_BINARY_DIR}/bung>")
+include_directories("sing$<1:/ting>")
diff --git a/Tests/IncludeDirectories/TargetIncludeDirectories/main.cpp b/Tests/IncludeDirectories/TargetIncludeDirectories/main.cpp
index 8aa3532..63217f4 100644
--- a/Tests/IncludeDirectories/TargetIncludeDirectories/main.cpp
+++ b/Tests/IncludeDirectories/TargetIncludeDirectories/main.cpp
@@ -3,6 +3,10 @@
#include "bat.h"
#include "foo.h"
#include "baz.h"
+#include "bang.h"
+#include "bing.h"
+#include "bung.h"
+#include "ting.h"
int main(int, char**)
{
diff --git a/Tests/IncludeDirectories/TargetIncludeDirectories/sing/ting/ting.h b/Tests/IncludeDirectories/TargetIncludeDirectories/sing/ting/ting.h
new file mode 100644
index 0000000..4fe01dd
--- /dev/null
+++ b/Tests/IncludeDirectories/TargetIncludeDirectories/sing/ting/ting.h
@@ -0,0 +1 @@
+//ting.h
diff --git a/Tests/PDBDirectoryAndName/CMakeLists.txt b/Tests/PDBDirectoryAndName/CMakeLists.txt
new file mode 100644
index 0000000..bc2f013
--- /dev/null
+++ b/Tests/PDBDirectoryAndName/CMakeLists.txt
@@ -0,0 +1,79 @@
+cmake_minimum_required(VERSION 2.8)
+project(PDBDirectoryAndName C)
+
+# Make sure the proper compiler is in use.
+if(NOT MSVC AND NOT "${CMAKE_C_COMPILER_ID}" MATCHES "^(Intel)$")
+ message(FATAL_ERROR "The PDBDirectoryAndName test works only with MSVC or Intel")
+endif()
+
+set(my_targets "")
+
+add_library(mylibA SHARED mylibA.c)
+set_target_properties(mylibA PROPERTIES
+ PDB_NAME "mylibA_Special"
+ PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mylibA_PDB"
+)
+list(APPEND my_targets mylibA)
+
+add_library(mylibB STATIC mylibB.c)
+set_target_properties(mylibB PROPERTIES
+ PDB_NAME "mylibB_Special"
+ PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/mylibB_PDB"
+)
+list(APPEND my_targets mylibB)
+
+add_library(mylibC SHARED mylibC.c)
+set_target_properties(mylibC PROPERTIES
+ PDB_NAME "mylibC_Special"
+)
+list(APPEND my_targets mylibC)
+
+add_library(mylibD STATIC mylibD.c)
+set_target_properties(mylibD PROPERTIES
+ PDB_NAME "mylibD_Special"
+)
+list(APPEND my_targets mylibD)
+
+add_executable(myexe myexe.c)
+set_target_properties(myexe PROPERTIES
+ PDB_NAME "myexe_Special"
+ PDB_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/myexe_PDB"
+)
+list(APPEND my_targets myexe)
+
+target_link_libraries(myexe mylibA mylibB mylibC mylibD)
+
+add_executable(myexe2 myexe2.c)
+set_target_properties(myexe2 PROPERTIES
+ PDB_NAME "myexe2_Special"
+)
+list(APPEND my_targets myexe2)
+
+target_link_libraries(myexe2 mylibA mylibD)
+
+#-----------------------------------------------------------------------------
+# Check that PDB files actually appear where expected.
+
+# The PDB_NAME and PDB_OUTPUT_DIRECTORY options do not work in VS 6.
+if("${CMAKE_GENERATOR}" MATCHES "Visual Studio 6")
+ return()
+endif()
+# PDB output not fully implemented for Intel
+if("${CMAKE_C_COMPILER_ID}" MATCHES "^(Intel)$")
+ return()
+endif()
+
+set(pdbs "")
+foreach(t ${my_targets})
+ get_property(pdb_name TARGET ${t} PROPERTY PDB_NAME)
+ get_property(pdb_dir TARGET ${t} PROPERTY PDB_OUTPUT_DIRECTORY)
+ if(NOT pdb_dir)
+ set(pdb_dir ${CMAKE_CURRENT_BINARY_DIR})
+ endif()
+ list(APPEND pdbs ${pdb_dir}/${CMAKE_CFG_INTDIR}/${pdb_name}.pdb)
+endforeach()
+add_custom_target(check_pdbs ALL VERBATIM
+ COMMAND ${CMAKE_COMMAND} -Dconfig=$<CONFIGURATION> "-Dpdbs=${pdbs}"
+ -P ${CMAKE_CURRENT_SOURCE_DIR}/check_pdbs.cmake
+ )
+add_dependencies(check_pdbs ${my_targets})
diff --git a/Tests/PDBDirectoryAndName/check_pdbs.cmake b/Tests/PDBDirectoryAndName/check_pdbs.cmake
new file mode 100644
index 0000000..89cdb3c
--- /dev/null
+++ b/Tests/PDBDirectoryAndName/check_pdbs.cmake
@@ -0,0 +1,10 @@
+if(NOT "${config}" MATCHES "[Dd][Ee][Bb]")
+ return()
+endif()
+foreach(pdb ${pdbs})
+ if(EXISTS "${pdb}")
+ message(STATUS "PDB Exists: ${pdb}")
+ else()
+ message(SEND_ERROR "PDB MISSING: ${pdb}")
+ endif()
+endforeach()
diff --git a/Tests/PDBDirectoryAndName/myexe.c b/Tests/PDBDirectoryAndName/myexe.c
new file mode 100644
index 0000000..c6d9065
--- /dev/null
+++ b/Tests/PDBDirectoryAndName/myexe.c
@@ -0,0 +1,5 @@
+extern int mylibA();
+extern int mylibB();
+extern int mylibC();
+extern int mylibD();
+int main() { return mylibA() + mylibB() + mylibC() + mylibD(); }
diff --git a/Tests/PDBDirectoryAndName/myexe2.c b/Tests/PDBDirectoryAndName/myexe2.c
new file mode 100644
index 0000000..75b39cd
--- /dev/null
+++ b/Tests/PDBDirectoryAndName/myexe2.c
@@ -0,0 +1,3 @@
+extern int mylibA();
+extern int mylibD();
+int main() { return mylibA() + mylibD(); }
diff --git a/Tests/PDBDirectoryAndName/mylibA.c b/Tests/PDBDirectoryAndName/mylibA.c
new file mode 100644
index 0000000..f4c553f
--- /dev/null
+++ b/Tests/PDBDirectoryAndName/mylibA.c
@@ -0,0 +1 @@
+__declspec(dllexport) int mylibA() { return 1; }
diff --git a/Tests/PDBDirectoryAndName/mylibB.c b/Tests/PDBDirectoryAndName/mylibB.c
new file mode 100644
index 0000000..2040c67
--- /dev/null
+++ b/Tests/PDBDirectoryAndName/mylibB.c
@@ -0,0 +1 @@
+int mylibB() { return -1; }
diff --git a/Tests/PDBDirectoryAndName/mylibC.c b/Tests/PDBDirectoryAndName/mylibC.c
new file mode 100644
index 0000000..adf7c70
--- /dev/null
+++ b/Tests/PDBDirectoryAndName/mylibC.c
@@ -0,0 +1 @@
+__declspec(dllexport) int mylibC() { return 1; }
diff --git a/Tests/PDBDirectoryAndName/mylibD.c b/Tests/PDBDirectoryAndName/mylibD.c
new file mode 100644
index 0000000..efa8a82
--- /dev/null
+++ b/Tests/PDBDirectoryAndName/mylibD.c
@@ -0,0 +1 @@
+int mylibD() { return -1; }
diff --git a/Tests/RunCMake/CMakeLists.txt b/Tests/RunCMake/CMakeLists.txt
index 3ea54f1..2fa7141 100644
--- a/Tests/RunCMake/CMakeLists.txt
+++ b/Tests/RunCMake/CMakeLists.txt
@@ -46,6 +46,7 @@ macro(add_RunCMake_test test)
endmacro()
add_RunCMake_test(GeneratorExpression)
+add_RunCMake_test(TargetPropertyGeneratorExpressions)
add_RunCMake_test(Languages)
add_RunCMake_test(ObjectLibrary)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1-stderr.txt
new file mode 100644
index 0000000..791c4a9
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1-stderr.txt
@@ -0,0 +1,6 @@
+CMake Error:
+ Error evaluating generator expression:
+
+ \$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>
+
+ Self reference on target "TargetPropertyGeneratorExpressions".$
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1.cmake
new file mode 100644
index 0000000..a85731e
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference1.cmake
@@ -0,0 +1,7 @@
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
+ "int main(int, char **) { return 0; }\n")
+
+add_executable(TargetPropertyGeneratorExpressions
+ "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
+include_directories("$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>")
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2-stderr.txt
new file mode 100644
index 0000000..791c4a9
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2-stderr.txt
@@ -0,0 +1,6 @@
+CMake Error:
+ Error evaluating generator expression:
+
+ \$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>
+
+ Self reference on target "TargetPropertyGeneratorExpressions".$
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2.cmake
new file mode 100644
index 0000000..f1459b8
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference2.cmake
@@ -0,0 +1,9 @@
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
+ "int main(int, char **) { return 0; }\n")
+
+add_executable(TargetPropertyGeneratorExpressions
+ "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
+set_property(TARGET TargetPropertyGeneratorExpressions PROPERTY
+ INCLUDE_DIRECTORIES "$<TARGET_PROPERTY:INCLUDE_DIRECTORIES>"
+)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3-stderr.txt
new file mode 100644
index 0000000..f60d726
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3-stderr.txt
@@ -0,0 +1,6 @@
+CMake Error:
+ Error evaluating generator expression:
+
+ \$<TARGET_PROPERTY:TargetPropertyGeneratorExpressions,INCLUDE_DIRECTORIES>
+
+ Self reference on target "TargetPropertyGeneratorExpressions".$
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3.cmake
new file mode 100644
index 0000000..433b730
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference3.cmake
@@ -0,0 +1,8 @@
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
+ "int main(int, char **) { return 0; }\n")
+
+add_executable(TargetPropertyGeneratorExpressions
+ "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
+include_directories(
+ "$<TARGET_PROPERTY:TargetPropertyGeneratorExpressions,INCLUDE_DIRECTORIES>")
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4-stderr.txt
new file mode 100644
index 0000000..f60d726
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4-stderr.txt
@@ -0,0 +1,6 @@
+CMake Error:
+ Error evaluating generator expression:
+
+ \$<TARGET_PROPERTY:TargetPropertyGeneratorExpressions,INCLUDE_DIRECTORIES>
+
+ Self reference on target "TargetPropertyGeneratorExpressions".$
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4.cmake
new file mode 100644
index 0000000..4b64459
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference4.cmake
@@ -0,0 +1,10 @@
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
+ "int main(int, char **) { return 0; }\n")
+
+add_executable(TargetPropertyGeneratorExpressions
+ "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
+set_property(TARGET TargetPropertyGeneratorExpressions PROPERTY
+INCLUDE_DIRECTORIES
+ "$<TARGET_PROPERTY:TargetPropertyGeneratorExpressions,INCLUDE_DIRECTORIES>"
+)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5-stderr.txt
new file mode 100644
index 0000000..2b22d0f
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5-stderr.txt
@@ -0,0 +1,6 @@
+CMake Error:
+ Error evaluating generator expression:
+
+ \$<TARGET_PROPERTY:COMPILE_DEFINITIONS>
+
+ Self reference on target "TargetPropertyGeneratorExpressions".$
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5.cmake
new file mode 100644
index 0000000..74fff67
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference5.cmake
@@ -0,0 +1,10 @@
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
+ "int main(int, char **) { return 0; }\n")
+
+add_executable(TargetPropertyGeneratorExpressions
+ "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
+set_property(TARGET TargetPropertyGeneratorExpressions
+PROPERTY
+ COMPILE_DEFINITIONS "$<TARGET_PROPERTY:COMPILE_DEFINITIONS>"
+)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6-result.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6-result.txt
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6-result.txt
@@ -0,0 +1 @@
+1
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6-stderr.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6-stderr.txt
new file mode 100644
index 0000000..fe7caa3
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6-stderr.txt
@@ -0,0 +1,6 @@
+CMake Error:
+ Error evaluating generator expression:
+
+ \$<TARGET_PROPERTY:TargetPropertyGeneratorExpressions,COMPILE_DEFINITIONS>
+
+ Self reference on target "TargetPropertyGeneratorExpressions".$
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6.cmake
new file mode 100644
index 0000000..d6650d3
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/BadSelfReference6.cmake
@@ -0,0 +1,10 @@
+
+file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/main.cpp"
+ "int main(int, char **) { return 0; }\n")
+
+add_executable(TargetPropertyGeneratorExpressions
+ "${CMAKE_CURRENT_BINARY_DIR}/main.cpp")
+set_property(TARGET TargetPropertyGeneratorExpressions PROPERTY
+COMPILE_DEFINITIONS
+ "$<TARGET_PROPERTY:TargetPropertyGeneratorExpressions,COMPILE_DEFINITIONS>"
+)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/CMakeLists.txt b/Tests/RunCMake/TargetPropertyGeneratorExpressions/CMakeLists.txt
new file mode 100644
index 0000000..22577da
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/CMakeLists.txt
@@ -0,0 +1,8 @@
+
+cmake_minimum_required(VERSION 2.8)
+project(${RunCMake_TEST} CXX)
+
+# MSVC creates extra targets which pollute the stderr unless we set this.
+set(CMAKE_SUPPRESS_REGENERATION TRUE)
+
+include(${RunCMake_TEST}.cmake)
diff --git a/Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake b/Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake
new file mode 100644
index 0000000..f2ff05b
--- /dev/null
+++ b/Tests/RunCMake/TargetPropertyGeneratorExpressions/RunCMakeTest.cmake
@@ -0,0 +1,8 @@
+include(RunCMake)
+
+run_cmake(BadSelfReference1)
+run_cmake(BadSelfReference2)
+run_cmake(BadSelfReference3)
+run_cmake(BadSelfReference4)
+run_cmake(BadSelfReference5)
+run_cmake(BadSelfReference6)
diff --git a/bootstrap b/bootstrap
index ceddfdc..713f01f 100755
--- a/bootstrap
+++ b/bootstrap
@@ -199,9 +199,12 @@ CMAKE_CXX_SOURCES="\
cmMakefile \
cmExportFileGenerator \
cmExportInstallFileGenerator \
+ cmExportSet \
+ cmExportSetMap \
cmInstallDirectoryGenerator \
cmGeneratedFileStream \
cmGeneratorTarget \
+ cmGeneratorExpressionDAGChecker \
cmGeneratorExpressionEvaluator \
cmGeneratorExpressionLexer \
cmGeneratorExpressionParser \