summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/CMakeLists.txt12
-rw-r--r--Source/CMakeVersion.cmake2
-rw-r--r--Source/CPack/cmCPackDebGenerator.cxx15
-rw-r--r--Source/CTest/cmCTestCoverageHandler.cxx30
-rw-r--r--Source/CTest/cmCTestMemCheckHandler.cxx2
-rw-r--r--Source/CTest/cmCTestRunTest.cxx2
-rw-r--r--Source/CTest/cmCTestScriptHandler.cxx6
-rw-r--r--Source/cmCTest.cxx23
-rw-r--r--Source/cmCoreTryCompile.cxx1
-rw-r--r--Source/cmDocumentationFormatterHTML.cxx10
-rw-r--r--Source/cmExtraCodeBlocksGenerator.cxx46
-rw-r--r--Source/cmExtraCodeBlocksGenerator.h2
-rw-r--r--Source/cmFileCommand.cxx2
-rw-r--r--Source/cmFindPackageCommand.cxx29
-rw-r--r--Source/cmGlobalGenerator.cxx15
-rw-r--r--Source/cmGlobalGenerator.h3
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx66
-rw-r--r--Source/cmGlobalVisualStudio10Generator.h18
-rw-r--r--Source/cmGlobalVisualStudio71Generator.cxx14
-rw-r--r--Source/cmGlobalVisualStudio71Generator.h4
-rw-r--r--Source/cmGlobalVisualStudio7Generator.cxx28
-rw-r--r--Source/cmGlobalVisualStudio7Generator.h4
-rw-r--r--Source/cmGlobalVisualStudio8Generator.cxx25
-rw-r--r--Source/cmGlobalVisualStudio8Generator.h3
-rw-r--r--Source/cmIncludeExternalMSProjectCommand.cxx67
-rw-r--r--Source/cmIncludeExternalMSProjectCommand.h12
-rw-r--r--Source/cmListCommand.cxx15
-rw-r--r--Source/cmLocalVisualStudio10Generator.cxx8
-rw-r--r--Source/cmLocalVisualStudio6Generator.cxx2
-rw-r--r--Source/cmMakefile.cxx50
-rw-r--r--Source/cmMakefile.h30
-rw-r--r--Source/cmNinjaNormalTargetGenerator.cxx33
-rw-r--r--Source/cmNinjaNormalTargetGenerator.h3
-rw-r--r--Source/cmSystemTools.cxx52
-rw-r--r--Source/cmSystemTools.h12
-rw-r--r--Source/cmTargetLinkLibrariesCommand.h3
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx144
-rw-r--r--Source/cmVisualStudio10TargetGenerator.h16
-rw-r--r--Source/kwsys/CMakeLists.txt16
-rw-r--r--Source/kwsys/DateStamp.h.in42
-rw-r--r--Source/kwsys/SystemTools.cxx236
-rw-r--r--Source/kwsys/SystemTools.hxx.in6
-rw-r--r--Source/kwsys/kwsysDateStamp.cmake21
-rwxr-xr-xSource/kwsys/kwsysDateStamp.py54
-rw-r--r--Source/kwsys/kwsysPlatformTestsCXX.cxx26
-rw-r--r--Source/kwsys/testSystemTools.cxx54
46 files changed, 862 insertions, 402 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt
index f9d1c03..c01c490 100644
--- a/Source/CMakeLists.txt
+++ b/Source/CMakeLists.txt
@@ -355,18 +355,18 @@ IF (WIN32)
ENDIF(NOT UNIX)
ENDIF (WIN32)
-# turn on Ninja by default
+# Turn on Ninja by default, but disable it
+# on platforms where it does not pass all tests.
+# Enforce Ninja support by setting CMAKE_USE_NINJA
set(_CMAKE_DEFAULT_NINJA_VALUE TRUE)
-# turn it off for platforms where it does not pass all the
-# tests
if(WIN32 OR APPLE)
SET(_CMAKE_DEFAULT_NINJA_VALUE FALSE)
endif()
SET(CMAKE_ENABLE_NINJA ${_CMAKE_DEFAULT_NINJA_VALUE} CACHE BOOL
- "Enable the ninja generator for CMake. currently not fully working for Windows or OSX")
+ "Enable the ninja generator for CMake. On Windows and OSX broken")
MARK_AS_ADVANCED(CMAKE_ENABLE_NINJA)
IF(CMAKE_ENABLE_NINJA)
- MESSAGE(STATUS "Enable ninja generator.")
+ MESSAGE(STATUS "Ninja generator enabled.")
SET(SRCS ${SRCS}
cmGlobalNinjaGenerator.cxx
cmGlobalNinjaGenerator.h
@@ -382,7 +382,7 @@ IF(CMAKE_ENABLE_NINJA)
)
ADD_DEFINITIONS(-DCMAKE_USE_NINJA)
ELSE()
- MESSAGE(STATUS "Disable ninja generator.")
+ MESSAGE(STATUS "Ninja generator disabled, enforce with -DCMAKE_ENABLE_NINJA=ON")
ENDIF()
# create a library used by the command line and the GUI
diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake
index 13268bb..0908537 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 8)
-SET(CMake_VERSION_TWEAK 20120422)
+SET(CMake_VERSION_TWEAK 20120501)
#SET(CMake_VERSION_RC 1)
diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx
index 178a18d..fa456de 100644
--- a/Source/CPack/cmCPackDebGenerator.cxx
+++ b/Source/CPack/cmCPackDebGenerator.cxx
@@ -480,11 +480,16 @@ int cmCPackDebGenerator::createDeb()
// Do not end the md5sum file with yet another (invalid)
}
- cmd = "\"";
- cmd += cmakeExecutable;
- cmd += "\" -E tar cfz control.tar.gz ./control ./md5sums";
- const char* controlExtra =
- this->GetOption("CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA");
+ cmd = "";
+ if (NULL != this->GetOption("CPACK_DEBIAN_FAKEROOT_EXECUTABLE"))
+ {
+ cmd = this->GetOption("CPACK_DEBIAN_FAKEROOT_EXECUTABLE");
+ }
+ cmd += " \"";
+ cmd += cmakeExecutable;
+ cmd += "\" -E tar cfz control.tar.gz ./control ./md5sums";
+ const char* controlExtra =
+ this->GetOption("CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA");
if( controlExtra )
{
std::vector<std::string> controlExtraList;
diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx
index 309abb1..ae06b0f 100644
--- a/Source/CTest/cmCTestCoverageHandler.cxx
+++ b/Source/CTest/cmCTestCoverageHandler.cxx
@@ -752,6 +752,33 @@ int cmCTestCoverageHandler::HandlePHPCoverage(
return static_cast<int>(cont->TotalCoverage.size());
}
+struct cmCTestCoverageHandlerLocale
+{
+ cmCTestCoverageHandlerLocale()
+ {
+ if(const char* l = cmSystemTools::GetEnv("LC_ALL"))
+ {
+ lc_all = l;
+ }
+ if(lc_all != "C")
+ {
+ cmSystemTools::PutEnv("LC_ALL=C");
+ }
+ }
+ ~cmCTestCoverageHandlerLocale()
+ {
+ if(!lc_all.empty())
+ {
+ cmSystemTools::PutEnv(("LC_ALL=" + lc_all).c_str());
+ }
+ else
+ {
+ cmSystemTools::UnsetEnv("LC_ALL");
+ }
+ }
+ std::string lc_all;
+};
+
//----------------------------------------------------------------------
int cmCTestCoverageHandler::HandleGCovCoverage(
cmCTestCoverageHandlerContainer* cont)
@@ -815,7 +842,8 @@ int cmCTestCoverageHandler::HandleGCovCoverage(
int file_count = 0;
// make sure output from gcov is in English!
- cmSystemTools::PutEnv("LC_ALL=POSIX");
+ cmCTestCoverageHandlerLocale locale_C;
+ static_cast<void>(locale_C);
// files is a list of *.da and *.gcda files with coverage data in them.
// These are binary files that you give as input to gcov so that it will
diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx
index 035aaa9..3e4ecdd 100644
--- a/Source/CTest/cmCTestMemCheckHandler.cxx
+++ b/Source/CTest/cmCTestMemCheckHandler.cxx
@@ -358,7 +358,7 @@ void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os)
os
<< "\t\t</Results>\n"
- << logTag << memcheckstr << std::endl
+ << logTag << cmXMLSafe(memcheckstr) << std::endl
<< "\t</Log>\n";
this->WriteTestResultFooter(os, result);
if ( current < cc )
diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx
index 81f18b0..c3de5dc 100644
--- a/Source/CTest/cmCTestRunTest.cxx
+++ b/Source/CTest/cmCTestRunTest.cxx
@@ -671,7 +671,7 @@ bool cmCTestRunTest::ForkProcess(double testTimeOut, bool explicitTimeout,
if (environment && environment->size()>0)
{
- cmSystemTools::AppendEnv(environment);
+ cmSystemTools::AppendEnv(*environment);
}
return this->TestProcess->StartProcess();
diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx
index 5841b8d..d3ab2ef 100644
--- a/Source/CTest/cmCTestScriptHandler.cxx
+++ b/Source/CTest/cmCTestScriptHandler.cxx
@@ -643,11 +643,7 @@ int cmCTestScriptHandler::RunCurrentScript()
{
std::vector<std::string> envArgs;
cmSystemTools::ExpandListArgument(this->CTestEnv.c_str(),envArgs);
- // for each variable/argument do a putenv
- for (unsigned i = 0; i < envArgs.size(); ++i)
- {
- cmSystemTools::PutEnv(envArgs[i].c_str());
- }
+ cmSystemTools::AppendEnv(envArgs);
}
// now that we have done most of the error checking finally run the
diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx
index 3f7fdc7..4aff64b 100644
--- a/Source/cmCTest.cxx
+++ b/Source/cmCTest.cxx
@@ -48,7 +48,7 @@
#include <float.h>
#include <ctype.h>
-#include <memory> // auto_ptr
+#include <cmsys/auto_ptr.hxx>
#include <cm_zlib.h>
#include <cmsys/Base64.h>
@@ -509,7 +509,7 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command)
cmake cm;
cmGlobalGenerator gg;
gg.SetCMakeInstance(&cm);
- std::auto_ptr<cmLocalGenerator> lg(gg.CreateLocalGenerator());
+ cmsys::auto_ptr<cmLocalGenerator> lg(gg.CreateLocalGenerator());
cmMakefile *mf = lg->GetMakefile();
if ( !this->ReadCustomConfigurationFileTree(this->BinaryDir.c_str(), mf) )
{
@@ -1277,7 +1277,6 @@ int cmCTest::RunTest(std::vector<const char*> argv,
std::ostream* log, double testTimeOut,
std::vector<std::string>* environment)
{
- std::vector<std::string> origEnv;
bool modifyEnv = (environment && environment->size()>0);
// determine how much time we have
@@ -1334,9 +1333,11 @@ int cmCTest::RunTest(std::vector<const char*> argv,
}
std::string oldpath = cmSystemTools::GetCurrentWorkingDirectory();
+ cmsys::auto_ptr<cmSystemTools::SaveRestoreEnvironment> saveEnv;
if (modifyEnv)
{
- origEnv = cmSystemTools::AppendEnv(environment);
+ saveEnv.reset(new cmSystemTools::SaveRestoreEnvironment);
+ cmSystemTools::AppendEnv(*environment);
}
*retVal = inst.Run(args, output);
@@ -1351,11 +1352,6 @@ int cmCTest::RunTest(std::vector<const char*> argv,
"Internal cmCTest object used to run test." << std::endl
<< *output << std::endl);
- if (modifyEnv)
- {
- cmSystemTools::RestoreEnv(origEnv);
- }
-
return cmsysProcess_State_Exited;
}
std::vector<char> tempOutput;
@@ -1364,9 +1360,11 @@ int cmCTest::RunTest(std::vector<const char*> argv,
*output = "";
}
+ cmsys::auto_ptr<cmSystemTools::SaveRestoreEnvironment> saveEnv;
if (modifyEnv)
{
- origEnv = cmSystemTools::AppendEnv(environment);
+ saveEnv.reset(new cmSystemTools::SaveRestoreEnvironment);
+ cmSystemTools::AppendEnv(*environment);
}
cmsysProcess* cp = cmsysProcess_New();
@@ -1436,11 +1434,6 @@ int cmCTest::RunTest(std::vector<const char*> argv,
}
cmsysProcess_Delete(cp);
- if (modifyEnv)
- {
- cmSystemTools::RestoreEnv(origEnv);
- }
-
return result;
}
diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx
index 48f644b..ed485e3 100644
--- a/Source/cmCoreTryCompile.cxx
+++ b/Source/cmCoreTryCompile.cxx
@@ -404,6 +404,7 @@ void cmCoreTryCompile::CleanupFiles(const char* binDir)
if(cmSystemTools::FileIsDirectory(fullPath.c_str()))
{
this->CleanupFiles(fullPath.c_str());
+ cmSystemTools::RemoveADirectory(fullPath.c_str());
}
else
{
diff --git a/Source/cmDocumentationFormatterHTML.cxx b/Source/cmDocumentationFormatterHTML.cxx
index 6ced1e4..ed28b45 100644
--- a/Source/cmDocumentationFormatterHTML.cxx
+++ b/Source/cmDocumentationFormatterHTML.cxx
@@ -127,7 +127,7 @@ void cmDocumentationFormatterHTML
{
os << "<h2><a name=\"section_";
cmDocumentationPrintHTMLId(os, name);
- os << "\"/>" << name << "</h2>\n";
+ os << "\"></a>" << name << "</h2>\n";
}
// Is a list needed?
@@ -167,9 +167,9 @@ void cmDocumentationFormatterHTML
{
os << " <a name=\"" << prefix << ":";
cmDocumentationPrintHTMLId(os, op->Name.c_str());
- os << "\"><b><code>";
+ os << "\"></a><b><code>";
this->PrintHTMLEscapes(os, op->Name.c_str());
- os << "</code></b></a>: ";
+ os << "</code></b>: ";
}
this->PrintHTMLEscapes(os, op->Brief.c_str());
if(op->Full.size())
@@ -269,9 +269,9 @@ void cmDocumentationFormatterHTML
return;
}
- os << "<h2><a name=\"section_Index\">Master Index "
+ os << "<h2><a name=\"section_Index\"></a>Master Index "
<< "CMake " << cmVersion::GetCMakeVersion()
- << "</a></h2>\n";
+ << "</h2>\n";
if (!sections.empty())
{
diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx
index ccb17f0..5df8627 100644
--- a/Source/cmExtraCodeBlocksGenerator.cxx
+++ b/Source/cmExtraCodeBlocksGenerator.cxx
@@ -60,6 +60,9 @@ cmExtraCodeBlocksGenerator::cmExtraCodeBlocksGenerator()
// disable until somebody actually tests it:
// this->SupportedGlobalGenerators.push_back("MSYS Makefiles");
#endif
+#ifdef CMAKE_USE_NINJA
+ this->SupportedGlobalGenerators.push_back("Ninja");
+#endif
this->SupportedGlobalGenerators.push_back("Unix Makefiles");
}
@@ -383,6 +386,7 @@ void cmExtraCodeBlocksGenerator
case cmTarget::STATIC_LIBRARY:
case cmTarget::SHARED_LIBRARY:
case cmTarget::MODULE_LIBRARY:
+ case cmTarget::OBJECT_LIBRARY:
{
this->AppendTarget(fout, ti->first.c_str(), &ti->second,
make.c_str(), makefile, compiler.c_str());
@@ -420,6 +424,7 @@ void cmExtraCodeBlocksGenerator
case cmTarget::STATIC_LIBRARY:
case cmTarget::SHARED_LIBRARY:
case cmTarget::MODULE_LIBRARY:
+ case cmTarget::OBJECT_LIBRARY:
case cmTarget::UTILITY: // can have sources since 2.6.3
{
const std::vector<cmSourceFile*>&sources=ti->second.GetSourceFiles();
@@ -532,6 +537,31 @@ void cmExtraCodeBlocksGenerator
}
+// Write a dummy file for OBJECT libraries, so C::B can reference some file
+std::string cmExtraCodeBlocksGenerator::CreateDummyTargetFile(
+ cmMakefile* mf, cmTarget* target) const
+{
+ // this file doesn't seem to be used by C::B in custom makefile mode,
+ // but we generate a unique file for each OBJECT library so in case
+ // C::B uses it in some way, the targets don't interfere with each other.
+ std::string filename = mf->GetCurrentOutputDirectory();
+ filename += "/";
+ filename += mf->GetLocalGenerator()->GetTargetDirectory(*target);
+ filename += "/";
+ filename += target->GetName();
+ filename += ".objlib";
+ cmGeneratedFileStream fout(filename.c_str());
+ if(fout)
+ {
+ fout << "# This is a dummy file for the OBJECT library "
+ << target->GetName()
+ << " for the CMake CodeBlocks project generator.\n"
+ << "# Don't edit, this file will be overwritten.\n";
+ }
+ return filename;
+}
+
+
// Generate the xml code for one target.
void cmExtraCodeBlocksGenerator::AppendTarget(cmGeneratedFileStream& fout,
const char* targetName,
@@ -570,7 +600,18 @@ void cmExtraCodeBlocksGenerator::AppendTarget(cmGeneratedFileStream& fout,
}
const char* buildType = makefile->GetDefinition("CMAKE_BUILD_TYPE");
- fout<<" <Option output=\"" << target->GetLocation(buildType)
+ std::string location;
+ if ( target->GetType()==cmTarget::OBJECT_LIBRARY)
+ {
+ location = this->CreateDummyTargetFile(const_cast<cmMakefile*>(makefile),
+ target);
+ }
+ else
+ {
+ location = target->GetLocation(buildType);
+ }
+
+ fout<<" <Option output=\"" << location
<< "\" prefix_auto=\"0\" extension_auto=\"0\" />\n"
" <Option working_dir=\"" << workingDir << "\" />\n"
" <Option object_output=\"./\" />\n"
@@ -728,7 +769,8 @@ int cmExtraCodeBlocksGenerator::GetCBTargetType(cmTarget* target)
return 1;
}
}
- else if ( target->GetType()==cmTarget::STATIC_LIBRARY)
+ else if (( target->GetType()==cmTarget::STATIC_LIBRARY)
+ || (target->GetType()==cmTarget::OBJECT_LIBRARY))
{
return 2;
}
diff --git a/Source/cmExtraCodeBlocksGenerator.h b/Source/cmExtraCodeBlocksGenerator.h
index 57751fc..e0a64ca 100644
--- a/Source/cmExtraCodeBlocksGenerator.h
+++ b/Source/cmExtraCodeBlocksGenerator.h
@@ -44,6 +44,8 @@ private:
void CreateNewProjectFile(const std::vector<cmLocalGenerator*>& lgs,
const std::string& filename);
+ std::string CreateDummyTargetFile(cmMakefile* mf, cmTarget* target) const;
+
std::string GetCBCompilerId(const cmMakefile* mf);
int GetCBTargetType(cmTarget* target);
std::string BuildMakeCommand(const std::string& make, const char* makefile,
diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx
index 3f14fa1..d69431e 100644
--- a/Source/cmFileCommand.cxx
+++ b/Source/cmFileCommand.cxx
@@ -300,7 +300,7 @@ bool cmFileCommand::HandleReadCommand(std::vector<std::string> const& args)
offset = atoi(offsetArg.GetCString());
}
- file.seekg(offset);
+ file.seekg(offset, std::ios::beg); // explicit ios::beg for IBM VisualAge 6
std::string output;
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx
index ef16ce8..4f9ba7e 100644
--- a/Source/cmFindPackageCommand.cxx
+++ b/Source/cmFindPackageCommand.cxx
@@ -89,7 +89,7 @@ void cmFindPackageCommand::GenerateDocumentation()
"FIND_XXX", "find_package");
this->CommandDocumentation =
" find_package(<package> [version] [EXACT] [QUIET] [MODULE]\n"
- " [[REQUIRED|COMPONENTS] [components...]]\n"
+ " [REQUIRED] [[COMPONENTS] [components...]]\n"
" [OPTIONAL_COMPONENTS components...]\n"
" [NO_POLICY_SCOPE])\n"
"Finds and loads settings from an external project. "
@@ -102,7 +102,7 @@ void cmFindPackageCommand::GenerateDocumentation()
"package cannot be found."
"\n"
"A package-specific list of required components may be listed after the "
- "COMPONENTS option or directly after the REQUIRED option. "
+ "COMPONENTS option (or after the REQUIRED option if present). "
"Additional optional components may be listed after OPTIONAL_COMPONENTS. "
"Available components and their influence on whether a package is "
"considered to be found are defined by the target package."
@@ -136,7 +136,7 @@ void cmFindPackageCommand::GenerateDocumentation()
"proceeds to Config mode.\n"
"The complete Config mode command signature is:\n"
" find_package(<package> [version] [EXACT] [QUIET]\n"
- " [[REQUIRED|COMPONENTS] [components...]]\n"
+ " [REQUIRED] [[COMPONENTS] [components...]]\n"
" [CONFIG|NO_MODULE]\n"
" [NO_POLICY_SCOPE]\n"
" [NAMES name1 [name2 ...]]\n"
@@ -353,6 +353,29 @@ void cmFindPackageCommand::GenerateDocumentation()
"variable CMAKE_DISABLE_FIND_PACKAGE_<package> to TRUE. See the "
"documentation for the CMAKE_DISABLE_FIND_PACKAGE_<package> variable for "
"more information.\n"
+ "When loading a find module or package configuration file find_package "
+ "defines variables to provide information about the call arguments "
+ "(and restores their original state before returning):\n"
+ " <package>_FIND_REQUIRED = true if REQUIRED option was given\n"
+ " <package>_FIND_QUIETLY = true if QUIET option was given\n"
+ " <package>_FIND_VERSION = full requested version string\n"
+ " <package>_FIND_VERSION_MAJOR = major version if requested, else 0\n"
+ " <package>_FIND_VERSION_MINOR = minor version if requested, else 0\n"
+ " <package>_FIND_VERSION_PATCH = patch version if requested, else 0\n"
+ " <package>_FIND_VERSION_TWEAK = tweak version if requested, else 0\n"
+ " <package>_FIND_VERSION_COUNT = number of version components, 0 to 4\n"
+ " <package>_FIND_VERSION_EXACT = true if EXACT option was given\n"
+ " <package>_FIND_COMPONENTS = list of requested components\n"
+ " <package>_FIND_REQUIRED_<c> = true if component <c> is required\n"
+ " false if component <c> is optional\n"
+ "In Module mode the loaded find module is responsible to honor the "
+ "request detailed by these variables; see the find module for details. "
+ "In Config mode find_package handles REQUIRED, QUIET, and version "
+ "options automatically but leaves it to the package configuration file "
+ "to handle components in a way that makes sense for the package. "
+ "The package configuration file may set <package>_FOUND to false "
+ "to tell find_package that component requirements are not satisfied."
+ "\n"
"See the cmake_policy() command documentation for discussion of the "
"NO_POLICY_SCOPE option."
;
diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx
index 545f9e8..b06cdb4 100644
--- a/Source/cmGlobalGenerator.cxx
+++ b/Source/cmGlobalGenerator.cxx
@@ -2092,6 +2092,21 @@ cmTarget cmGlobalGenerator::CreateGlobalTarget(
}
//----------------------------------------------------------------------------
+std::string
+cmGlobalGenerator::GenerateRuleFile(std::string const& output) const
+{
+ std::string ruleFile = output;
+ ruleFile += ".rule";
+ const char* dir = this->GetCMakeCFGIntDir();
+ if(dir && dir[0] == '$')
+ {
+ cmSystemTools::ReplaceString(ruleFile, dir,
+ cmake::GetCMakeFilesDirectory());
+ }
+ return ruleFile;
+}
+
+//----------------------------------------------------------------------------
void cmGlobalGenerator::AppendDirectoryForConfig(const char*, const char*,
const char*, std::string&)
{
diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h
index 80b948b..5254b89 100644
--- a/Source/cmGlobalGenerator.h
+++ b/Source/cmGlobalGenerator.h
@@ -277,6 +277,9 @@ public:
i.e. "Can I build Debug and Release in the same tree?" */
virtual bool IsMultiConfig() { return false; }
+ /** Generate an <output>.rule file path for a given command output. */
+ virtual std::string GenerateRuleFile(std::string const& output) const;
+
protected:
typedef std::vector<cmLocalGenerator*> GeneratorVector;
// for a project collect all its targets by following depend
diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx
index 22ead10..18a786d 100644
--- a/Source/cmGlobalVisualStudio10Generator.cxx
+++ b/Source/cmGlobalVisualStudio10Generator.cxx
@@ -13,6 +13,7 @@
#include "cmGlobalVisualStudio10Generator.h"
#include "cmLocalVisualStudio10Generator.h"
#include "cmMakefile.h"
+#include "cmSourceFile.h"
#include "cmake.h"
@@ -51,6 +52,38 @@ cmLocalGenerator *cmGlobalVisualStudio10Generator::CreateLocalGenerator()
}
//----------------------------------------------------------------------------
+void cmGlobalVisualStudio10Generator::Generate()
+{
+ this->LongestSource = LongestSourcePath();
+ this->cmGlobalVisualStudio8Generator::Generate();
+ if(this->LongestSource.Length > 0)
+ {
+ cmMakefile* mf = this->LongestSource.Target->GetMakefile();
+ cmOStringStream e;
+ e <<
+ "The binary and/or source directory paths may be too long to generate "
+ "Visual Studio 10 files for this project. "
+ "Consider choosing shorter directory names to build this project with "
+ "Visual Studio 10. "
+ "A more detailed explanation follows."
+ "\n"
+ "There is a bug in the VS 10 IDE that renders property dialog fields "
+ "blank for files referenced by full path in the project file. "
+ "However, CMake must reference at least one file by full path:\n"
+ " " << this->LongestSource.SourceFile->GetFullPath() << "\n"
+ "This is because some Visual Studio tools would append the relative "
+ "path to the end of the referencing directory path, as in:\n"
+ " " << mf->GetCurrentOutputDirectory() << "/"
+ << this->LongestSource.SourceRel << "\n"
+ "and then incorrectly complain that the file does not exist because "
+ "the path length is too long for some internal buffer or API. "
+ "To avoid this problem CMake must use a full path for this file "
+ "which then triggers the VS 10 property dialog bug.";
+ mf->IssueMessage(cmake::WARNING, e.str().c_str());
+ }
+}
+
+//----------------------------------------------------------------------------
void cmGlobalVisualStudio10Generator
::GetDocumentation(cmDocumentationEntry& entry) const
{
@@ -212,3 +245,36 @@ bool cmGlobalVisualStudio10Generator::Find64BitTools(cmMakefile* mf)
return false;
}
}
+
+//----------------------------------------------------------------------------
+std::string
+cmGlobalVisualStudio10Generator
+::GenerateRuleFile(std::string const& output) const
+{
+ // The VS 10 generator needs to create the .rule files on disk.
+ // Hide them away under the CMakeFiles directory.
+ std::string ruleDir = this->GetCMakeInstance()->GetHomeOutputDirectory();
+ ruleDir += cmake::GetCMakeFilesDirectory();
+ ruleDir += "/";
+ ruleDir += cmSystemTools::ComputeStringMD5(
+ cmSystemTools::GetFilenamePath(output).c_str());
+ std::string ruleFile = ruleDir + "/";
+ ruleFile += cmSystemTools::GetFilenameName(output);
+ ruleFile += ".rule";
+ return ruleFile;
+}
+
+//----------------------------------------------------------------------------
+void cmGlobalVisualStudio10Generator::PathTooLong(
+ cmTarget* target, cmSourceFile* sf, std::string const& sfRel)
+{
+ size_t len = (strlen(target->GetMakefile()->GetCurrentOutputDirectory()) +
+ 1 + sfRel.length());
+ if(len > this->LongestSource.Length)
+ {
+ this->LongestSource.Length = len;
+ this->LongestSource.Target = target;
+ this->LongestSource.SourceFile = sf;
+ this->LongestSource.SourceRel = sfRel;
+ }
+}
diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h
index 750b89c..4236563 100644
--- a/Source/cmGlobalVisualStudio10Generator.h
+++ b/Source/cmGlobalVisualStudio10Generator.h
@@ -46,6 +46,8 @@ public:
///! create the correct local generator
virtual cmLocalGenerator *CreateLocalGenerator();
+ virtual void Generate();
+
/**
* Try to determine system infomation such as shared library
* extension, pthreads, byte order etc.
@@ -75,10 +77,26 @@ public:
virtual const char* GetCMakeCFGIntDir() const
{ return "$(Configuration)";}
bool Find64BitTools(cmMakefile* mf);
+
+ /** Generate an <output>.rule file path for a given command output. */
+ virtual std::string GenerateRuleFile(std::string const& output) const;
+
+ void PathTooLong(cmTarget* target, cmSourceFile* sf,
+ std::string const& sfRel);
protected:
virtual const char* GetIDEVersion() { return "10.0"; }
std::string PlatformToolset;
bool ExpressEdition;
+private:
+ struct LongestSourcePath
+ {
+ LongestSourcePath(): Length(0), Target(0), SourceFile(0) {}
+ size_t Length;
+ cmTarget* Target;
+ cmSourceFile* SourceFile;
+ std::string SourceRel;
+ };
+ LongestSourcePath LongestSource;
};
#endif
diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx
index a5feaca..d6b653c 100644
--- a/Source/cmGlobalVisualStudio71Generator.cxx
+++ b/Source/cmGlobalVisualStudio71Generator.cxx
@@ -241,9 +241,12 @@ void cmGlobalVisualStudio71Generator
::WriteExternalProject(std::ostream& fout,
const char* name,
const char* location,
+ const char* typeGuid,
const std::set<cmStdString>& depends)
{
- fout << "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \""
+ fout << "Project(\"{"
+ << (typeGuid ? typeGuid : "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942")
+ << "}\") = \""
<< name << "\", \""
<< this->ConvertToSolutionPath(location) << "\", \"{"
<< this->GetGUID(name)
@@ -279,18 +282,21 @@ void cmGlobalVisualStudio71Generator
// executables to the libraries it uses are also done here
void cmGlobalVisualStudio71Generator
::WriteProjectConfigurations(std::ostream& fout, const char* name,
- bool partOfDefaultBuild)
+ bool partOfDefaultBuild,
+ const char* platformMapping)
{
std::string guid = this->GetGUID(name);
for(std::vector<std::string>::iterator i = this->Configurations.begin();
i != this->Configurations.end(); ++i)
{
fout << "\t\t{" << guid << "}." << *i
- << ".ActiveCfg = " << *i << "|Win32\n";
+ << ".ActiveCfg = " << *i << "|"
+ << (platformMapping ? platformMapping : "Win32") << std::endl;
if(partOfDefaultBuild)
{
fout << "\t\t{" << guid << "}." << *i
- << ".Build.0 = " << *i << "|Win32\n";
+ << ".Build.0 = " << *i << "|"
+ << (platformMapping ? platformMapping : "Win32") << std::endl;
}
}
}
diff --git a/Source/cmGlobalVisualStudio71Generator.h b/Source/cmGlobalVisualStudio71Generator.h
index 81c2087..503b708 100644
--- a/Source/cmGlobalVisualStudio71Generator.h
+++ b/Source/cmGlobalVisualStudio71Generator.h
@@ -64,10 +64,12 @@ protected:
const char* name, const char* path, cmTarget &t);
virtual void WriteProjectConfigurations(std::ostream& fout,
const char* name,
- bool partOfDefaultBuild);
+ bool partOfDefaultBuild,
+ const char* platformMapping = NULL);
virtual void WriteExternalProject(std::ostream& fout,
const char* name,
const char* path,
+ const char* typeGuid,
const std::set<cmStdString>& depends);
virtual void WriteSLNFooter(std::ostream& fout);
virtual void WriteSLNHeader(std::ostream& fout);
diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx
index a68e6d8..6332d0b 100644
--- a/Source/cmGlobalVisualStudio7Generator.cxx
+++ b/Source/cmGlobalVisualStudio7Generator.cxx
@@ -250,8 +250,9 @@ void cmGlobalVisualStudio7Generator::WriteTargetConfigurations(
const char* expath = target->GetProperty("EXTERNAL_MSPROJECT");
if(expath)
{
- this->WriteProjectConfigurations(fout, target->GetName(),
- true);
+ this->WriteProjectConfigurations(
+ fout, target->GetName(),
+ true, target->GetProperty("VS_PLATFORM_MAPPING"));
}
else
{
@@ -286,8 +287,12 @@ void cmGlobalVisualStudio7Generator::WriteTargetsToSolution(
{
std::string project = target->GetName();
std::string location = expath;
- this->WriteExternalProject(fout, project.c_str(),
- location.c_str(), target->GetUtilities());
+
+ this->WriteExternalProject(fout,
+ project.c_str(),
+ location.c_str(),
+ target->GetProperty("VS_PROJECT_TYPE"),
+ target->GetUtilities());
written = true;
}
else
@@ -580,18 +585,21 @@ cmGlobalVisualStudio7Generator
// executables to the libraries it uses are also done here
void cmGlobalVisualStudio7Generator
::WriteProjectConfigurations(std::ostream& fout, const char* name,
- bool partOfDefaultBuild)
+ bool partOfDefaultBuild,
+ const char* platformMapping)
{
std::string guid = this->GetGUID(name);
for(std::vector<std::string>::iterator i = this->Configurations.begin();
i != this->Configurations.end(); ++i)
{
fout << "\t\t{" << guid << "}." << *i
- << ".ActiveCfg = " << *i << "|Win32\n";
+ << ".ActiveCfg = " << *i << "|"
+ << (platformMapping ? platformMapping : "Win32") << "\n";
if(partOfDefaultBuild)
{
fout << "\t\t{" << guid << "}." << *i
- << ".Build.0 = " << *i << "|Win32\n";
+ << ".Build.0 = " << *i << "|"
+ << (platformMapping ? platformMapping : "Win32") << "\n";
}
}
}
@@ -604,10 +612,14 @@ void cmGlobalVisualStudio7Generator
void cmGlobalVisualStudio7Generator::WriteExternalProject(std::ostream& fout,
const char* name,
const char* location,
+ const char* typeGuid,
const std::set<cmStdString>&)
{
std::string d = cmSystemTools::ConvertToOutputPath(location);
- fout << "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \""
+ fout << "Project("
+ << "\"{"
+ << (typeGuid ? typeGuid : "8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942")
+ << "}\") = \""
<< name << "\", \""
<< this->ConvertToSolutionPath(location) << "\", \"{"
<< this->GetGUID(name)
diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h
index c92998e..9b9107d 100644
--- a/Source/cmGlobalVisualStudio7Generator.h
+++ b/Source/cmGlobalVisualStudio7Generator.h
@@ -107,7 +107,8 @@ protected:
const char* name, const char* path, cmTarget &t);
virtual void WriteProjectConfigurations(std::ostream& fout,
const char* name,
- bool partOfDefaultBuild);
+ bool partOfDefaultBuild,
+ const char* platformMapping = NULL);
virtual void WriteSLNFooter(std::ostream& fout);
virtual void WriteSLNHeader(std::ostream& fout);
virtual std::string WriteUtilityDepend(cmTarget* target);
@@ -130,6 +131,7 @@ protected:
virtual void WriteExternalProject(std::ostream& fout,
const char* name,
const char* path,
+ const char* typeGuid,
const std::set<cmStdString>&
dependencies);
diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx
index a723109..e7c4232 100644
--- a/Source/cmGlobalVisualStudio8Generator.cxx
+++ b/Source/cmGlobalVisualStudio8Generator.cxx
@@ -214,13 +214,11 @@ void cmGlobalVisualStudio8Generator::AddCheckTarget()
// (this could be avoided with per-target source files)
const char* no_main_dependency = 0;
const char* no_working_directory = 0;
- mf->AddCustomCommandToOutput(
- stamps, listFiles,
- no_main_dependency, commandLines, "Checking Build System",
- no_working_directory, true);
- std::string ruleName = stamps[0];
- ruleName += ".rule";
- if(cmSourceFile* file = mf->GetSource(ruleName.c_str()))
+ if(cmSourceFile* file =
+ mf->AddCustomCommandToOutput(
+ stamps, listFiles,
+ no_main_dependency, commandLines, "Checking Build System",
+ no_working_directory, true))
{
tgt->AddSourceFile(file);
}
@@ -270,20 +268,23 @@ cmGlobalVisualStudio8Generator
void
cmGlobalVisualStudio8Generator
::WriteProjectConfigurations(std::ostream& fout, const char* name,
- bool partOfDefaultBuild)
+ bool partOfDefaultBuild,
+ const char* platformMapping)
{
std::string guid = this->GetGUID(name);
for(std::vector<std::string>::iterator i = this->Configurations.begin();
i != this->Configurations.end(); ++i)
{
fout << "\t\t{" << guid << "}." << *i
- << "|" << this->GetPlatformName() << ".ActiveCfg = "
- << *i << "|" << this->GetPlatformName() << "\n";
+ << "|" << this->GetPlatformName() << ".ActiveCfg = " << *i << "|"
+ << (platformMapping ? platformMapping : this->GetPlatformName())
+ << "\n";
if(partOfDefaultBuild)
{
fout << "\t\t{" << guid << "}." << *i
- << "|" << this->GetPlatformName() << ".Build.0 = "
- << *i << "|" << this->GetPlatformName() << "\n";
+ << "|" << this->GetPlatformName() << ".Build.0 = " << *i << "|"
+ << (platformMapping ? platformMapping : this->GetPlatformName())
+ << "\n";
}
}
}
diff --git a/Source/cmGlobalVisualStudio8Generator.h b/Source/cmGlobalVisualStudio8Generator.h
index e0913ed..7dae429 100644
--- a/Source/cmGlobalVisualStudio8Generator.h
+++ b/Source/cmGlobalVisualStudio8Generator.h
@@ -77,7 +77,8 @@ protected:
virtual void WriteSolutionConfigurations(std::ostream& fout);
virtual void WriteProjectConfigurations(std::ostream& fout,
const char* name,
- bool partOfDefaultBuild);
+ bool partOfDefaultBuild,
+ const char* platformMapping = NULL);
virtual bool ComputeTargetDepends();
virtual void WriteProjectDepends(std::ostream& fout, const char* name,
const char* path, cmTarget &t);
diff --git a/Source/cmIncludeExternalMSProjectCommand.cxx b/Source/cmIncludeExternalMSProjectCommand.cxx
index a4369a3..d219c16 100644
--- a/Source/cmIncludeExternalMSProjectCommand.cxx
+++ b/Source/cmIncludeExternalMSProjectCommand.cxx
@@ -25,18 +25,75 @@ bool cmIncludeExternalMSProjectCommand
#ifdef _WIN32
if(this->Makefile->GetDefinition("WIN32"))
{
+ enum Doing { DoingNone, DoingType, DoingGuid, DoingPlatform };
+
+ Doing doing = DoingNone;
+
+ std::string customType;
+ std::string customGuid;
+ std::string platformMapping;
+
+ std::vector<std::string> depends;
+ for (unsigned int i=2; i<args.size(); ++i)
+ {
+ if (args[i] == "TYPE")
+ {
+ doing = DoingType;
+ }
+ else if (args[i] == "GUID")
+ {
+ doing = DoingGuid;
+ }
+ else if (args[i] == "PLATFORM")
+ {
+ doing = DoingPlatform;
+ }
+ else
+ {
+ switch (doing)
+ {
+ case DoingNone: depends.push_back(args[i]); break;
+ case DoingType: customType = args[i]; break;
+ case DoingGuid: customGuid = args[i]; break;
+ case DoingPlatform: platformMapping = args[i]; break;
+ }
+ doing = DoingNone;
+ }
+ }
+
+ // Hack together a utility target storing enough information
+ // to reproduce the target inclusion.
+ std::string utility_name = args[0];
+
std::string path = args[1];
cmSystemTools::ConvertToUnixSlashes(path);
+ if (!customGuid.empty())
+ {
+ std::string guidVariable = utility_name + "_GUID_CMAKE";
+ this->Makefile->GetCMakeInstance()->AddCacheEntry(
+ guidVariable.c_str(), customGuid.c_str(),
+ "Stored GUID", cmCacheManager::INTERNAL);
+ }
+
// Create a target instance for this utility.
cmTarget* target=this->Makefile->AddNewTarget(cmTarget::UTILITY,
- args[0].c_str());
+ utility_name.c_str());
+
+ target->SetProperty("GENERATOR_FILE_NAME", utility_name.c_str());
target->SetProperty("EXTERNAL_MSPROJECT", path.c_str());
- target->SetProperty("EXCLUDE_FROM_ALL","FALSE");
- target->SetProperty("GENERATOR_FILE_NAME", args[0].c_str());
- for (unsigned int i=2; i<args.size(); ++i)
+ target->SetProperty("EXCLUDE_FROM_ALL", "FALSE");
+
+ if (!customType.empty())
+ target->SetProperty("VS_PROJECT_TYPE",customType.c_str());
+ if (!platformMapping.empty())
+ target->SetProperty("VS_PLATFORM_MAPPING",platformMapping.c_str());
+
+ for (std::vector<std::string>::const_iterator it = depends.begin();
+ it != depends.end();
+ ++it)
{
- target->AddUtility(args[i].c_str());
+ target->AddUtility(it->c_str());
}
}
#endif
diff --git a/Source/cmIncludeExternalMSProjectCommand.h b/Source/cmIncludeExternalMSProjectCommand.h
index 911a772..2b2ed0d 100644
--- a/Source/cmIncludeExternalMSProjectCommand.h
+++ b/Source/cmIncludeExternalMSProjectCommand.h
@@ -59,11 +59,21 @@ public:
{
return
" include_external_msproject(projectname location\n"
+ " [TYPE projectTypeGUID]\n"
+ " [GUID projectGUID]\n"
+ " [PLATFORM platformName]\n"
" dep1 dep2 ...)\n"
"Includes an external Microsoft project in the generated workspace "
"file. Currently does nothing on UNIX. This will create a "
"target named [projectname]. This can be used in the add_dependencies "
- "command to make things depend on the external project.";
+ "command to make things depend on the external project."
+ "\n"
+ "TYPE, GUID and PLATFORM are optional parameters that allow one "
+ "to specify the type of project, id (GUID) of the project and "
+ "the name of the target platform. "
+ "This is useful for projects requiring values other than the default "
+ "(e.g. WIX projects). "
+ "These options are not supported by the Visual Studio 6 generator.";
}
cmTypeMacro(cmIncludeExternalMSProjectCommand, cmCommand);
diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx
index cbbcbb0..908f3b0 100644
--- a/Source/cmListCommand.cxx
+++ b/Source/cmListCommand.cxx
@@ -204,6 +204,12 @@ bool cmListCommand::HandleGetCommand(std::vector<std::string> const& args)
this->Makefile->AddDefinition(variableName.c_str(), "NOTFOUND");
return true;
}
+ // FIXME: Add policy to make non-existing lists an error like empty lists.
+ if(varArgsExpanded.empty())
+ {
+ this->SetError("GET given empty list");
+ return false;
+ }
std::string value;
size_t cc;
@@ -318,7 +324,8 @@ bool cmListCommand::HandleInsertCommand(std::vector<std::string> const& args)
// expand the variable
int item = atoi(args[2].c_str());
std::vector<std::string> varArgsExpanded;
- if ( !this->GetList(varArgsExpanded, listName.c_str()) && item != 0)
+ if((!this->GetList(varArgsExpanded, listName.c_str())
+ || varArgsExpanded.empty()) && item != 0)
{
cmOStringStream str;
str << "index: " << item << " out of range (0, 0)";
@@ -544,6 +551,12 @@ bool cmListCommand::HandleRemoveAtCommand(
this->SetError("sub-command REMOVE_AT requires list to be present.");
return false;
}
+ // FIXME: Add policy to make non-existing lists an error like empty lists.
+ if(varArgsExpanded.empty())
+ {
+ this->SetError("REMOVE_AT given empty list");
+ return false;
+ }
size_t cc;
std::vector<size_t> removed;
diff --git a/Source/cmLocalVisualStudio10Generator.cxx b/Source/cmLocalVisualStudio10Generator.cxx
index bf0e997..ace7adf 100644
--- a/Source/cmLocalVisualStudio10Generator.cxx
+++ b/Source/cmLocalVisualStudio10Generator.cxx
@@ -99,6 +99,14 @@ void cmLocalVisualStudio10Generator
{
cmVS10XMLParser parser;
parser.ParseFile(path);
+
+ // if we can not find a GUID then create one
+ if(parser.GUID.empty())
+ {
+ this->GlobalGenerator->CreateGUID(name);
+ return;
+ }
+
std::string guidStoreName = name;
guidStoreName += "_GUID_CMAKE";
// save the GUID in the cache
diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx
index 99a4c95..5ab223b 100644
--- a/Source/cmLocalVisualStudio6Generator.cxx
+++ b/Source/cmLocalVisualStudio6Generator.cxx
@@ -320,7 +320,7 @@ void cmLocalVisualStudio6Generator::WriteDSPFile(std::ostream& fout,
sourceGroup.AssignSource(*i);
// while we are at it, if it is a .rule file then for visual studio 6 we
// must generate it
- if ((*i)->GetExtension() == "rule")
+ if ((*i)->GetPropertyAsBool("__CMAKE_RULE"))
{
if(!cmSystemTools::FileExists(source.c_str()))
{
diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx
index e3ef1b8..0a709ae 100644
--- a/Source/cmMakefile.cxx
+++ b/Source/cmMakefile.cxx
@@ -883,7 +883,7 @@ cmMakefile::AddCustomCommandToTarget(const char* target,
}
//----------------------------------------------------------------------------
-void
+cmSourceFile*
cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
const std::vector<std::string>& depends,
const char* main_dependency,
@@ -897,7 +897,7 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
if(outputs.empty())
{
cmSystemTools::Error("Attempt to add a custom rule with no output!");
- return;
+ return 0;
}
// Validate custom commands. TODO: More strict?
@@ -910,7 +910,7 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
cmOStringStream e;
e << "COMMAND may not contain literal quotes:\n " << cl[0] << "\n";
this->IssueMessage(cmake::FATAL_ERROR, e.str());
- return;
+ return 0;
}
}
@@ -928,7 +928,7 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
{
// The existing custom command is identical. Silently ignore
// the duplicate.
- return;
+ return file;
}
else
{
@@ -948,17 +948,11 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
// Generate a rule file if the main dependency is not available.
if(!file)
{
+ cmGlobalGenerator* gg = this->LocalGenerator->GetGlobalGenerator();
+
// Construct a rule file associated with the first output produced.
- std::string outName = outputs[0];
- outName += ".rule";
- const char* dir =
- this->LocalGenerator->GetGlobalGenerator()->
- GetCMakeCFGIntDir();
- if(dir && dir[0] == '$')
- {
- cmSystemTools::ReplaceString(outName, dir,
- cmake::GetCMakeFilesDirectory());
- }
+ std::string outName = gg->GenerateRuleFile(outputs[0]);
+
// Check if the rule file already exists.
file = this->GetSource(outName.c_str());
if(file && file->GetCustomCommand() && !replace)
@@ -970,11 +964,12 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
outName.c_str(),
"\" which already has a custom rule.");
}
- return;
+ return file;
}
// Create a cmSourceFile for the rule file.
file = this->GetOrCreateSource(outName.c_str(), true);
+ file->SetProperty("__CMAKE_RULE", "1");
}
// Always create the output sources and mark them generated.
@@ -1004,10 +999,11 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs,
cc->SetEscapeAllowMakeVars(true);
file->SetCustomCommand(cc);
}
+ return file;
}
//----------------------------------------------------------------------------
-void
+cmSourceFile*
cmMakefile::AddCustomCommandToOutput(const char* output,
const std::vector<std::string>& depends,
const char* main_dependency,
@@ -1019,9 +1015,9 @@ cmMakefile::AddCustomCommandToOutput(const char* output,
{
std::vector<std::string> outputs;
outputs.push_back(output);
- this->AddCustomCommandToOutput(outputs, depends, main_dependency,
- commandLines, comment, workingDir,
- replace, escapeOldStyle);
+ return this->AddCustomCommandToOutput(outputs, depends, main_dependency,
+ commandLines, comment, workingDir,
+ replace, escapeOldStyle);
}
//----------------------------------------------------------------------------
@@ -1054,13 +1050,14 @@ cmMakefile::AddCustomCommandOldStyle(const char* target,
{
// Get the name of this output.
const char* output = oi->c_str();
+ cmSourceFile* sf;
// Choose whether to use a main dependency.
if(sourceFiles.find(source))
{
// The source looks like a real file. Use it as the main dependency.
- this->AddCustomCommandToOutput(output, depends, source,
- commandLines, comment, 0);
+ sf = this->AddCustomCommandToOutput(output, depends, source,
+ commandLines, comment, 0);
}
else
{
@@ -1068,20 +1065,18 @@ cmMakefile::AddCustomCommandOldStyle(const char* target,
const char* no_main_dependency = 0;
std::vector<std::string> depends2 = depends;
depends2.push_back(source);
- this->AddCustomCommandToOutput(output, depends2, no_main_dependency,
- commandLines, comment, 0);
+ sf = this->AddCustomCommandToOutput(output, depends2, no_main_dependency,
+ commandLines, comment, 0);
}
// If the rule was added to the source (and not a .rule file),
// then add the source to the target to make sure the rule is
// included.
- std::string sname = output;
- sname += ".rule";
- if(!this->GetSource(sname.c_str()))
+ if(sf && !sf->GetPropertyAsBool("__CMAKE_RULE"))
{
if (this->Targets.find(target) != this->Targets.end())
{
- this->Targets[target].AddSource(source);
+ this->Targets[target].AddSourceFile(sf);
}
else
{
@@ -1976,7 +1971,6 @@ cmSourceFile *cmMakefile::GetSourceFileWithOutput(const char *cname)
// look through all the source files that have custom commands
// and see if the custom command has the passed source file as an output
- // keep in mind the possible .rule extension that may be tacked on
for(std::vector<cmSourceFile*>::const_iterator i =
this->SourceFiles.begin(); i != this->SourceFiles.end(); ++i)
{
diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h
index ebd5bcf..9fc64d6 100644
--- a/Source/cmMakefile.h
+++ b/Source/cmMakefile.h
@@ -175,20 +175,22 @@ public:
cmTarget::CustomCommandType type,
const char* comment, const char* workingDir,
bool escapeOldStyle = true);
- void AddCustomCommandToOutput(const std::vector<std::string>& outputs,
- const std::vector<std::string>& depends,
- const char* main_dependency,
- const cmCustomCommandLines& commandLines,
- const char* comment, const char* workingDir,
- bool replace = false,
- bool escapeOldStyle = true);
- void AddCustomCommandToOutput(const char* output,
- const std::vector<std::string>& depends,
- const char* main_dependency,
- const cmCustomCommandLines& commandLines,
- const char* comment, const char* workingDir,
- bool replace = false,
- bool escapeOldStyle = true);
+ cmSourceFile* AddCustomCommandToOutput(
+ const std::vector<std::string>& outputs,
+ const std::vector<std::string>& depends,
+ const char* main_dependency,
+ const cmCustomCommandLines& commandLines,
+ const char* comment, const char* workingDir,
+ bool replace = false,
+ bool escapeOldStyle = true);
+ cmSourceFile* AddCustomCommandToOutput(
+ const char* output,
+ const std::vector<std::string>& depends,
+ const char* main_dependency,
+ const cmCustomCommandLines& commandLines,
+ const char* comment, const char* workingDir,
+ bool replace = false,
+ bool escapeOldStyle = true);
void AddCustomCommandOldStyle(const char* target,
const std::vector<std::string>& outputs,
const std::vector<std::string>& depends,
diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx
index bb8bd3f..63ba58d 100644
--- a/Source/cmNinjaNormalTargetGenerator.cxx
+++ b/Source/cmNinjaNormalTargetGenerator.cxx
@@ -47,8 +47,7 @@ cmNinjaNormalTargetGenerator(cmTarget* target)
{
// on Windows the output dir is already needed at compile time
// ensure the directory exists (OutDir test)
- std::string outpath = target->GetDirectory(this->GetConfigName());
- cmSystemTools::MakeDirectory(outpath.c_str());
+ EnsureDirectoryExists(target->GetDirectory(this->GetConfigName()));
}
}
@@ -56,6 +55,21 @@ cmNinjaNormalTargetGenerator::~cmNinjaNormalTargetGenerator()
{
}
+void
+cmNinjaNormalTargetGenerator
+::EnsureDirectoryExists(const std::string& dir)
+{
+ cmSystemTools::MakeDirectory(dir.c_str());
+}
+
+void
+cmNinjaNormalTargetGenerator
+::EnsureParentDirectoryExists(const std::string& path)
+{
+ EnsureDirectoryExists(cmSystemTools::GetParentDirectory(path.c_str()));
+}
+
+
void cmNinjaNormalTargetGenerator::Generate()
{
if (!this->TargetLinkLanguage) {
@@ -384,13 +398,18 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
}
}
+ std::string path;
if (!this->TargetNameImport.empty()) {
- vars["TARGET_IMPLIB"] = this->GetLocalGenerator()->ConvertToOutputFormat(
- targetOutputImplib.c_str(), cmLocalGenerator::SHELL);
+ path = this->GetLocalGenerator()->ConvertToOutputFormat(
+ targetOutputImplib.c_str(), cmLocalGenerator::SHELL);
+ vars["TARGET_IMPLIB"] = path;
+ EnsureParentDirectoryExists(path);
}
- vars["TARGET_PDB"] = this->GetLocalGenerator()->ConvertToOutputFormat(
- this->GetTargetPDB().c_str(), cmLocalGenerator::SHELL);
+ path = this->GetLocalGenerator()->ConvertToOutputFormat(
+ this->GetTargetPDB().c_str(), cmLocalGenerator::SHELL);
+ vars["TARGET_PDB"] = path;
+ EnsureParentDirectoryExists(path);
std::vector<cmCustomCommand> *cmdLists[3] = {
&this->GetTarget()->GetPreBuildCommands(),
@@ -417,7 +436,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement()
// If we have any PRE_LINK commands, we need to go back to HOME_OUTPUT for
// the link commands.
if (!preLinkCmdLines.empty()) {
- std::string path = this->GetLocalGenerator()->ConvertToOutputFormat(
+ path = this->GetLocalGenerator()->ConvertToOutputFormat(
this->GetMakefile()->GetHomeOutputDirectory(),
cmLocalGenerator::SHELL);
preLinkCmdLines.push_back("cd " + path);
diff --git a/Source/cmNinjaNormalTargetGenerator.h b/Source/cmNinjaNormalTargetGenerator.h
index 1702caf..7acbe8f 100644
--- a/Source/cmNinjaNormalTargetGenerator.h
+++ b/Source/cmNinjaNormalTargetGenerator.h
@@ -35,6 +35,9 @@ private:
void WriteObjectLibStatement();
std::vector<std::string> ComputeLinkCmd();
+ void EnsureDirectoryExists(const std::string& dir);
+ void EnsureParentDirectoryExists(const std::string& path);
+
private:
// Target name info.
std::string TargetNameOut;
diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx
index 1376a48..89f03f6 100644
--- a/Source/cmSystemTools.cxx
+++ b/Source/cmSystemTools.cxx
@@ -104,6 +104,9 @@ public:
private:
HANDLE handle_;
};
+#elif defined(__APPLE__)
+#include <crt_externs.h>
+#define environ (*_NSGetEnviron())
#endif
bool cmSystemTools::s_RunCommandHideConsole = false;
@@ -1630,33 +1633,28 @@ std::vector<std::string> cmSystemTools::GetEnvironmentVariables()
}
//----------------------------------------------------------------------
-std::vector<std::string> cmSystemTools::AppendEnv(
- std::vector<std::string>* env)
+void cmSystemTools::AppendEnv(std::vector<std::string> const& env)
{
- std::vector<std::string> origEnv = GetEnvironmentVariables();
-
- if (env && env->size()>0)
+ for(std::vector<std::string>::const_iterator eit = env.begin();
+ eit != env.end(); ++eit)
{
- std::vector<std::string>::const_iterator eit;
-
- for (eit = env->begin(); eit!= env->end(); ++eit)
- {
- PutEnv(eit->c_str());
- }
+ cmSystemTools::PutEnv(eit->c_str());
}
-
- return origEnv;
}
//----------------------------------------------------------------------
-void cmSystemTools::RestoreEnv(const std::vector<std::string>& env)
+cmSystemTools::SaveRestoreEnvironment::SaveRestoreEnvironment()
{
- std::vector<std::string>::const_iterator eit;
+ this->Env = cmSystemTools::GetEnvironmentVariables();
+}
+//----------------------------------------------------------------------
+cmSystemTools::SaveRestoreEnvironment::~SaveRestoreEnvironment()
+{
// First clear everything in the current environment:
- //
std::vector<std::string> currentEnv = GetEnvironmentVariables();
- for (eit = currentEnv.begin(); eit!= currentEnv.end(); ++eit)
+ for(std::vector<std::string>::const_iterator
+ eit = currentEnv.begin(); eit != currentEnv.end(); ++eit)
{
std::string var(*eit);
@@ -1666,27 +1664,11 @@ void cmSystemTools::RestoreEnv(const std::vector<std::string>& env)
var = var.substr(0, pos);
}
- UnsetEnv(var.c_str());
+ cmSystemTools::UnsetEnv(var.c_str());
}
// Then put back each entry from the original environment:
- //
- for (eit = env.begin(); eit!= env.end(); ++eit)
- {
- PutEnv(eit->c_str());
- }
-}
-
-//----------------------------------------------------------------------
-cmSystemTools::SaveRestoreEnvironment::SaveRestoreEnvironment()
-{
- this->Env = cmSystemTools::GetEnvironmentVariables();
-}
-
-//----------------------------------------------------------------------
-cmSystemTools::SaveRestoreEnvironment::~SaveRestoreEnvironment()
-{
- cmSystemTools::RestoreEnv(this->Env);
+ cmSystemTools::AppendEnv(this->Env);
}
#endif
diff --git a/Source/cmSystemTools.h b/Source/cmSystemTools.h
index 5f21de2..69673c9 100644
--- a/Source/cmSystemTools.h
+++ b/Source/cmSystemTools.h
@@ -371,16 +371,8 @@ public:
/** Get the list of all environment variables */
static std::vector<std::string> GetEnvironmentVariables();
- /** Append multiple variables to the current environment.
- Return the original environment, as it was before the
- append. */
- static std::vector<std::string> AppendEnv(
- std::vector<std::string>* env);
-
- /** Restore the full environment to "env" - use after
- AppendEnv to put the environment back to the way it
- was. */
- static void RestoreEnv(const std::vector<std::string>& env);
+ /** Append multiple variables to the current environment. */
+ static void AppendEnv(std::vector<std::string> const& env);
/** Helper class to save and restore the environment.
Instantiate this class as an automatic variable on
diff --git a/Source/cmTargetLinkLibrariesCommand.h b/Source/cmTargetLinkLibrariesCommand.h
index be866c3..63114d2 100644
--- a/Source/cmTargetLinkLibrariesCommand.h
+++ b/Source/cmTargetLinkLibrariesCommand.h
@@ -64,7 +64,8 @@ public:
"Specify libraries or flags to use when linking a given target. "
"The named <target> must have been created in the current directory "
"by a command such as add_executable or add_library. "
- "The remaining arguments specify library names or flags."
+ "The remaining arguments specify library names or flags. "
+ "Repeated calls for the same <target> append items in the order called."
"\n"
"If a library name matches that of another target in the project "
"a dependency will automatically be added in the build system to make "
diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx
index 6caaad1..9a97ab0 100644
--- a/Source/cmVisualStudio10TargetGenerator.cxx
+++ b/Source/cmVisualStudio10TargetGenerator.cxx
@@ -459,8 +459,9 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source,
command)
{
std::string sourcePath = source->GetFullPath();
- // the rule file seems to need to exist for vs10
- if (source->GetExtension() == "rule")
+ // VS 10 will always rebuild a custom command attached to a .rule
+ // file that doesn't exist so create the file explicitly.
+ if (source->GetPropertyAsBool("__CMAKE_RULE"))
{
if(!cmSystemTools::FileExists(sourcePath.c_str()))
{
@@ -490,14 +491,9 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source,
std::vector<std::string> *configs =
static_cast<cmGlobalVisualStudio7Generator *>
(this->GlobalGenerator)->GetConfigurations();
- this->WriteString("<CustomBuild Include=\"", 2);
- // custom command have to use relative paths or they do not
- // show up in the GUI
- std::string path = cmSystemTools::RelativePath(
- this->Makefile->GetCurrentOutputDirectory(),
- sourcePath.c_str());
- this->ConvertToWindowsSlash(path);
- (*this->BuildFileStream ) << path << "\">\n";
+
+ this->WriteSource("CustomBuild", source, ">\n");
+
for(std::vector<std::string>::iterator i = configs->begin();
i != configs->end(); ++i)
{
@@ -540,6 +536,18 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile* source,
this->WriteString("</CustomBuild>\n", 2);
}
+std::string
+cmVisualStudio10TargetGenerator::ConvertPath(std::string const& path,
+ bool forceRelative)
+{
+ return forceRelative
+ ? cmSystemTools::RelativePath(
+ this->Makefile->GetCurrentOutputDirectory(), path.c_str())
+ : this->LocalGenerator->Convert(path.c_str(),
+ cmLocalGenerator::START_OUTPUT,
+ cmLocalGenerator::UNCHANGED);
+}
+
void cmVisualStudio10TargetGenerator::ConvertToWindowsSlash(std::string& s)
{
// first convert all of the slashes
@@ -558,13 +566,6 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
std::vector<cmSourceFile*> classes = this->Target->GetSourceFiles();
std::set<cmSourceGroup*> groupsUsed;
- std::vector<cmSourceFile*> clCompile;
- std::vector<cmSourceFile*> customBuild;
- std::vector<cmSourceFile*> none;
- std::vector<cmSourceFile*> headers;
- std::vector<cmSourceFile*> idls;
- std::vector<cmSourceFile*> resource;
-
for(std::vector<cmSourceFile*>::const_iterator s = classes.begin();
s != classes.end(); s++)
{
@@ -573,40 +574,6 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
cmSourceGroup& sourceGroup =
this->Makefile->FindSourceGroup(source.c_str(), sourceGroups);
groupsUsed.insert(&sourceGroup);
- const char* lang = sf->GetLanguage();
- bool header = (*s)->GetPropertyAsBool("HEADER_FILE_ONLY")
- || this->GlobalGenerator->IgnoreFile
- ((*s)->GetExtension().c_str());
- std::string ext =
- cmSystemTools::LowerCase((*s)->GetExtension());
- if(!lang)
- {
- lang = "None";
- }
- if(header)
- {
- headers.push_back(sf);
- }
- else if(lang[0] == 'C')
- {
- clCompile.push_back(sf);
- }
- else if(strcmp(lang, "RC") == 0)
- {
- resource.push_back(sf);
- }
- else if(sf->GetCustomCommand())
- {
- customBuild.push_back(sf);
- }
- else if(ext == "idl")
- {
- idls.push_back(sf);
- }
- else
- {
- none.push_back(sf);
- }
}
this->AddMissingSourceGroups(groupsUsed, sourceGroups);
@@ -628,11 +595,11 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
"xmlns=\"http://schemas.microsoft.com/"
"developer/msbuild/2003\">\n",
0);
- this->WriteGroupSources("ClCompile", clCompile, sourceGroups);
- this->WriteGroupSources("ClInclude", headers, sourceGroups);
- this->WriteGroupSources("ResourceCompile", resource, sourceGroups);
- this->WriteGroupSources("Midl", idls, sourceGroups);
- this->WriteGroupSources("CustomBuild", customBuild, sourceGroups);
+ for(ToolSourceMap::const_iterator ti = this->Tools.begin();
+ ti != this->Tools.end(); ++ti)
+ {
+ this->WriteGroupSources(ti->first.c_str(), ti->second, sourceGroups);
+ }
// Add object library contents as external objects.
std::vector<std::string> objs;
@@ -689,7 +656,6 @@ void cmVisualStudio10TargetGenerator::WriteGroups()
this->WriteString("</Filter>\n", 2);
}
this->WriteString("</ItemGroup>\n", 1);
- this->WriteGroupSources("None", none, sourceGroups);
this->WriteString("</Project>\n", 0);
// restore stream pointer
this->BuildFileStream = save;
@@ -749,32 +715,20 @@ cmVisualStudio10TargetGenerator::AddMissingSourceGroups(
void
cmVisualStudio10TargetGenerator::
WriteGroupSources(const char* name,
- std::vector<cmSourceFile*> const& sources,
+ ToolSources const& sources,
std::vector<cmSourceGroup>& sourceGroups)
{
this->WriteString("<ItemGroup>\n", 1);
- for(std::vector<cmSourceFile*>::const_iterator s = sources.begin();
+ for(ToolSources::const_iterator s = sources.begin();
s != sources.end(); ++s)
{
- cmSourceFile* sf = *s;
- if(sf->GetExtension() == "obj")
- {
- continue;
- }
+ cmSourceFile* sf = s->SourceFile;
std::string const& source = sf->GetFullPath();
cmSourceGroup& sourceGroup =
this->Makefile->FindSourceGroup(source.c_str(), sourceGroups);
const char* filter = sourceGroup.GetFullName();
this->WriteString("<", 2);
- std::string path = source;
- // custom command sources must use relative paths or they will
- // not show up in the GUI.
- if(sf->GetCustomCommand())
- {
- path = cmSystemTools::RelativePath(
- this->Makefile->GetCurrentOutputDirectory(),
- source.c_str());
- }
+ std::string path = this->ConvertPath(source, s->RelativePath);
this->ConvertToWindowsSlash(path);
(*this->BuildFileStream) << name << " Include=\""
<< path;
@@ -795,15 +749,47 @@ WriteGroupSources(const char* name,
}
void cmVisualStudio10TargetGenerator::WriteSource(
- const char* tool, cmSourceFile* sf, bool end)
+ const char* tool, cmSourceFile* sf, const char* end)
{
- std::string sourceFile = sf->GetFullPath();
- // do not use a relative path here because it means that you
- // can not use as long a path to the file.
+ // Visual Studio tools append relative paths to the current dir, as in:
+ //
+ // c:\path\to\current\dir\..\..\..\relative\path\to\source.c
+ //
+ // and fail if this exceeds the maximum allowed path length. Our path
+ // conversion uses full paths outside the build tree to allow deeper trees.
+ bool forceRelative = false;
+ std::string sourceFile = this->ConvertPath(sf->GetFullPath(), false);
+ if(this->LocalGenerator->GetVersion() == cmLocalVisualStudioGenerator::VS10
+ && cmSystemTools::FileIsFullPath(sourceFile.c_str()))
+ {
+ // Normal path conversion resulted in a full path. VS 10 (but not 11)
+ // refuses to show the property page in the IDE for a source file with a
+ // full path (not starting in a '.' or '/' AFAICT). CMake <= 2.8.4 used a
+ // relative path but to allow deeper build trees CMake 2.8.[5678] used a
+ // full path except for custom commands. Custom commands do not work
+ // without a relative path, but they do not seem to be involved in tools
+ // with the above behavior. For other sources we now use a relative path
+ // when the combined path will not be too long so property pages appear.
+ std::string sourceRel = this->ConvertPath(sf->GetFullPath(), true);
+ size_t const maxLen = 250;
+ if(sf->GetCustomCommand() ||
+ ((strlen(this->Makefile->GetCurrentOutputDirectory()) + 1 +
+ sourceRel.length()) <= maxLen))
+ {
+ forceRelative = true;
+ sourceFile = sourceRel;
+ }
+ else
+ {
+ this->GlobalGenerator->PathTooLong(this->Target, sf, sourceRel);
+ }
+ }
this->ConvertToWindowsSlash(sourceFile);
this->WriteString("<", 2);
(*this->BuildFileStream ) << tool <<
- " Include=\"" << sourceFile << (end? "\" />\n" : "\" ");
+ " Include=\"" << sourceFile << "\"" << (end? end : " />\n");
+ ToolSource toolSource = {sf, forceRelative};
+ this->Tools[tool].push_back(toolSource);
}
void cmVisualStudio10TargetGenerator::WriteSources(
@@ -835,7 +821,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources()
bool cl = strcmp(lang, "C") == 0 || strcmp(lang, "CXX") == 0;
bool rc = strcmp(lang, "RC") == 0;
const char* tool = cl? "ClCompile" : (rc? "ResourceCompile" : "None");
- this->WriteSource(tool, *si, false);
+ this->WriteSource(tool, *si, " ");
// ouput any flags specific to this source file
if(cl && this->OutputSourceSpecificFlags(*si))
{
diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h
index 20a443b..2d5ec2a 100644
--- a/Source/cmVisualStudio10TargetGenerator.h
+++ b/Source/cmVisualStudio10TargetGenerator.h
@@ -43,11 +43,19 @@ public:
);
private:
+ struct ToolSource
+ {
+ cmSourceFile* SourceFile;
+ bool RelativePath;
+ };
+ struct ToolSources: public std::vector<ToolSource> {};
+
+ std::string ConvertPath(std::string const& path, bool forceRelative);
void ConvertToWindowsSlash(std::string& s);
void WriteString(const char* line, int indentLevel);
void WriteProjectConfigurations();
void WriteProjectConfigurationValues();
- void WriteSource(const char* tool, cmSourceFile* sf, bool end = true);
+ void WriteSource(const char* tool, cmSourceFile* sf, const char* end = 0);
void WriteSources(const char* tool, std::vector<cmSourceFile*> const&);
void WriteAllSources();
void WriteDotNetReferences();
@@ -77,8 +85,7 @@ private:
void WriteEvents(std::string const& configName);
void WriteEvent(const char* name, std::vector<cmCustomCommand> & commands,
std::string const& configName);
- void WriteGroupSources(const char* name,
- std::vector<cmSourceFile*> const& sources,
+ void WriteGroupSources(const char* name, ToolSources const& sources,
std::vector<cmSourceGroup>& );
void AddMissingSourceGroups(std::set<cmSourceGroup*>& groupsUsed,
const std::vector<cmSourceGroup>& allGroups);
@@ -99,6 +106,9 @@ private:
cmGeneratedFileStream* BuildFileStream;
cmLocalVisualStudio7Generator* LocalGenerator;
std::set<cmSourceFile*> SourcesVisited;
+
+ typedef std::map<cmStdString, ToolSources> ToolSourceMap;
+ ToolSourceMap Tools;
};
#endif
diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt
index 0ef4e28..520cafb 100644
--- a/Source/kwsys/CMakeLists.txt
+++ b/Source/kwsys/CMakeLists.txt
@@ -123,7 +123,6 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR)
SET(KWSYS_USE_FundamentalType 1)
SET(KWSYS_USE_Terminal 1)
SET(KWSYS_USE_IOStream 1)
- SET(KWSYS_USE_DateStamp 1)
SET(KWSYS_USE_String 1)
SET(KWSYS_USE_SystemInformation 1)
SET(KWSYS_USE_CPU 1)
@@ -553,11 +552,16 @@ SET_SOURCE_FILES_PROPERTIES(ProcessUNIX.c System.c PROPERTIES
COMPILE_FLAGS "-DKWSYS_C_HAS_PTRDIFF_T=${KWSYS_C_HAS_PTRDIFF_T} -DKWSYS_C_HAS_SSIZE_T=${KWSYS_C_HAS_SSIZE_T}"
)
-IF(KWSYS_DO_NOT_CLEAN_PUTENV)
- # Disable cleanup of putenv memory for issues with GCOV.
+IF(KWSYS_USE_SystemTools)
+ KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_SETENV
+ "Checking whether CXX compiler has setenv" DIRECT)
+ KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_UNSETENV
+ "Checking whether CXX compiler has unsetenv" DIRECT)
+ KWSYS_PLATFORM_CXX_TEST(KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H
+ "Checking whether CXX compiler has environ in stdlib.h" DIRECT)
SET_SOURCE_FILES_PROPERTIES(SystemTools.cxx PROPERTIES
- COMPILE_FLAGS -DKWSYS_DO_NOT_CLEAN_PUTENV=1)
-ENDIF(KWSYS_DO_NOT_CLEAN_PUTENV)
+ COMPILE_FLAGS "-DKWSYS_CXX_HAS_SETENV=${KWSYS_CXX_HAS_SETENV} -DKWSYS_CXX_HAS_UNSETENV=${KWSYS_CXX_HAS_UNSETENV} -DKWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H=${KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H}")
+ENDIF()
#-----------------------------------------------------------------------------
# Choose a directory for the generated headers.
@@ -690,7 +694,7 @@ ENDFOREACH(cpp)
# Add selected C components.
FOREACH(c
- Process Base64 FundamentalType MD5 Terminal System DateStamp String CPU
+ Process Base64 FundamentalType MD5 Terminal System String CPU
)
IF(KWSYS_USE_${c})
# Use the corresponding header file.
diff --git a/Source/kwsys/DateStamp.h.in b/Source/kwsys/DateStamp.h.in
deleted file mode 100644
index c3d0099..0000000
--- a/Source/kwsys/DateStamp.h.in
+++ /dev/null
@@ -1,42 +0,0 @@
-/*============================================================================
- KWSys - Kitware System Library
- 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 @KWSYS_NAMESPACE@_DateStamp_h
-#define @KWSYS_NAMESPACE@_DateStamp_h
-
-/** Version date integer year. The format is CCYY. */
-#define @KWSYS_NAMESPACE@_DATE_STAMP_YEAR @KWSYS_DATE_STAMP_YEAR@
-
-/** Version date integer month. The format is MM. */
-#define @KWSYS_NAMESPACE@_DATE_STAMP_MONTH @KWSYS_DATE_STAMP_MONTH@
-
-/** Version date integer day. The format is DD. */
-#define @KWSYS_NAMESPACE@_DATE_STAMP_DAY @KWSYS_DATE_STAMP_DAY@
-
-/** Version date full integer. The format is CCYYMMDD. */
-#define @KWSYS_NAMESPACE@_DATE_STAMP_FULL @KWSYS_DATE_STAMP_YEAR@@KWSYS_DATE_STAMP_MONTH@@KWSYS_DATE_STAMP_DAY@
-
-/** Version date string year. The format is "CCYY". */
-#define @KWSYS_NAMESPACE@_DATE_STAMP_STRING_YEAR "@KWSYS_DATE_STAMP_YEAR@"
-
-/** Version date string month. The format is "MM". */
-#define @KWSYS_NAMESPACE@_DATE_STAMP_STRING_MONTH "@KWSYS_DATE_STAMP_MONTH@"
-
-/** Version date string day. The format is "DD". */
-#define @KWSYS_NAMESPACE@_DATE_STAMP_STRING_DAY "@KWSYS_DATE_STAMP_DAY@"
-
-/** Version date full string. The format is "CCYYMMDD". */
-#define @KWSYS_NAMESPACE@_DATE_STAMP_STRING_FULL "@KWSYS_DATE_STAMP_YEAR@@KWSYS_DATE_STAMP_MONTH@@KWSYS_DATE_STAMP_DAY@"
-
-/** Version date formatted string. The format is "CCYY-MM-DD". */
-#define @KWSYS_NAMESPACE@_DATE_STAMP_STRING "@KWSYS_DATE_STAMP_YEAR@-@KWSYS_DATE_STAMP_MONTH@-@KWSYS_DATE_STAMP_DAY@"
-
-#endif
diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx
index 4d83293..8ab580f 100644
--- a/Source/kwsys/SystemTools.cxx
+++ b/Source/kwsys/SystemTools.cxx
@@ -25,6 +25,8 @@
#include KWSYS_HEADER(ios/fstream)
#include KWSYS_HEADER(ios/sstream)
+#include KWSYS_HEADER(stl/set)
+
// Work-around CMake dependency scanning limitation. This must
// duplicate the above list of headers.
#if 0
@@ -78,6 +80,14 @@
# undef _WIN32
#endif
+#if !KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H
+# if defined(_WIN32)
+extern __declspec(dllimport) char **environ;
+# else
+extern char **environ;
+# endif
+#endif
+
#ifdef __CYGWIN__
extern "C" void cygwin_conv_to_win32_path(const char *path, char *win32_path);
#endif
@@ -371,38 +381,224 @@ bool SystemTools::GetEnv(const char* key, kwsys_stl::string& result)
}
}
-#ifdef __INTEL_COMPILER
-#pragma warning disable 444
+//----------------------------------------------------------------------------
+
+#if defined(__CYGWIN__) || defined(__GLIBC__)
+# define KWSYS_PUTENV_NAME /* putenv("A") removes A. */
+#elif defined(_WIN32)
+# define KWSYS_PUTENV_EMPTY /* putenv("A=") removes A. */
#endif
-class kwsysDeletingCharVector : public kwsys_stl::vector<char*>
+#if KWSYS_CXX_HAS_UNSETENV
+/* unsetenv("A") removes A from the environment.
+ On older platforms it returns void instead of int. */
+static int kwsysUnPutEnv(const char* env)
{
-public:
- ~kwsysDeletingCharVector();
-};
+ if(const char* eq = strchr(env, '='))
+ {
+ std::string name(env, eq-env);
+ unsetenv(name.c_str());
+ }
+ else
+ {
+ unsetenv(env);
+ }
+ return 0;
+}
-kwsysDeletingCharVector::~kwsysDeletingCharVector()
+#elif defined(KWSYS_PUTENV_EMPTY) || defined(KWSYS_PUTENV_NAME)
+/* putenv("A=") or putenv("A") removes A from the environment. */
+static int kwsysUnPutEnv(const char* env)
{
-#ifndef KWSYS_DO_NOT_CLEAN_PUTENV
- for(kwsys_stl::vector<char*>::iterator i = this->begin();
- i != this->end(); ++i)
+ int err = 0;
+ const char* eq = strchr(env, '=');
+ size_t const len = eq? (size_t)(eq-env) : strlen(env);
+# ifdef KWSYS_PUTENV_EMPTY
+ size_t const sz = len + 2;
+# else
+ size_t const sz = len + 1;
+# endif
+ char local_buf[256];
+ char* buf = sz > sizeof(local_buf) ? (char*)malloc(sz) : local_buf;
+ if(!buf)
+ {
+ return -1;
+ }
+ strncpy(buf, env, len);
+# ifdef KWSYS_PUTENV_EMPTY
+ buf[len] = '=';
+ buf[len+1] = 0;
+ if(putenv(buf) < 0)
+ {
+ err = errno;
+ }
+# else
+ buf[len] = 0;
+ if(putenv(buf) < 0 && errno != EINVAL)
+ {
+ err = errno;
+ }
+# endif
+ if(buf != local_buf)
+ {
+ free(buf);
+ }
+ if(err)
+ {
+ errno = err;
+ return -1;
+ }
+ return 0;
+}
+
+#else
+/* Manipulate the "environ" global directly. */
+static int kwsysUnPutEnv(const char* env)
+{
+ const char* eq = strchr(env, '=');
+ size_t const len = eq? (size_t)(eq-env) : strlen(env);
+ int in = 0;
+ int out = 0;
+ while(environ[in])
+ {
+ if(strlen(environ[in]) > len &&
+ environ[in][len] == '=' &&
+ strncmp(env, environ[in], len) == 0)
+ {
+ ++in;
+ }
+ else
+ {
+ environ[out++] = environ[in++];
+ }
+ }
+ while(out < in)
{
- delete []*i;
+ environ[out++] = 0;
}
+ return 0;
+}
#endif
+
+//----------------------------------------------------------------------------
+
+#if KWSYS_CXX_HAS_SETENV
+
+/* setenv("A", "B", 1) will set A=B in the environment and makes its
+ own copies of the strings. */
+bool SystemTools::PutEnv(const char* env)
+{
+ if(const char* eq = strchr(env, '='))
+ {
+ std::string name(env, eq-env);
+ return setenv(name.c_str(), eq+1, 1) == 0;
+ }
+ else
+ {
+ return kwsysUnPutEnv(env) == 0;
+ }
}
-bool SystemTools::PutEnv(const char* value)
+
+bool SystemTools::UnPutEnv(const char* env)
{
- static kwsysDeletingCharVector localEnvironment;
- char* envVar = new char[strlen(value)+1];
- strcpy(envVar, value);
- int ret = putenv(envVar);
- // save the pointer in the static vector so that it can
- // be deleted on exit
- localEnvironment.push_back(envVar);
- return ret == 0;
+ return kwsysUnPutEnv(env) == 0;
}
+#else
+
+/* putenv("A=B") will set A=B in the environment. Most putenv implementations
+ put their argument directly in the environment. They never free the memory
+ on program exit. Keep an active set of pointers to memory we allocate and
+ pass to putenv, one per environment key. At program exit remove any
+ environment values that may still reference memory we allocated. Then free
+ the memory. This will not affect any environment values we never set. */
+
+# ifdef __INTEL_COMPILER
+# pragma warning disable 444 /* base has non-virtual destructor */
+# endif
+
+/* Order by environment key only (VAR from VAR=VALUE). */
+struct kwsysEnvCompare
+{
+ bool operator() (const char* l, const char* r) const
+ {
+ const char* leq = strchr(l, '=');
+ const char* req = strchr(r, '=');
+ size_t llen = leq? (leq-l) : strlen(l);
+ size_t rlen = req? (req-r) : strlen(r);
+ if(llen == rlen)
+ {
+ return strncmp(l,r,llen) < 0;
+ }
+ else
+ {
+ return strcmp(l,r) < 0;
+ }
+ }
+};
+
+class kwsysEnv: public kwsys_stl::set<const char*, kwsysEnvCompare>
+{
+ class Free
+ {
+ const char* Env;
+ public:
+ Free(const char* env): Env(env) {}
+ ~Free() { free(const_cast<char*>(this->Env)); }
+ };
+public:
+ typedef kwsys_stl::set<const char*, kwsysEnvCompare> derived;
+ ~kwsysEnv()
+ {
+ for(derived::iterator i = this->begin(); i != this->end(); ++i)
+ {
+ kwsysUnPutEnv(*i);
+ free(const_cast<char*>(*i));
+ }
+ }
+ const char* Release(const char* env)
+ {
+ const char* old = 0;
+ derived::iterator i = this->find(env);
+ if(i != this->end())
+ {
+ old = *i;
+ this->erase(i);
+ }
+ return old;
+ }
+ bool Put(const char* env)
+ {
+ Free oldEnv(this->Release(env));
+ static_cast<void>(oldEnv);
+ char* newEnv = strdup(env);
+ this->insert(newEnv);
+ return putenv(newEnv) == 0;
+ }
+ bool UnPut(const char* env)
+ {
+ Free oldEnv(this->Release(env));
+ static_cast<void>(oldEnv);
+ return kwsysUnPutEnv(env) == 0;
+ }
+};
+
+static kwsysEnv kwsysEnvInstance;
+
+bool SystemTools::PutEnv(const char* env)
+{
+ return kwsysEnvInstance.Put(env);
+}
+
+bool SystemTools::UnPutEnv(const char* env)
+{
+ return kwsysEnvInstance.UnPut(env);
+}
+
+#endif
+
+//----------------------------------------------------------------------------
+
const char* SystemTools::GetExecutableExtension()
{
#if defined(_WIN32) || defined(__CYGWIN__) || defined(__VMS)
diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in
index 04f1978..5171125 100644
--- a/Source/kwsys/SystemTools.hxx.in
+++ b/Source/kwsys/SystemTools.hxx.in
@@ -749,7 +749,11 @@ public:
/** Put a string into the environment
of the form var=value */
- static bool PutEnv(const char* value);
+ static bool PutEnv(const char* env);
+
+ /** Remove a string from the environment.
+ Input is of the form "var" or "var=value" (value is ignored). */
+ static bool UnPutEnv(const char* env);
/**
* Get current working directory CWD
diff --git a/Source/kwsys/kwsysDateStamp.cmake b/Source/kwsys/kwsysDateStamp.cmake
deleted file mode 100644
index 3d0f03d..0000000
--- a/Source/kwsys/kwsysDateStamp.cmake
+++ /dev/null
@@ -1,21 +0,0 @@
-# Do not edit! Generated by kwsysDateStamp.py
-#=============================================================================
-# KWSys - Kitware System Library
-# 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.
-#=============================================================================
-
-# KWSys version date year component. Format is CCYY.
-SET(KWSYS_DATE_STAMP_YEAR 2012)
-
-# KWSys version date month component. Format is MM.
-SET(KWSYS_DATE_STAMP_MONTH 04)
-
-# KWSys version date day component. Format is DD.
-SET(KWSYS_DATE_STAMP_DAY 20)
diff --git a/Source/kwsys/kwsysDateStamp.py b/Source/kwsys/kwsysDateStamp.py
deleted file mode 100755
index bd2e49a..0000000
--- a/Source/kwsys/kwsysDateStamp.py
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/usr/bin/python
-#=============================================================================
-# KWSys - Kitware System Library
-# 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.
-#=============================================================================
-
-import sys,os
-import time
-
-# Get the path to the directory containing this script.
-if __name__ == '__main__':
- selfdir = os.path.abspath(sys.path[0] or os.curdir)
-else:
- selfdir = os.path.abspath(os.path.dirname(__file__))
-
-# Open the CMake code file.
-fname = os.path.join(selfdir, 'kwsysDateStamp.cmake')
-fout = open(fname, 'w');
-
-# Get the current time.
-ct = time.localtime()
-
-# Write the CMake code describing the date.
-fout.write("""# Do not edit! Generated by kwsysDateStamp.py
-#=============================================================================
-# KWSys - Kitware System Library
-# 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.
-#=============================================================================
-
-# KWSys version date year component. Format is CCYY.
-SET(KWSYS_DATE_STAMP_YEAR %04u)
-
-# KWSys version date month component. Format is MM.
-SET(KWSYS_DATE_STAMP_MONTH %02u)
-
-# KWSys version date day component. Format is DD.
-SET(KWSYS_DATE_STAMP_DAY %02u)
-""" % (ct.tm_year, ct.tm_mon, ct.tm_mday))
-
-fout.close()
diff --git a/Source/kwsys/kwsysPlatformTestsCXX.cxx b/Source/kwsys/kwsysPlatformTestsCXX.cxx
index 903be9b..16124d3 100644
--- a/Source/kwsys/kwsysPlatformTestsCXX.cxx
+++ b/Source/kwsys/kwsysPlatformTestsCXX.cxx
@@ -393,6 +393,32 @@ int main(int, char **argv)
}
#endif
+#ifdef TEST_KWSYS_CXX_HAS_SETENV
+#include <stdlib.h>
+int main()
+{
+ return setenv("A", "B", 1);
+}
+#endif
+
+#ifdef TEST_KWSYS_CXX_HAS_UNSETENV
+#include <stdlib.h>
+int main()
+{
+ unsetenv("A");
+ return 0;
+}
+#endif
+
+#ifdef TEST_KWSYS_CXX_HAS_ENVIRON_IN_STDLIB_H
+#include <stdlib.h>
+int main()
+{
+ char* e = environ[0];
+ return e? 0:1;
+}
+#endif
+
#ifdef TEST_KWSYS_CXX_TYPE_INFO
/* Collect fundamental type information and save it to a CMake script. */
diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx
index c0e74af..3ac0cb3 100644
--- a/Source/kwsys/testSystemTools.cxx
+++ b/Source/kwsys/testSystemTools.cxx
@@ -328,6 +328,58 @@ bool CheckStringOperations()
}
//----------------------------------------------------------------------------
+
+bool CheckPutEnv(const char* env, const char* name, const char* value)
+{
+ if(!kwsys::SystemTools::PutEnv(env))
+ {
+ kwsys_ios::cerr << "PutEnv(\"" << env
+ << "\") failed!" << kwsys_ios::endl;
+ return false;
+ }
+ const char* v = kwsys::SystemTools::GetEnv(name);
+ v = v? v : "(null)";
+ if(strcmp(v, value) != 0)
+ {
+ kwsys_ios::cerr << "GetEnv(\"" << name << "\") returned \""
+ << v << "\", not \"" << value << "\"!" << kwsys_ios::endl;
+ return false;
+ }
+ return true;
+}
+
+bool CheckUnPutEnv(const char* env, const char* name)
+{
+ if(!kwsys::SystemTools::UnPutEnv(env))
+ {
+ kwsys_ios::cerr << "UnPutEnv(\"" << env << "\") failed!"
+ << kwsys_ios::endl;
+ return false;
+ }
+ if(const char* v = kwsys::SystemTools::GetEnv(name))
+ {
+ kwsys_ios::cerr << "GetEnv(\"" << name << "\") returned \""
+ << v << "\", not (null)!" << kwsys_ios::endl;
+ return false;
+ }
+ return true;
+}
+
+bool CheckEnvironmentOperations()
+{
+ bool res = true;
+ res &= CheckPutEnv("A=B", "A", "B");
+ res &= CheckPutEnv("B=C", "B", "C");
+ res &= CheckPutEnv("C=D", "C", "D");
+ res &= CheckPutEnv("D=E", "D", "E");
+ res &= CheckUnPutEnv("A", "A");
+ res &= CheckUnPutEnv("B=", "B");
+ res &= CheckUnPutEnv("C=D", "C");
+ /* Leave "D=E" in environment so a memory checker can test for leaks. */
+ return res;
+}
+
+//----------------------------------------------------------------------------
int testSystemTools(int, char*[])
{
bool res = true;
@@ -356,5 +408,7 @@ int testSystemTools(int, char*[])
res &= CheckStringOperations();
+ res &= CheckEnvironmentOperations();
+
return res ? 0 : 1;
}