diff options
Diffstat (limited to 'Source')
214 files changed, 4785 insertions, 4793 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 6f12785..a7adb51 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -233,8 +233,6 @@ set(SRCS cmExtraKateGenerator.h cmExtraSublimeTextGenerator.cxx cmExtraSublimeTextGenerator.h - cmExtraQbsGenerator.cxx - cmExtraQbsGenerator.h cmFileLock.cxx cmFileLock.h cmFileLockPool.cxx @@ -349,6 +347,8 @@ set(SRCS cmXMLParser.h cmXMLSafe.cxx cmXMLSafe.h + cmXMLWriter.cxx + cmXMLWriter.h cmake.cxx cmake.h diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index f76ba0d..727cbcc 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,5 +1,5 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) -set(CMake_VERSION_MINOR 2) -set(CMake_VERSION_PATCH 20150429) -#set(CMake_VERSION_RC 1) +set(CMake_VERSION_MINOR 3) +set(CMake_VERSION_PATCH 0) +set(CMake_VERSION_RC 1) diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.cxx b/Source/CPack/IFW/cmCPackIFWGenerator.cxx index 0439ff6..80ba068 100644 --- a/Source/CPack/IFW/cmCPackIFWGenerator.cxx +++ b/Source/CPack/IFW/cmCPackIFWGenerator.cxx @@ -29,6 +29,8 @@ #include <cmMakefile.h> #include <cmGeneratedFileStream.h> #include <cmXMLSafe.h> +#include <cmVersionConfig.h> +#include <cmTimestamp.h> //---------------------------------------------------------------------------- cmCPackIFWGenerator::cmCPackIFWGenerator() @@ -41,6 +43,27 @@ cmCPackIFWGenerator::~cmCPackIFWGenerator() } //---------------------------------------------------------------------------- +bool cmCPackIFWGenerator::IsVersionLess(const char *version) +{ + return cmSystemTools::VersionCompare(cmSystemTools::OP_LESS, + FrameworkVersion.data(), version); +} + +//---------------------------------------------------------------------------- +bool cmCPackIFWGenerator::IsVersionGreater(const char *version) +{ + return cmSystemTools::VersionCompare(cmSystemTools::OP_GREATER, + FrameworkVersion.data(), version); +} + +//---------------------------------------------------------------------------- +bool cmCPackIFWGenerator::IsVersionEqual(const char *version) +{ + return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL, + FrameworkVersion.data(), version); +} + +//---------------------------------------------------------------------------- int cmCPackIFWGenerator::PackageFiles() { cmCPackLogger(cmCPackLog::LOG_OUTPUT, "- Configuration" << std::endl); @@ -59,7 +82,12 @@ int cmCPackIFWGenerator::PackageFiles() if (!Installer.Repositories.empty()) { std::string ifwCmd = RepoGen; - ifwCmd += " -c " + this->toplevel + "/config/config.xml"; + + if(IsVersionLess("2.0.0")) + { + ifwCmd += " -c " + this->toplevel + "/config/config.xml"; + } + ifwCmd += " -p " + this->toplevel + "/packages"; if(!PkgsDirsVector.empty()) @@ -216,8 +244,7 @@ const char *cmCPackIFWGenerator::GetPackagingInstallPrefix() //---------------------------------------------------------------------------- const char *cmCPackIFWGenerator::GetOutputExtension() { - const char *suffix = this->GetOption("CMAKE_EXECUTABLE_SUFFIX"); - return suffix ? suffix : cmCPackGenerator::GetOutputExtension(); + return ExecutableSuffix.c_str(); } //---------------------------------------------------------------------------- @@ -267,6 +294,17 @@ int cmCPackIFWGenerator::InitializeInternal() RepoGen = RepoGenStr; } + // Framework version + if(const char* FrameworkVersionSrt = + this->GetOption("CPACK_IFW_FRAMEWORK_VERSION")) + { + FrameworkVersion = FrameworkVersionSrt; + } + else + { + FrameworkVersion = "1.9.9"; + } + // Variables that Change Behavior // Resolve duplicate names @@ -307,6 +345,24 @@ int cmCPackIFWGenerator::InitializeInternal() return 0; } + // Executable suffix + if(const char *optExeSuffix = this->GetOption("CMAKE_EXECUTABLE_SUFFIX")) + { + ExecutableSuffix = optExeSuffix; + if(ExecutableSuffix.empty()) + { + std::string sysName(this->GetOption("CMAKE_SYSTEM_NAME")); + if(sysName == "Linux") + { + ExecutableSuffix = ".run"; + } + } + } + else + { + ExecutableSuffix = cmCPackGenerator::GetOutputExtension(); + } + return this->Superclass::InitializeInternal(); } @@ -552,3 +608,20 @@ cmCPackIFWPackage* cmCPackIFWGenerator::GetComponentPackage( = ComponentPackages.find(component); return pit != ComponentPackages.end() ? pit->second : 0; } + +//---------------------------------------------------------------------------- +void cmCPackIFWGenerator::WriteGeneratedByToStrim(cmGeneratedFileStream &xout) +{ + xout << "<!-- Generated by CPack " << CMake_VERSION << " IFW generator " + << "for QtIFW "; + if(IsVersionLess("2.0")) + { + xout << "less 2.0"; + } + else + { + xout << FrameworkVersion; + } + xout << " tools at " << cmTimestamp().CurrentTime("", true) << " -->" + << std::endl; +} diff --git a/Source/CPack/IFW/cmCPackIFWGenerator.h b/Source/CPack/IFW/cmCPackIFWGenerator.h index 1d4d67b..3246861 100644 --- a/Source/CPack/IFW/cmCPackIFWGenerator.h +++ b/Source/CPack/IFW/cmCPackIFWGenerator.h @@ -13,6 +13,7 @@ #ifndef cmCPackIFWGenerator_h #define cmCPackIFWGenerator_h +#include <cmGeneratedFileStream.h> #include <CPack/cmCPackGenerator.h> #include "cmCPackIFWPackage.h" @@ -44,6 +45,21 @@ public: */ virtual ~cmCPackIFWGenerator(); + /** + * Compare \a version with QtIFW framework version + */ + bool IsVersionLess(const char *version); + + /** + * Compare \a version with QtIFW framework version + */ + bool IsVersionGreater(const char *version); + + /** + * Compare \a version with QtIFW framework version + */ + bool IsVersionEqual(const char *version); + protected: // cmCPackGenerator reimplementation /** @@ -105,6 +121,8 @@ protected: // Methods cmCPackIFWPackage* GetGroupPackage(cmCPackComponentGroup *group) const; cmCPackIFWPackage* GetComponentPackage(cmCPackComponent *component) const; + void WriteGeneratedByToStrim(cmGeneratedFileStream& xout); + protected: // Data friend class cmCPackIFWPackage; @@ -126,6 +144,8 @@ protected: // Data private: std::string RepoGen; std::string BinCreator; + std::string FrameworkVersion; + std::string ExecutableSuffix; bool OnlineOnly; bool ResolveDuplicateNames; diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.cxx b/Source/CPack/IFW/cmCPackIFWInstaller.cxx index 4a99e50..8c77a2c 100644 --- a/Source/CPack/IFW/cmCPackIFWInstaller.cxx +++ b/Source/CPack/IFW/cmCPackIFWInstaller.cxx @@ -51,6 +51,25 @@ bool cmCPackIFWInstaller::IsOn(const std::string &op) const } //---------------------------------------------------------------------------- +bool cmCPackIFWInstaller::IsVersionLess(const char *version) +{ + return Generator ? Generator->IsVersionLess(version) : false; +} + +//---------------------------------------------------------------------------- +bool cmCPackIFWInstaller::IsVersionGreater(const char *version) +{ + return Generator ? Generator->IsVersionGreater(version) : false; +} + +//---------------------------------------------------------------------------- +bool cmCPackIFWInstaller::IsVersionEqual(const char *version) +{ + return Generator ? Generator->IsVersionEqual(version) : false; +} + + +//---------------------------------------------------------------------------- void cmCPackIFWInstaller::ConfigureFromOptions() { // Name; @@ -151,6 +170,17 @@ void cmCPackIFWInstaller::ConfigureFromOptions() } } + // Start menu + if (const char* optIFW_START_MENU_DIR = + this->GetOption("CPACK_IFW_PACKAGE_START_MENU_DIRECTORY")) + { + StartMenuDir = optIFW_START_MENU_DIR; + } + else + { + StartMenuDir = Name; + } + // Default target directory for installation if (const char* optIFW_TARGET_DIRECTORY = GetOption("CPACK_IFW_TARGET_DIRECTORY")) @@ -177,7 +207,7 @@ void cmCPackIFWInstaller::ConfigureFromOptions() // Repositories Repositories.clear(); RepositoryStruct Repo; - if (const char *site = this->GetOption("CPACK_DOWNLOAD_SITE")) + if(const char *site = this->GetOption("CPACK_DOWNLOAD_SITE")) { Repo.Url = site; Repositories.push_back(Repo); @@ -245,6 +275,53 @@ void cmCPackIFWInstaller::ConfigureFromOptions() } } } + + // Maintenance tool + if(const char* optIFW_MAINTENANCE_TOOL = + this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_NAME")) + { + MaintenanceToolName = optIFW_MAINTENANCE_TOOL; + } + + // Maintenance tool ini file + if(const char* optIFW_MAINTENANCE_TOOL_INI = + this->GetOption("CPACK_IFW_PACKAGE_MAINTENANCE_TOOL_INI_FILE")) + { + MaintenanceToolIniFile = optIFW_MAINTENANCE_TOOL_INI; + } + + // Allow non-ASCII characters + if(this->GetOption("CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS")) + { + if(IsOn("CPACK_IFW_PACKAGE_ALLOW_NON_ASCII_CHARACTERS")) + { + AllowNonAsciiCharacters = "true"; + } + else + { + AllowNonAsciiCharacters = "false"; + } + } + + // Space in path + if(this->GetOption("CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH")) + { + if(IsOn("CPACK_IFW_PACKAGE_ALLOW_SPACE_IN_PATH")) + { + AllowSpaceInPath = "true"; + } + else + { + AllowSpaceInPath = "false"; + } + } + + // Control script + if(const char* optIFW_CONTROL_SCRIPT = + this->GetOption("CPACK_IFW_PACKAGE_CONTROL_SCRIPT")) + { + ControlScript = optIFW_CONTROL_SCRIPT; + } } //---------------------------------------------------------------------------- @@ -259,7 +336,10 @@ void cmCPackIFWInstaller::GenerateInstallerFile() // Output stream cmGeneratedFileStream xout((Directory + "/config/config.xml").data()); - xout << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << std::endl; + xout << "<?xml version=\"1.0\"?>" << std::endl; + + WriteGeneratedByToStrim(xout); + xout << "<Installer>" << std::endl; xout << " <Name>" << cmXMLSafe(Name).str() << "</Name>" << std::endl; @@ -313,11 +393,20 @@ void cmCPackIFWInstaller::GenerateInstallerFile() xout << " <Logo>" << name << "</Logo>" << std::endl; } + // Start menu + if(!IsVersionLess("2.0")) + { + xout << " <StartMenuDir>" << StartMenuDir + << "</StartMenuDir>" << std::endl; + } + + // Target dir if(!TargetDir.empty()) { xout << " <TargetDir>" << TargetDir << "</TargetDir>" << std::endl; } + // Admin target dir if(!AdminTargetDir.empty()) { xout << " <AdminTargetDir>" << AdminTargetDir @@ -364,11 +453,52 @@ void cmCPackIFWInstaller::GenerateInstallerFile() xout << " </RemoteRepositories>" << std::endl; } - // CPack IFW default policy - xout << " <!-- CPack IFW default policy -->" << std::endl; - xout << " <AllowNonAsciiCharacters>true</AllowNonAsciiCharacters>" - << std::endl; - xout << " <AllowSpaceInPath>true</AllowSpaceInPath>" << std::endl; + // Maintenance tool + if(!IsVersionLess("2.0") && !MaintenanceToolName.empty()) + { + xout << " <MaintenanceToolName>" << MaintenanceToolName + << "</MaintenanceToolName>" << std::endl; + } + + // Maintenance tool ini file + if(!IsVersionLess("2.0") && !MaintenanceToolIniFile.empty()) + { + xout << " <MaintenanceToolIniFile>" << MaintenanceToolIniFile + << "</MaintenanceToolIniFile>" << std::endl; + } + + // Different allows + if(IsVersionLess("2.0")) + { + // CPack IFW default policy + xout << " <!-- CPack IFW default policy for QtIFW less 2.0 -->" + << std::endl; + xout << " <AllowNonAsciiCharacters>true</AllowNonAsciiCharacters>" + << std::endl; + xout << " <AllowSpaceInPath>true</AllowSpaceInPath>" << std::endl; + } + else + { + if(!AllowNonAsciiCharacters.empty()) + { + xout << " <AllowNonAsciiCharacters>" << AllowNonAsciiCharacters + << "</AllowNonAsciiCharacters>" << std::endl; + } + if(!AllowSpaceInPath.empty()) + { + xout << " <AllowAllowSpaceInPath>" << AllowSpaceInPath + << "</AllowSpaceInPath>" << std::endl; + } + } + + // Control script (copy to config dir) + if(!IsVersionLess("2.0") && !ControlScript.empty()) + { + std::string name = cmSystemTools::GetFilenameName(ControlScript); + std::string path = Directory + "/config/" + name; + cmsys::SystemTools::CopyFileIfDifferent(ControlScript.data(), path.data()); + xout << " <ControlScript>" << name << "</ControlScript>" << std::endl; + } xout << "</Installer>" << std::endl; } @@ -402,5 +532,10 @@ void cmCPackIFWInstaller::GeneratePackageFiles() { cmCPackIFWPackage* package = pit->second; package->GeneratePackageFile(); - } + } +} + +void cmCPackIFWInstaller::WriteGeneratedByToStrim(cmGeneratedFileStream &xout) +{ + if(Generator) Generator->WriteGeneratedByToStrim(xout); } diff --git a/Source/CPack/IFW/cmCPackIFWInstaller.h b/Source/CPack/IFW/cmCPackIFWInstaller.h index 5824d33..4cba5b2 100644 --- a/Source/CPack/IFW/cmCPackIFWInstaller.h +++ b/Source/CPack/IFW/cmCPackIFWInstaller.h @@ -13,6 +13,7 @@ #ifndef cmCPackIFWInstaller_h #define cmCPackIFWInstaller_h +#include <cmGeneratedFileStream.h> #include <cmStandardIncludes.h> class cmCPackIFWPackage; @@ -69,17 +70,39 @@ public: // Configuration /// Filename for a logo std::string Logo; + /// Name of the default program group in the Windows Start menu + std::string StartMenuDir; + /// Default target directory for installation std::string TargetDir; /// Default target directory for installation with administrator rights std::string AdminTargetDir; + /// Filename of the generated maintenance tool + std::string MaintenanceToolName; + + /// Filename for the configuration of the generated maintenance tool + std::string MaintenanceToolIniFile; + + /// Set to true if the installation path can contain non-ASCII characters + std::string AllowNonAsciiCharacters; + + /// Set to false if the installation path cannot contain space characters + std::string AllowSpaceInPath; + + /// Filename for a custom installer control script + std::string ControlScript; + public: // Internal implementation const char* GetOption(const std::string& op) const; bool IsOn(const std::string& op) const; + bool IsVersionLess(const char *version); + bool IsVersionGreater(const char *version); + bool IsVersionEqual(const char *version); + void ConfigureFromOptions(); void GenerateInstallerFile(); @@ -90,6 +113,9 @@ public: // Internal implementation PackagesMap Packages; std::vector<RepositoryStruct> Repositories; std::string Directory; + +protected: + void WriteGeneratedByToStrim(cmGeneratedFileStream& xout); }; #endif // cmCPackIFWInstaller_h diff --git a/Source/CPack/IFW/cmCPackIFWPackage.cxx b/Source/CPack/IFW/cmCPackIFWPackage.cxx index 38cef87..5474ad1b 100644 --- a/Source/CPack/IFW/cmCPackIFWPackage.cxx +++ b/Source/CPack/IFW/cmCPackIFWPackage.cxx @@ -132,6 +132,24 @@ bool cmCPackIFWPackage::IsOn(const std::string &op) const } //---------------------------------------------------------------------------- +bool cmCPackIFWPackage::IsVersionLess(const char *version) +{ + return Generator ? Generator->IsVersionLess(version) : false; +} + +//---------------------------------------------------------------------------- +bool cmCPackIFWPackage::IsVersionGreater(const char *version) +{ + return Generator ? Generator->IsVersionGreater(version) : false; +} + +//---------------------------------------------------------------------------- +bool cmCPackIFWPackage::IsVersionEqual(const char *version) +{ + return Generator ? Generator->IsVersionEqual(version) : false; +} + +//---------------------------------------------------------------------------- std::string cmCPackIFWPackage::GetComponentName(cmCPackComponent *component) { if (!component) return ""; @@ -432,6 +450,9 @@ void cmCPackIFWPackage::GeneratePackageFile() cmGeneratedFileStream xout((Directory + "/meta/package.xml").data()); xout << "<?xml version=\"1.0\"?>" << std::endl; + + WriteGeneratedByToStrim(xout); + xout << "<Package>" << std::endl; xout << " <DisplayName>" << DisplayName @@ -538,3 +559,8 @@ void cmCPackIFWPackage::GeneratePackageFile() xout << "</Package>" << std::endl; } + +void cmCPackIFWPackage::WriteGeneratedByToStrim(cmGeneratedFileStream &xout) +{ + if(Generator) Generator->WriteGeneratedByToStrim(xout); +} diff --git a/Source/CPack/IFW/cmCPackIFWPackage.h b/Source/CPack/IFW/cmCPackIFWPackage.h index 9fc9bd0..d2f7927 100644 --- a/Source/CPack/IFW/cmCPackIFWPackage.h +++ b/Source/CPack/IFW/cmCPackIFWPackage.h @@ -14,6 +14,7 @@ #define cmCPackIFWPackage_h #include <cmStandardIncludes.h> +#include <cmGeneratedFileStream.h> class cmCPackComponent; class cmCPackComponentGroup; @@ -107,6 +108,10 @@ public: // Internal implementation const char* GetOption(const std::string& op) const; bool IsOn(const std::string& op) const; + bool IsVersionLess(const char *version); + bool IsVersionGreater(const char *version); + bool IsVersionEqual(const char *version); + std::string GetComponentName(cmCPackComponent *component); void DefaultConfiguration(); @@ -128,6 +133,9 @@ public: // Internal implementation std::set<DependenceStruct*> AlienDependencies; // Patch to package directory std::string Directory; + +protected: + void WriteGeneratedByToStrim(cmGeneratedFileStream& xout); }; #endif // cmCPackIFWPackage_h diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 0137374..5049a3f 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -283,8 +283,6 @@ int cmCPackDebGenerator::PackageFiles() int cmCPackDebGenerator::createDeb() { - const char* cmakeExecutable = this->GetOption("CMAKE_COMMAND"); - // debian-binary file std::string dbfilename; dbfilename += this->GetOption("GEN_WDIR"); @@ -420,15 +418,15 @@ int cmCPackDebGenerator::createDeb() } else if(!strcmp(debian_compression_type, "bzip2")) { compression_suffix = ".bz2"; compression_modifier = "j"; - cmake_tar += "\"" + std::string(cmakeExecutable) + "\" -E "; + cmake_tar += "\"" + cmSystemTools::GetCMakeCommand() + "\" -E "; } else if(!strcmp(debian_compression_type, "gzip")) { compression_suffix = ".gz"; compression_modifier = "z"; - cmake_tar += "\"" + std::string(cmakeExecutable) + "\" -E "; + cmake_tar += "\"" + cmSystemTools::GetCMakeCommand() + "\" -E "; } else if(!strcmp(debian_compression_type, "none")) { compression_suffix = ""; compression_modifier = ""; - cmake_tar += "\"" + std::string(cmakeExecutable) + "\" -E "; + cmake_tar += "\"" + cmSystemTools::GetCMakeCommand() + "\" -E "; } else { cmCPackLogger(cmCPackLog::LOG_ERROR, "Error unrecognized compression type: " @@ -501,7 +499,7 @@ int cmCPackDebGenerator::createDeb() fileIt != packageFiles.end(); ++ fileIt ) { cmd = "\""; - cmd += cmakeExecutable; + cmd += cmSystemTools::GetCMakeCommand(); cmd += "\" -E md5sum \""; cmd += *fileIt; cmd += "\""; diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index e254e9a..bf4df60 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -711,11 +711,12 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( } cmake cm; + cm.SetHomeDirectory(""); + cm.SetHomeOutputDirectory(""); cm.AddCMakePaths(); cm.SetProgressCallback(cmCPackGeneratorProgress, this); - cmGlobalGenerator gg; - gg.SetCMakeInstance(&cm); - cmsys::auto_ptr<cmLocalGenerator> lg(gg.CreateLocalGenerator()); + cmGlobalGenerator gg(&cm); + cmsys::auto_ptr<cmLocalGenerator> lg(gg.MakeLocalGenerator()); cmMakefile *mf = lg->GetMakefile(); std::string realInstallDirectory = tempInstallDirectory; if ( !installSubDirectory.empty() && installSubDirectory != "/" ) diff --git a/Source/CPack/cpack.cxx b/Source/CPack/cpack.cxx index 2207873..c2fe763 100644 --- a/Source/CPack/cpack.cxx +++ b/Source/CPack/cpack.cxx @@ -198,10 +198,11 @@ int main (int argc, char const* const* argv) "Read CPack config file: " << cpackConfigFile << std::endl); cmake cminst; + cminst.SetHomeDirectory(""); + cminst.SetHomeOutputDirectory(""); cminst.GetState()->RemoveUnscriptableCommands(); - cmGlobalGenerator cmgg; - cmgg.SetCMakeInstance(&cminst); - cmsys::auto_ptr<cmLocalGenerator> cmlg(cmgg.CreateLocalGenerator()); + cmGlobalGenerator cmgg(&cminst); + cmsys::auto_ptr<cmLocalGenerator> cmlg(cmgg.MakeLocalGenerator()); cmMakefile* globalMF = cmlg->GetMakefile(); #if defined(__CYGWIN__) globalMF->AddDefinition("CMAKE_LEGACY_CYGWIN_WIN32", "0"); diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx index 586070b..20d303d 100644 --- a/Source/CTest/cmCTestBuildAndTestHandler.cxx +++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx @@ -204,6 +204,8 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) } cmake cm; + cm.SetHomeDirectory(""); + cm.SetHomeOutputDirectory(""); std::string cmakeOutString; cmCTestBuildAndTestCaptureRAII captureRAII(cm, cmakeOutString); static_cast<void>(captureRAII); diff --git a/Source/CTest/cmCTestBuildCommand.cxx b/Source/CTest/cmCTestBuildCommand.cxx index 2b36b0a..27e22c4 100644 --- a/Source/CTest/cmCTestBuildCommand.cxx +++ b/Source/CTest/cmCTestBuildCommand.cxx @@ -141,7 +141,8 @@ cmCTestGenericHandler* cmCTestBuildCommand::InitializeHandler() = this->GlobalGenerator-> GenerateCMakeBuildCommand(cmakeBuildTarget ? cmakeBuildTarget : "", cmakeBuildConfiguration, - cmakeBuildAdditionalFlags ? cmakeBuildAdditionalFlags : "", true); + cmakeBuildAdditionalFlags ? cmakeBuildAdditionalFlags : "", + this->Makefile->IgnoreErrorsCMP0061()); cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "SetMakeCommand:" << buildCommand << "\n", this->Quiet); this->CTest->SetCTestConfiguration("MakeCommand", buildCommand.c_str(), diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx index 29e07ef..e141b60 100644 --- a/Source/CTest/cmCTestBuildHandler.cxx +++ b/Source/CTest/cmCTestBuildHandler.cxx @@ -18,7 +18,7 @@ #include "cmLocalGenerator.h" #include "cmGlobalGenerator.h" #include "cmGeneratedFileStream.h" -#include "cmXMLSafe.h" +#include "cmXMLWriter.h" #include "cmFileTimeComparison.h" #include "cmAlgorithms.h" @@ -68,13 +68,13 @@ static const char* cmCTestErrorMatches[] = { "^CMake Error.*:", ":[ \\t]cannot find", ":[ \\t]can't find", - ": \\*\\*\\* No rule to make target \\[`'].*\\'. Stop", + ": \\*\\*\\* No rule to make target [`'].*\\'. Stop", ": \\*\\*\\* No targets specified and no makefile found", ": Invalid loader fixup for symbol", ": Invalid fixups exist", ": Can't find library for", ": internal link edit command failed", - ": Unrecognized option \\[`'].*\\'", + ": Unrecognized option [`'].*\\'", "\", line [0-9]+\\.[0-9]+: [0-9]+-[0-9]+ \\([^WI]\\)", "ld: 0706-006 Cannot find or open library file: -l ", "ild: \\(argument error\\) can't find library argument ::", @@ -523,16 +523,17 @@ int cmCTestBuildHandler::ProcessHandler() << std::endl); return -1; } - this->GenerateXMLHeader(xofs); + cmXMLWriter xml(xofs); + this->GenerateXMLHeader(xml); if(this->UseCTestLaunch) { - this->GenerateXMLLaunched(xofs); + this->GenerateXMLLaunched(xml); } else { - this->GenerateXMLLogScraped(xofs); + this->GenerateXMLLogScraped(xml); } - this->GenerateXMLFooter(xofs, elapsed_build_time); + this->GenerateXMLFooter(xml, elapsed_build_time); if (res != cmsysProcess_State_Exited || retVal || this->TotalErrors > 0) { @@ -552,17 +553,14 @@ int cmCTestBuildHandler::ProcessHandler() } //---------------------------------------------------------------------------- -void cmCTestBuildHandler::GenerateXMLHeader(std::ostream& os) +void cmCTestBuildHandler::GenerateXMLHeader(cmXMLWriter& xml) { - this->CTest->StartXML(os, this->AppendXML); - os << "<Build>\n" - << "\t<StartDateTime>" << this->StartBuild << "</StartDateTime>\n" - << "\t<StartBuildTime>" << - static_cast<unsigned int>(this->StartBuildTime) - << "</StartBuildTime>\n" - << "<BuildCommand>" - << cmXMLSafe(this->GetMakeCommand()) - << "</BuildCommand>" << std::endl; + this->CTest->StartXML(xml, this->AppendXML); + xml.StartElement("Build"); + xml.Element("StartDateTime", this->StartBuild); + xml.Element("StartBuildTime", + static_cast<unsigned int>(this->StartBuildTime)); + xml.Element("BuildCommand", this->GetMakeCommand()); } //---------------------------------------------------------------------------- @@ -591,7 +589,7 @@ private: }; //---------------------------------------------------------------------------- -void cmCTestBuildHandler::GenerateXMLLaunched(std::ostream& os) +void cmCTestBuildHandler::GenerateXMLLaunched(cmXMLWriter& xml) { if(this->CTestLaunchDir.empty()) { @@ -632,12 +630,12 @@ void cmCTestBuildHandler::GenerateXMLLaunched(std::ostream& os) for(Fragments::const_iterator fi = fragments.begin(); fi != fragments.end(); ++fi) { - this->GenerateXMLLaunchedFragment(os, fi->c_str()); + xml.FragmentFile(fi->c_str()); } } //---------------------------------------------------------------------------- -void cmCTestBuildHandler::GenerateXMLLogScraped(std::ostream& os) +void cmCTestBuildHandler::GenerateXMLLogScraped(cmXMLWriter& xml) { std::vector<cmCTestBuildErrorWarning>& ew = this->ErrorsAndWarnings; std::vector<cmCTestBuildErrorWarning>::iterator it; @@ -665,10 +663,9 @@ void cmCTestBuildHandler::GenerateXMLLogScraped(std::ostream& os) { numWarningsAllowed--; } - os << "\t<" << (cm->Error ? "Error" : "Warning") << ">\n" - << "\t\t<BuildLogLine>" << cm->LogLine << "</BuildLogLine>\n" - << "\t\t<Text>" << cmXMLSafe(cm->Text).Quotes(false) - << "\n</Text>" << std::endl; + xml.StartElement(cm->Error ? "Error" : "Warning"); + xml.Element("BuildLogLine", cm->LogLine); + xml.Element("Text", cm->Text); std::vector<cmCTestCompileErrorWarningRex>::iterator rit; for ( rit = this->ErrorWarningFileLineRegex.begin(); rit != this->ErrorWarningFileLineRegex.end(); ++ rit ) @@ -706,62 +703,48 @@ void cmCTestBuildHandler::GenerateXMLLogScraped(std::ostream& os) { if (!cm->SourceFile.empty()) { - os << "\t\t<SourceFile>" << cm->SourceFile << "</SourceFile>" - << std::endl; + xml.Element("SourceFile", cm->SourceFile); } if (!cm->SourceFileTail.empty()) { - os << "\t\t<SourceFileTail>" << cm->SourceFileTail - << "</SourceFileTail>" << std::endl; + xml.Element("SourceFileTail", cm->SourceFileTail); } if ( cm->LineNumber >= 0 ) { - os << "\t\t<SourceLineNumber>" << cm->LineNumber - << "</SourceLineNumber>" << std::endl; + xml.Element("SourceLineNumber", cm->LineNumber); } } - os << "\t\t<PreContext>" << cmXMLSafe(cm->PreContext).Quotes(false) - << "</PreContext>\n" - << "\t\t<PostContext>" << cmXMLSafe(cm->PostContext).Quotes(false); + xml.Element("PreContext", cm->PreContext); + xml.StartElement("PostContext"); + xml.Content(cm->PostContext); // is this the last warning or error, if so notify if ((cm->Error && !numErrorsAllowed) || (!cm->Error && !numWarningsAllowed)) { - os << "\nThe maximum number of reported warnings or errors has been " - "reached!!!\n"; + xml.Content("\nThe maximum number of reported warnings or errors " + "has been reached!!!\n"); } - os << "</PostContext>\n" - << "\t\t<RepeatCount>0</RepeatCount>\n" - << "</" << (cm->Error ? "Error" : "Warning") << ">\n\n" - << std::endl; + xml.EndElement(); // PostContext + xml.Element("RepeatCount", "0"); + xml.EndElement(); // "Error" / "Warning" } } } //---------------------------------------------------------------------------- -void cmCTestBuildHandler::GenerateXMLFooter(std::ostream& os, +void cmCTestBuildHandler::GenerateXMLFooter(cmXMLWriter& xml, double elapsed_build_time) { - os << "\t<Log Encoding=\"base64\" Compression=\"/bin/gzip\">\n\t</Log>\n" - << "\t<EndDateTime>" << this->EndBuild << "</EndDateTime>\n" - << "\t<EndBuildTime>" << static_cast<unsigned int>(this->EndBuildTime) - << "</EndBuildTime>\n" - << "<ElapsedMinutes>" << static_cast<int>(elapsed_build_time/6)/10.0 - << "</ElapsedMinutes>" - << "</Build>" << std::endl; - this->CTest->EndXML(os); -} - -//---------------------------------------------------------------------------- -void cmCTestBuildHandler::GenerateXMLLaunchedFragment(std::ostream& os, - const char* fname) -{ - cmsys::ifstream fin(fname, std::ios::in | std::ios::binary); - std::string line; - while(cmSystemTools::GetLineFromStream(fin, line)) - { - os << line << "\n"; - } + xml.StartElement("Log"); + xml.Attribute("Encoding", "base64"); + xml.Attribute("Compression", "bin/gzip"); + xml.EndElement(); // Log + + xml.Element("EndDateTime", this->EndBuild); + xml.Element("EndBuildTime", static_cast<unsigned int>(this->EndBuildTime)); + xml.Element("ElapsedMinutes", static_cast<int>(elapsed_build_time/6)/10.0); + xml.EndElement(); // Build + this->CTest->EndXML(xml); } //---------------------------------------------------------------------------- diff --git a/Source/CTest/cmCTestBuildHandler.h b/Source/CTest/cmCTestBuildHandler.h index d13d5cf..2e9b92a 100644 --- a/Source/CTest/cmCTestBuildHandler.h +++ b/Source/CTest/cmCTestBuildHandler.h @@ -22,6 +22,7 @@ #include <deque> class cmMakefile; +class cmXMLWriter; /** \class cmCTestBuildHandler * \brief A class that handles ctest -S invocations @@ -86,11 +87,10 @@ private: }; // generate the XML output - void GenerateXMLHeader(std::ostream& os); - void GenerateXMLLaunched(std::ostream& os); - void GenerateXMLLogScraped(std::ostream& os); - void GenerateXMLFooter(std::ostream& os, double elapsed_build_time); - void GenerateXMLLaunchedFragment(std::ostream& os, const char* fname); + void GenerateXMLHeader(cmXMLWriter& xml); + void GenerateXMLLaunched(cmXMLWriter& xml); + void GenerateXMLLogScraped(cmXMLWriter& xml); + void GenerateXMLFooter(cmXMLWriter& xml, double elapsed_build_time); bool IsLaunchedErrorFile(const char* fname); bool IsLaunchedWarningFile(const char* fname); diff --git a/Source/CTest/cmCTestCVS.cxx b/Source/CTest/cmCTestCVS.cxx index ab363d0..0fb3fec 100644 --- a/Source/CTest/cmCTestCVS.cxx +++ b/Source/CTest/cmCTestCVS.cxx @@ -13,7 +13,7 @@ #include "cmCTest.h" #include "cmSystemTools.h" -#include "cmXMLSafe.h" +#include "cmXMLWriter.h" #include <cmsys/RegularExpression.hxx> #include <cmsys/FStream.hxx> @@ -266,13 +266,13 @@ void cmCTestCVS::LoadRevisions(std::string const& file, } //---------------------------------------------------------------------------- -void cmCTestCVS::WriteXMLDirectory(std::ostream& xml, +void cmCTestCVS::WriteXMLDirectory(cmXMLWriter& xml, std::string const& path, Directory const& dir) { const char* slash = path.empty()? "":"/"; - xml << "\t<Directory>\n" - << "\t\t<Name>" << cmXMLSafe(path) << "</Name>\n"; + xml.StartElement("Directory"); + xml.Element("Name", path); // Lookup the branch checked out in the working tree. std::string branchFlag = this->ComputeBranchFlag(path); @@ -298,11 +298,11 @@ void cmCTestCVS::WriteXMLDirectory(std::ostream& xml, File f(fi->second, &revisions[0], &revisions[1]); this->WriteXMLEntry(xml, path, fi->first, full, f); } - xml << "\t</Directory>\n"; + xml.EndElement(); // Directory } //---------------------------------------------------------------------------- -bool cmCTestCVS::WriteXMLUpdates(std::ostream& xml) +bool cmCTestCVS::WriteXMLUpdates(cmXMLWriter& xml) { cmCTestLog(this->CTest, HANDLER_OUTPUT, " Gathering version information (one . per updated file):\n" diff --git a/Source/CTest/cmCTestCVS.h b/Source/CTest/cmCTestCVS.h index 64e1747..f2c0a73 100644 --- a/Source/CTest/cmCTestCVS.h +++ b/Source/CTest/cmCTestCVS.h @@ -29,7 +29,7 @@ public: private: // Implement cmCTestVC internal API. virtual bool UpdateImpl(); - virtual bool WriteXMLUpdates(std::ostream& xml); + virtual bool WriteXMLUpdates(cmXMLWriter& xml); // Update status for files in each directory. class Directory: public std::map<std::string, PathStatus> {}; @@ -38,7 +38,7 @@ private: std::string ComputeBranchFlag(std::string const& dir); void LoadRevisions(std::string const& file, const char* branchFlag, std::vector<Revision>& revisions); - void WriteXMLDirectory(std::ostream& xml, std::string const& path, + void WriteXMLDirectory(cmXMLWriter& xml, std::string const& path, Directory const& dir); // Parsing helper classes. diff --git a/Source/CTest/cmCTestConfigureHandler.cxx b/Source/CTest/cmCTestConfigureHandler.cxx index 3b444f2..2e8aeb9 100644 --- a/Source/CTest/cmCTestConfigureHandler.cxx +++ b/Source/CTest/cmCTestConfigureHandler.cxx @@ -15,7 +15,7 @@ #include "cmCTest.h" #include "cmGeneratedFileStream.h" #include "cmake.h" -#include "cmXMLSafe.h" +#include "cmXMLWriter.h" #include <cmsys/Process.h> @@ -89,33 +89,22 @@ int cmCTestConfigureHandler::ProcessHandler() if ( os ) { - this->CTest->StartXML(os, this->AppendXML); - os << "<Configure>\n" - << "\t<StartDateTime>" << start_time << "</StartDateTime>" - << std::endl - << "\t<StartConfigureTime>" << start_time_time - << "</StartConfigureTime>\n"; - - if ( res == cmsysProcess_State_Exited && retVal ) - { - os << retVal; - } - os << "<ConfigureCommand>" << cCommand << "</ConfigureCommand>" - << std::endl; + cmXMLWriter xml(os); + this->CTest->StartXML(xml, this->AppendXML); + xml.StartElement("Configure"); + xml.Element("StartDateTime", start_time); + xml.Element("StartConfigureTime", start_time_time); + xml.Element("ConfigureCommand", cCommand); cmCTestOptionalLog(this->CTest, DEBUG, "End" << std::endl, this->Quiet); - os << "<Log>" << cmXMLSafe(output) << "</Log>" << std::endl; - std::string end_time = this->CTest->CurrentTime(); - os << "\t<ConfigureStatus>" << retVal << "</ConfigureStatus>\n" - << "\t<EndDateTime>" << end_time << "</EndDateTime>\n" - << "\t<EndConfigureTime>" << - static_cast<unsigned int>(cmSystemTools::GetTime()) - << "</EndConfigureTime>\n" - << "<ElapsedMinutes>" - << static_cast<int>( - (cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0 - << "</ElapsedMinutes>" - << "</Configure>" << std::endl; - this->CTest->EndXML(os); + xml.Element("Log", output); + xml.Element("ConfigureStatus", retVal); + xml.Element("EndDateTime", this->CTest->CurrentTime()); + xml.Element("EndConfigureTime", + static_cast<unsigned int>(cmSystemTools::GetTime())); + xml.Element("ElapsedMinutes", static_cast<int>( + (cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0); + xml.EndElement(); // Configure + this->CTest->EndXML(xml); } } else diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx index 790e488..f92f19a 100644 --- a/Source/CTest/cmCTestCoverageHandler.cxx +++ b/Source/CTest/cmCTestCoverageHandler.cxx @@ -22,7 +22,7 @@ #include "cmMakefile.h" #include "cmSystemTools.h" #include "cmGeneratedFileStream.h" -#include "cmXMLSafe.h" +#include "cmXMLWriter.h" #include <cmsys/Process.h> #include <cmsys/RegularExpression.hxx> @@ -185,14 +185,6 @@ bool cmCTestCoverageHandler::StartCoverageLogFile( << covLogFilename << std::endl); return false; } - std::string local_start_time = this->CTest->CurrentTime(); - this->CTest->StartXML(covLogFile, this->AppendXML); - covLogFile << "<CoverageLog>" << std::endl - << "\t<StartDateTime>" << local_start_time << "</StartDateTime>" - << "\t<StartTime>" - << static_cast<unsigned int>(cmSystemTools::GetTime()) - << "</StartTime>" - << std::endl; return true; } @@ -200,13 +192,6 @@ bool cmCTestCoverageHandler::StartCoverageLogFile( void cmCTestCoverageHandler::EndCoverageLogFile(cmGeneratedFileStream& ostr, int logFileCount) { - std::string local_end_time = this->CTest->CurrentTime(); - ostr << "\t<EndDateTime>" << local_end_time << "</EndDateTime>" << std::endl - << "\t<EndTime>" << - static_cast<unsigned int>(cmSystemTools::GetTime()) - << "</EndTime>" << std::endl - << "</CoverageLog>" << std::endl; - this->CTest->EndXML(ostr); char covLogFilename[1024]; sprintf(covLogFilename, "CoverageLog-%d.xml", logFileCount); cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Close file: " @@ -215,6 +200,25 @@ void cmCTestCoverageHandler::EndCoverageLogFile(cmGeneratedFileStream& ostr, } //---------------------------------------------------------------------- +void cmCTestCoverageHandler::StartCoverageLogXML(cmXMLWriter& xml) +{ + this->CTest->StartXML(xml, this->AppendXML); + xml.StartElement("CoverageLog"); + xml.Element("StartDateTime", this->CTest->CurrentTime()); + xml.Element("StartTime", + static_cast<unsigned int>(cmSystemTools::GetTime())); +} + +//---------------------------------------------------------------------- +void cmCTestCoverageHandler::EndCoverageLogXML(cmXMLWriter& xml) +{ + xml.Element("EndDateTime", this->CTest->CurrentTime()); + xml.Element("EndTime", static_cast<unsigned int>(cmSystemTools::GetTime())); + xml.EndElement(); // CoverageLog + this->CTest->EndXML(xml); +} + +//---------------------------------------------------------------------- bool cmCTestCoverageHandler::ShouldIDoCoverage(const char* file, const char* srcDir, const char* binDir) @@ -451,6 +455,8 @@ int cmCTestCoverageHandler::ProcessHandler() } cmGeneratedFileStream covSumFile; cmGeneratedFileStream covLogFile; + cmXMLWriter covSumXML(covSumFile); + cmXMLWriter covLogXML(covLogFile); if(!this->StartResultingXML(cmCTest::PartCoverage, "Coverage", covSumFile)) { @@ -458,20 +464,21 @@ int cmCTestCoverageHandler::ProcessHandler() "Cannot open coverage summary file." << std::endl); return -1; } + covSumFile.setf(std::ios::fixed, std::ios::floatfield); + covSumFile.precision(2); - this->CTest->StartXML(covSumFile, this->AppendXML); + this->CTest->StartXML(covSumXML, this->AppendXML); // Produce output xml files - covSumFile << "<Coverage>" << std::endl - << "\t<StartDateTime>" << coverage_start_time << "</StartDateTime>" - << std::endl - << "\t<StartTime>" << coverage_start_time_time << "</StartTime>" - << std::endl; + covSumXML.StartElement("Coverage"); + covSumXML.Element("StartDateTime", coverage_start_time); + covSumXML.Element("StartTime", coverage_start_time_time); int logFileCount = 0; if ( !this->StartCoverageLogFile(covLogFile, logFileCount) ) { return -1; } + this->StartCoverageLogXML(covLogXML); cmCTestCoverageHandlerContainer::TotalCoverageMap::iterator fileIterator; int cnt = 0; long total_tested = 0; @@ -528,12 +535,14 @@ int cmCTestCoverageHandler::ProcessHandler() if ( ++cnt % 100 == 0 ) { + this->EndCoverageLogXML(covLogXML); this->EndCoverageLogFile(covLogFile, logFileCount); logFileCount ++; if ( !this->StartCoverageLogFile(covLogFile, logFileCount) ) { return -1; } + this->StartCoverageLogXML(covLogXML); } const std::string fileName @@ -542,9 +551,10 @@ int cmCTestCoverageHandler::ProcessHandler() this->CTest->GetShortPathToFile(fullFileName.c_str()); const cmCTestCoverageHandlerContainer::SingleFileCoverageVector& fcov = fileIterator->second; - covLogFile << "\t<File Name=\"" << cmXMLSafe(fileName) - << "\" FullPath=\"" << cmXMLSafe(shortFileName) << "\">\n" - << "\t\t<Report>" << std::endl; + covLogXML.StartElement("File"); + covLogXML.Attribute("Name", fileName); + covLogXML.Attribute("FullPath", shortFileName); + covLogXML.StartElement("Report"); cmsys::ifstream ifs(fullFileName.c_str()); if ( !ifs) @@ -576,9 +586,11 @@ int cmCTestCoverageHandler::ProcessHandler() error ++; break; } - covLogFile << "\t\t<Line Number=\"" << cc << "\" Count=\"" << fcov[cc] - << "\">" - << cmXMLSafe(line) << "</Line>" << std::endl; + covLogXML.StartElement("Line"); + covLogXML.Attribute("Number", cc); + covLogXML.Attribute("Count", fcov[cc]); + covLogXML.Content(line); + covLogXML.EndElement(); // Line if ( fcov[cc] == 0 ) { untested ++; @@ -605,24 +617,19 @@ int cmCTestCoverageHandler::ProcessHandler() } total_tested += tested; total_untested += untested; - covLogFile << "\t\t</Report>" << std::endl - << "\t</File>" << std::endl; - covSumFile << "\t<File Name=\"" << cmXMLSafe(fileName) - << "\" FullPath=\"" << cmXMLSafe( - this->CTest->GetShortPathToFile(fullFileName.c_str())) - << "\" Covered=\"" << (tested+untested > 0 ? "true":"false") << "\">\n" - << "\t\t<LOCTested>" << tested << "</LOCTested>\n" - << "\t\t<LOCUnTested>" << untested << "</LOCUnTested>\n" - << "\t\t<PercentCoverage>"; - covSumFile.setf(std::ios::fixed, std::ios::floatfield); - covSumFile.precision(2); - covSumFile << (cper) << "</PercentCoverage>\n" - << "\t\t<CoverageMetric>"; - covSumFile.setf(std::ios::fixed, std::ios::floatfield); - covSumFile.precision(2); - covSumFile << (cmet) << "</CoverageMetric>\n"; - this->WriteXMLLabels(covSumFile, shortFileName); - covSumFile << "\t</File>" << std::endl; + covLogXML.EndElement(); // Report + covLogXML.EndElement(); // File + covSumXML.StartElement("File"); + covSumXML.Attribute("Name", fileName); + covSumXML.Attribute("FullPath", + this->CTest->GetShortPathToFile(fullFileName.c_str())); + covSumXML.Attribute("Covered", tested + untested > 0 ? "true" : "false"); + covSumXML.Element("LOCTested", tested); + covSumXML.Element("LOCUnTested", untested); + covSumXML.Element("PercentCoverage", cper); + covSumXML.Element("CoverageMetric", cmet); + this->WriteXMLLabels(covSumXML, shortFileName); + covSumXML.EndElement(); // File } //Handle all the files in the extra coverage globs that have no cov data @@ -632,9 +639,10 @@ int cmCTestCoverageHandler::ProcessHandler() std::string fileName = cmSystemTools::GetFilenameName(*i); std::string fullPath = cont.SourceDir + "/" + *i; - covLogFile << "\t<File Name=\"" << cmXMLSafe(fileName) - << "\" FullPath=\"" << cmXMLSafe(*i) << "\">\n" - << "\t\t<Report>" << std::endl; + covLogXML.StartElement("File"); + covLogXML.Attribute("Name", fileName); + covLogXML.Attribute("FullPath", *i); + covLogXML.StartElement("Report"); cmsys::ifstream ifs(fullPath.c_str()); if (!ifs) @@ -651,24 +659,30 @@ int cmCTestCoverageHandler::ProcessHandler() "Actually performing coverage for: " << *i << std::endl, this->Quiet); while (cmSystemTools::GetLineFromStream(ifs, line)) { - covLogFile << "\t\t<Line Number=\"" << untested << "\" Count=\"0\">" - << cmXMLSafe(line) << "</Line>" << std::endl; + covLogXML.StartElement("Line"); + covLogXML.Attribute("Number", untested); + covLogXML.Attribute("Count", 0); + covLogXML.Content(line); + covLogXML.EndElement(); // Line untested ++; } - covLogFile << "\t\t</Report>\n\t</File>" << std::endl; + covLogXML.EndElement(); // Report + covLogXML.EndElement(); // File total_untested += untested; - covSumFile << "\t<File Name=\"" << cmXMLSafe(fileName) - << "\" FullPath=\"" << cmXMLSafe(i->c_str()) - << "\" Covered=\"true\">\n" - << "\t\t<LOCTested>0</LOCTested>\n" - << "\t\t<LOCUnTested>" << untested << "</LOCUnTested>\n" - << "\t\t<PercentCoverage>0</PercentCoverage>\n" - << "\t\t<CoverageMetric>0</CoverageMetric>\n"; - this->WriteXMLLabels(covSumFile, *i); - covSumFile << "\t</File>" << std::endl; - } - + covSumXML.StartElement("File"); + covSumXML.Attribute("Name", fileName); + covSumXML.Attribute("FullPath", *i); + covSumXML.Attribute("Covered", "true"); + covSumXML.Element("LOCTested", 0); + covSumXML.Element("LOCUnTested", untested); + covSumXML.Element("PercentCoverage", 0); + covSumXML.Element("CoverageMetric", 0); + this->WriteXMLLabels(covSumXML, *i); + covSumXML.EndElement(); // File + } + + this->EndCoverageLogXML(covLogXML); this->EndCoverageLogFile(covLogFile, logFileCount); if (!errorsWhileAccumulating.empty()) @@ -696,22 +710,17 @@ int cmCTestCoverageHandler::ProcessHandler() std::string end_time = this->CTest->CurrentTime(); - covSumFile << "\t<LOCTested>" << total_tested << "</LOCTested>\n" - << "\t<LOCUntested>" << total_untested << "</LOCUntested>\n" - << "\t<LOC>" << total_lines << "</LOC>\n" - << "\t<PercentCoverage>"; - covSumFile.setf(std::ios::fixed, std::ios::floatfield); - covSumFile.precision(2); - covSumFile << (percent_coverage)<< "</PercentCoverage>\n" - << "\t<EndDateTime>" << end_time << "</EndDateTime>\n" - << "\t<EndTime>" << - static_cast<unsigned int>(cmSystemTools::GetTime()) - << "</EndTime>\n"; - covSumFile << "<ElapsedMinutes>" << - static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0 - << "</ElapsedMinutes>" - << "</Coverage>" << std::endl; - this->CTest->EndXML(covSumFile); + covSumXML.Element("LOCTested", total_tested); + covSumXML.Element("LOCUntested", total_untested); + covSumXML.Element("LOC", total_lines); + covSumXML.Element("PercentCoverage", percent_coverage); + covSumXML.Element("EndDateTime", end_time); + covSumXML.Element("EndTime", + static_cast<unsigned int>(cmSystemTools::GetTime())); + covSumXML.Element("ElapsedMinutes", + static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0); + covSumXML.EndElement(); // Coverage + this->CTest->EndXML(covSumXML); cmCTestLog(this->CTest, HANDLER_OUTPUT, "" << std::endl << "\tCovered LOC: " @@ -1952,11 +1961,13 @@ int cmCTestCoverageHandler::RunBullseyeCoverageBranch( } // create the output stream for the CoverageLog-N.xml file cmGeneratedFileStream covLogFile; + cmXMLWriter covLogXML(covLogFile); int logFileCount = 0; if ( !this->StartCoverageLogFile(covLogFile, logFileCount) ) { return -1; } + this->StartCoverageLogXML(covLogXML); // for each file run covbr on that file to get the coverage // information for that file std::string outputFile; @@ -2009,20 +2020,22 @@ int cmCTestCoverageHandler::RunBullseyeCoverageBranch( // if we are in a valid file close it because a new one started if(valid) { - covLogFile << "\t\t</Report>" << std::endl - << "\t</File>" << std::endl; + covLogXML.EndElement(); // Report + covLogXML.EndElement(); // File } // only allow 100 files in each log file if ( count != 0 && count % 100 == 0 ) { cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "start a new log file: " << count << std::endl, this->Quiet); + this->EndCoverageLogXML(covLogXML); this->EndCoverageLogFile(covLogFile, logFileCount); logFileCount ++; if ( !this->StartCoverageLogFile(covLogFile, logFileCount) ) { return -1; } + this->StartCoverageLogXML(covLogXML); count++; // move on one } std::map<std::string, std::string>::iterator @@ -2036,19 +2049,20 @@ int cmCTestCoverageHandler::RunBullseyeCoverageBranch( "Produce coverage for file: " << file << " " << count << std::endl, this->Quiet); // start the file output - covLogFile << "\t<File Name=\"" - << cmXMLSafe(i->first) - << "\" FullPath=\"" << cmXMLSafe( - this->CTest->GetShortPathToFile( - i->second.c_str())) << "\">" << std::endl - << "\t\t<Report>" << std::endl; + covLogXML.StartElement("File"); + covLogXML.Attribute("Name", i->first); + covLogXML.Attribute("FullPath", + this->CTest->GetShortPathToFile(i->second.c_str())); + covLogXML.StartElement("Report"); // write the bullseye header line =0; for(int k =0; bullseyeHelp[k] != 0; ++k) { - covLogFile << "\t\t<Line Number=\"" << line << "\" Count=\"-1\">" - << cmXMLSafe(bullseyeHelp[k]) - << "</Line>" << std::endl; + covLogXML.StartElement("Line"); + covLogXML.Attribute("Number", line); + covLogXML.Attribute("Count", -1); + covLogXML.Content(bullseyeHelp[k]); + covLogXML.EndElement(); // Line line++; } valid = true; // we are in a valid file section @@ -2062,18 +2076,21 @@ int cmCTestCoverageHandler::RunBullseyeCoverageBranch( // we are not at a start file, and we are in a valid file output the line else if(valid) { - covLogFile << "\t\t<Line Number=\"" << line << "\" Count=\"-1\">" - << cmXMLSafe(lineIn) - << "</Line>" << std::endl; + covLogXML.StartElement("Line"); + covLogXML.Attribute("Number", line); + covLogXML.Attribute("Count", -1); + covLogXML.Content(lineIn); + covLogXML.EndElement(); // Line line++; } } // if we ran out of lines a valid file then close that file if(valid) { - covLogFile << "\t\t</Report>" << std::endl - << "\t</File>" << std::endl; + covLogXML.EndElement(); // Report + covLogXML.EndElement(); // File } + this->EndCoverageLogXML(covLogXML); this->EndCoverageLogFile(covLogFile, logFileCount); return 1; } @@ -2143,23 +2160,20 @@ int cmCTestCoverageHandler::RunBullseyeSourceSummary( std::ostream& tmpLog = *cont->OFS; // copen the Coverage.xml file in the Testing directory cmGeneratedFileStream covSumFile; + cmXMLWriter xml(covSumFile); if(!this->StartResultingXML(cmCTest::PartCoverage, "Coverage", covSumFile)) { cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot open coverage summary file." << std::endl); return 0; } - this->CTest->StartXML(covSumFile, this->AppendXML); + this->CTest->StartXML(xml, this->AppendXML); double elapsed_time_start = cmSystemTools::GetTime(); std::string coverage_start_time = this->CTest->CurrentTime(); - covSumFile << "<Coverage>" << std::endl - << "\t<StartDateTime>" - << coverage_start_time << "</StartDateTime>" - << std::endl - << "\t<StartTime>" - << static_cast<unsigned int>(cmSystemTools::GetTime()) - << "</StartTime>" - << std::endl; + xml.StartElement("Coverage"); + xml.Element("StartDateTime", coverage_start_time); + xml.Element("StartTime", + static_cast<unsigned int>(cmSystemTools::GetTime())); std::string stdline; std::string errline; // expected output: @@ -2271,58 +2285,35 @@ int cmCTestCoverageHandler::RunBullseyeSourceSummary( tmpLog << "percentBranch: " << percentBranch << "\n"; tmpLog << "percentCoverage: " << percent_coverage << "\n"; tmpLog << "coverage metric: " << cmet << "\n"; - covSumFile << "\t<File Name=\"" << cmXMLSafe(sourceFile) - << "\" FullPath=\"" << cmXMLSafe(shortFileName) - << "\" Covered=\"" << (cmet>0?"true":"false") << "\">\n" - << "\t\t<BranchesTested>" - << branchCovered - << "</BranchesTested>\n" - << "\t\t<BranchesUnTested>" - << totalBranches - branchCovered - << "</BranchesUnTested>\n" - << "\t\t<FunctionsTested>" - << functionsCalled - << "</FunctionsTested>\n" - << "\t\t<FunctionsUnTested>" - << totalFunctions - functionsCalled - << "</FunctionsUnTested>\n" - // Hack for conversion of function to loc assume a function - // has 100 lines of code - << "\t\t<LOCTested>" << functionsCalled *100 - << "</LOCTested>\n" - << "\t\t<LOCUnTested>" - << (totalFunctions - functionsCalled)*100 - << "</LOCUnTested>\n" - << "\t\t<PercentCoverage>"; - covSumFile.setf(std::ios::fixed, std::ios::floatfield); - covSumFile.precision(2); - covSumFile << (cper) << "</PercentCoverage>\n" - << "\t\t<CoverageMetric>"; - covSumFile.setf(std::ios::fixed, std::ios::floatfield); - covSumFile.precision(2); - covSumFile << (cmet) << "</CoverageMetric>\n"; - this->WriteXMLLabels(covSumFile, shortFileName); - covSumFile << "\t</File>" << std::endl; + xml.StartElement("File"); + xml.Attribute("Name", sourceFile); + xml.Attribute("FullPath", shortFileName); + xml.Attribute("Covered", cmet > 0 ? "true" : "false"); + xml.Element("BranchesTested", branchCovered); + xml.Element("BranchesUnTested", totalBranches - branchCovered); + xml.Element("FunctionsTested", functionsCalled); + xml.Element("FunctionsUnTested", totalFunctions - functionsCalled); + // Hack for conversion of function to loc assume a function + // has 100 lines of code + xml.Element("LOCTested", functionsCalled * 100); + xml.Element("LOCUnTested", (totalFunctions - functionsCalled) * 100); + xml.Element("PercentCoverage", cper); + xml.Element("CoverageMetric", cmet); + this->WriteXMLLabels(xml, shortFileName); + xml.EndElement(); // File } } std::string end_time = this->CTest->CurrentTime(); - covSumFile << "\t<LOCTested>" << total_tested << "</LOCTested>\n" - << "\t<LOCUntested>" << total_untested << "</LOCUntested>\n" - << "\t<LOC>" << total_functions << "</LOC>\n" - << "\t<PercentCoverage>"; - covSumFile.setf(std::ios::fixed, std::ios::floatfield); - covSumFile.precision(2); - covSumFile - << SAFEDIV(percent_coverage,number_files)<< "</PercentCoverage>\n" - << "\t<EndDateTime>" << end_time << "</EndDateTime>\n" - << "\t<EndTime>" << static_cast<unsigned int>(cmSystemTools::GetTime()) - << "</EndTime>\n"; - covSumFile - << "<ElapsedMinutes>" << - static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0 - << "</ElapsedMinutes>" - << "</Coverage>" << std::endl; - this->CTest->EndXML(covSumFile); + xml.Element("LOCTested", total_tested); + xml.Element("LOCUntested", total_untested); + xml.Element("LOC", total_functions); + xml.Element("PercentCoverage", SAFEDIV(percent_coverage, number_files)); + xml.Element("EndDateTime", end_time); + xml.Element("EndTime", static_cast<unsigned int>(cmSystemTools::GetTime())); + xml.Element("ElapsedMinutes", + static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0); + xml.EndElement(); // Coverage + this->CTest->EndXML(xml); // Now create the coverage information for each file return this->RunBullseyeCoverageBranch(cont, @@ -2514,19 +2505,19 @@ void cmCTestCoverageHandler::LoadLabels(const char* dir) } //---------------------------------------------------------------------- -void cmCTestCoverageHandler::WriteXMLLabels(std::ostream& os, +void cmCTestCoverageHandler::WriteXMLLabels(cmXMLWriter& xml, std::string const& source) { LabelMapType::const_iterator li = this->SourceLabels.find(source); if(li != this->SourceLabels.end() && !li->second.empty()) { - os << "\t\t<Labels>\n"; + xml.StartElement("Labels"); for(LabelSet::const_iterator lsi = li->second.begin(); lsi != li->second.end(); ++lsi) { - os << "\t\t\t<Label>" << cmXMLSafe(this->Labels[*lsi]) << "</Label>\n"; + xml.Element("Label", this->Labels[*lsi]); } - os << "\t\t</Labels>\n"; + xml.EndElement(); // Labels } } diff --git a/Source/CTest/cmCTestCoverageHandler.h b/Source/CTest/cmCTestCoverageHandler.h index 3258ddb..2ca123a 100644 --- a/Source/CTest/cmCTestCoverageHandler.h +++ b/Source/CTest/cmCTestCoverageHandler.h @@ -20,6 +20,7 @@ #include <cmsys/RegularExpression.hxx> class cmGeneratedFileStream; +class cmXMLWriter; class cmCTestCoverageHandlerContainer { public: @@ -65,6 +66,9 @@ private: bool StartCoverageLogFile(cmGeneratedFileStream& ostr, int logFileCount); void EndCoverageLogFile(cmGeneratedFileStream& ostr, int logFileCount); + void StartCoverageLogXML(cmXMLWriter& xml); + void EndCoverageLogXML(cmXMLWriter& xml); + //! Handle coverage using GCC's GCov int HandleGCovCoverage(cmCTestCoverageHandlerContainer* cont); void FindGCovFiles(std::vector<std::string>& files); @@ -146,7 +150,7 @@ private: // Label reading and writing methods. void LoadLabels(); void LoadLabels(const char* dir); - void WriteXMLLabels(std::ostream& os, std::string const& source); + void WriteXMLLabels(cmXMLWriter& xml, std::string const& source); // Label-based filtering. std::set<int> LabelFilter; diff --git a/Source/CTest/cmCTestGlobalVC.cxx b/Source/CTest/cmCTestGlobalVC.cxx index 5f570b5..c091ec4 100644 --- a/Source/CTest/cmCTestGlobalVC.cxx +++ b/Source/CTest/cmCTestGlobalVC.cxx @@ -13,7 +13,7 @@ #include "cmCTest.h" #include "cmSystemTools.h" -#include "cmXMLSafe.h" +#include "cmXMLWriter.h" #include <cmsys/RegularExpression.hxx> @@ -91,36 +91,36 @@ void cmCTestGlobalVC::DoModification(PathStatus status, } //---------------------------------------------------------------------------- -void cmCTestGlobalVC::WriteXMLDirectory(std::ostream& xml, +void cmCTestGlobalVC::WriteXMLDirectory(cmXMLWriter& xml, std::string const& path, Directory const& dir) { const char* slash = path.empty()? "":"/"; - xml << "\t<Directory>\n" - << "\t\t<Name>" << cmXMLSafe(path) << "</Name>\n"; + xml.StartElement("Directory"); + xml.Element("Name", path); for(Directory::const_iterator fi = dir.begin(); fi != dir.end(); ++fi) { std::string full = path + slash + fi->first; this->WriteXMLEntry(xml, path, fi->first, full, fi->second); } - xml << "\t</Directory>\n"; + xml.EndElement(); // Directory } //---------------------------------------------------------------------------- -void cmCTestGlobalVC::WriteXMLGlobal(std::ostream& xml) +void cmCTestGlobalVC::WriteXMLGlobal(cmXMLWriter& xml) { if(!this->NewRevision.empty()) { - xml << "\t<Revision>" << this->NewRevision << "</Revision>\n"; + xml.Element("Revision", this->NewRevision); } if(!this->OldRevision.empty() && this->OldRevision != this->NewRevision) { - xml << "\t<PriorRevision>" << this->OldRevision << "</PriorRevision>\n"; + xml.Element("PriorRevision", this->OldRevision); } } //---------------------------------------------------------------------------- -bool cmCTestGlobalVC::WriteXMLUpdates(std::ostream& xml) +bool cmCTestGlobalVC::WriteXMLUpdates(cmXMLWriter& xml) { cmCTestLog(this->CTest, HANDLER_OUTPUT, " Gathering version information (one . per revision):\n" diff --git a/Source/CTest/cmCTestGlobalVC.h b/Source/CTest/cmCTestGlobalVC.h index 29e0a61..d0e9410 100644 --- a/Source/CTest/cmCTestGlobalVC.h +++ b/Source/CTest/cmCTestGlobalVC.h @@ -30,7 +30,7 @@ public: protected: // Implement cmCTestVC internal API. - virtual bool WriteXMLUpdates(std::ostream& xml); + virtual bool WriteXMLUpdates(cmXMLWriter& xml); /** Represent a vcs-reported action for one path in a revision. */ struct Change @@ -62,8 +62,8 @@ protected: virtual void LoadModifications() = 0; virtual void LoadRevisions() = 0; - virtual void WriteXMLGlobal(std::ostream& xml); - void WriteXMLDirectory(std::ostream& xml, std::string const& path, + virtual void WriteXMLGlobal(cmXMLWriter& xml); + void WriteXMLDirectory(cmXMLWriter& xml, std::string const& path, Directory const& dir); }; diff --git a/Source/CTest/cmCTestLaunch.cxx b/Source/CTest/cmCTestLaunch.cxx index de6ecde..0f588c5 100644 --- a/Source/CTest/cmCTestLaunch.cxx +++ b/Source/CTest/cmCTestLaunch.cxx @@ -13,7 +13,7 @@ #include "cmGeneratedFileStream.h" #include "cmSystemTools.h" -#include "cmXMLSafe.h" +#include "cmXMLWriter.h" #include "cmake.h" #include <cmsys/MD5.h> @@ -407,35 +407,32 @@ void cmCTestLaunch::WriteXML() // Use cmGeneratedFileStream to atomically create the report file. cmGeneratedFileStream fxml(logXML.c_str()); - fxml << "\t<Failure type=\"" - << (this->IsError()? "Error" : "Warning") << "\">\n"; - this->WriteXMLAction(fxml); - this->WriteXMLCommand(fxml); - this->WriteXMLResult(fxml); - this->WriteXMLLabels(fxml); - fxml << "\t</Failure>\n"; + cmXMLWriter xml(fxml, 2); + xml.StartElement("Failure"); + xml.Attribute("type", this->IsError() ? "Error" : "Warning"); + this->WriteXMLAction(xml); + this->WriteXMLCommand(xml); + this->WriteXMLResult(xml); + this->WriteXMLLabels(xml); + xml.EndElement(); // Failure } //---------------------------------------------------------------------------- -void cmCTestLaunch::WriteXMLAction(std::ostream& fxml) +void cmCTestLaunch::WriteXMLAction(cmXMLWriter& xml) { - fxml << "\t\t<!-- Meta-information about the build action -->\n"; - fxml << "\t\t<Action>\n"; + xml.Comment("Meta-information about the build action"); + xml.StartElement("Action"); // TargetName if(!this->OptionTargetName.empty()) { - fxml << "\t\t\t<TargetName>" - << cmXMLSafe(this->OptionTargetName) - << "</TargetName>\n"; + xml.Element("TargetName", this->OptionTargetName); } // Language if(!this->OptionLanguage.empty()) { - fxml << "\t\t\t<Language>" - << cmXMLSafe(this->OptionLanguage) - << "</Language>\n"; + xml.Element("Language", this->OptionLanguage); } // SourceFile @@ -454,17 +451,13 @@ void cmCTestLaunch::WriteXMLAction(std::ostream& fxml) source.c_str()); } - fxml << "\t\t\t<SourceFile>" - << cmXMLSafe(source) - << "</SourceFile>\n"; + xml.Element("SourceFile", source); } // OutputFile if(!this->OptionOutput.empty()) { - fxml << "\t\t\t<OutputFile>" - << cmXMLSafe(this->OptionOutput) - << "</OutputFile>\n"; + xml.Element("OutputFile", this->OptionOutput); } // OutputType @@ -494,103 +487,94 @@ void cmCTestLaunch::WriteXMLAction(std::ostream& fxml) } if(outputType) { - fxml << "\t\t\t<OutputType>" - << cmXMLSafe(outputType) - << "</OutputType>\n"; + xml.Element("OutputType", outputType); } - fxml << "\t\t</Action>\n"; + xml.EndElement(); // Action } //---------------------------------------------------------------------------- -void cmCTestLaunch::WriteXMLCommand(std::ostream& fxml) +void cmCTestLaunch::WriteXMLCommand(cmXMLWriter& xml) { - fxml << "\n"; - fxml << "\t\t<!-- Details of command -->\n"; - fxml << "\t\t<Command>\n"; + xml.Comment("Details of command"); + xml.StartElement("Command"); if(!this->CWD.empty()) { - fxml << "\t\t\t<WorkingDirectory>" - << cmXMLSafe(this->CWD) - << "</WorkingDirectory>\n"; + xml.Element("WorkingDirectory", this->CWD); } for(std::vector<std::string>::const_iterator ai = this->RealArgs.begin(); ai != this->RealArgs.end(); ++ai) { - fxml << "\t\t\t<Argument>" - << cmXMLSafe(ai->c_str()) - << "</Argument>\n"; + xml.Element("Argument", *ai); } - fxml << "\t\t</Command>\n"; + xml.EndElement(); // Command } //---------------------------------------------------------------------------- -void cmCTestLaunch::WriteXMLResult(std::ostream& fxml) +void cmCTestLaunch::WriteXMLResult(cmXMLWriter& xml) { - fxml << "\n"; - fxml << "\t\t<!-- Result of command -->\n"; - fxml << "\t\t<Result>\n"; + xml.Comment("Result of command"); + xml.StartElement("Result"); // StdOut - fxml << "\t\t\t<StdOut>"; - this->DumpFileToXML(fxml, this->LogOut); - fxml << "</StdOut>\n"; + xml.StartElement("StdOut"); + this->DumpFileToXML(xml, this->LogOut); + xml.EndElement(); // StdOut // StdErr - fxml << "\t\t\t<StdErr>"; - this->DumpFileToXML(fxml, this->LogErr); - fxml << "</StdErr>\n"; + xml.StartElement("StdErr"); + this->DumpFileToXML(xml, this->LogErr); + xml.EndElement(); // StdErr // ExitCondition - fxml << "\t\t\t<ExitCondition>"; + xml.StartElement("ExitCondition"); cmsysProcess* cp = this->Process; switch (cmsysProcess_GetState(cp)) { case cmsysProcess_State_Starting: - fxml << "No process has been executed"; break; + xml.Content("No process has been executed"); break; case cmsysProcess_State_Executing: - fxml << "The process is still executing"; break; + xml.Content("The process is still executing"); break; case cmsysProcess_State_Disowned: - fxml << "Disowned"; break; + xml.Content("Disowned"); break; case cmsysProcess_State_Killed: - fxml << "Killed by parent"; break; + xml.Content("Killed by parent"); break; case cmsysProcess_State_Expired: - fxml << "Killed when timeout expired"; break; + xml.Content("Killed when timeout expired"); break; case cmsysProcess_State_Exited: - fxml << this->ExitCode; break; + xml.Content(this->ExitCode); break; case cmsysProcess_State_Exception: - fxml << "Terminated abnormally: " - << cmXMLSafe(cmsysProcess_GetExceptionString(cp)); break; + xml.Content("Terminated abnormally: "); + xml.Content(cmsysProcess_GetExceptionString(cp)); break; case cmsysProcess_State_Error: - fxml << "Error administrating child process: " - << cmXMLSafe(cmsysProcess_GetErrorString(cp)); break; + xml.Content("Error administrating child process: "); + xml.Content(cmsysProcess_GetErrorString(cp)); break; }; - fxml << "</ExitCondition>\n"; + xml.EndElement(); // ExitCondition - fxml << "\t\t</Result>\n"; + xml.EndElement(); // Result } //---------------------------------------------------------------------------- -void cmCTestLaunch::WriteXMLLabels(std::ostream& fxml) +void cmCTestLaunch::WriteXMLLabels(cmXMLWriter& xml) { this->LoadLabels(); if(!this->Labels.empty()) { - fxml << "\n"; - fxml << "\t\t<!-- Interested parties -->\n"; - fxml << "\t\t<Labels>\n"; + xml.Comment("Interested parties"); + xml.StartElement("Labels"); for(std::set<std::string>::const_iterator li = this->Labels.begin(); li != this->Labels.end(); ++li) { - fxml << "\t\t\t<Label>" << cmXMLSafe(*li) << "</Label>\n"; + xml.Element("Label", *li); } - fxml << "\t\t</Labels>\n"; + xml.EndElement(); // Labels } } //---------------------------------------------------------------------------- -void cmCTestLaunch::DumpFileToXML(std::ostream& fxml, +void cmCTestLaunch::DumpFileToXML(cmXMLWriter& xml, std::string const& fname) { cmsys::ifstream fin(fname.c_str(), std::ios::in | std::ios::binary); @@ -605,7 +589,8 @@ void cmCTestLaunch::DumpFileToXML(std::ostream& fxml, continue; } - fxml << sep << cmXMLSafe(line).Quotes(false); + xml.Content(sep); + xml.Content(line); sep = "\n"; } } @@ -750,9 +735,10 @@ int cmCTestLaunch::Main(int argc, const char* const argv[]) void cmCTestLaunch::LoadConfig() { cmake cm; - cmGlobalGenerator gg; - gg.SetCMakeInstance(&cm); - cmsys::auto_ptr<cmLocalGenerator> lg(gg.CreateLocalGenerator()); + cm.SetHomeDirectory(""); + cm.SetHomeOutputDirectory(""); + cmGlobalGenerator gg(&cm); + cmsys::auto_ptr<cmLocalGenerator> lg(gg.MakeLocalGenerator()); cmMakefile* mf = lg->GetMakefile(); std::string fname = this->LogDir; fname += "CTestLaunchConfig.cmake"; diff --git a/Source/CTest/cmCTestLaunch.h b/Source/CTest/cmCTestLaunch.h index bc90d28..b13e484 100644 --- a/Source/CTest/cmCTestLaunch.h +++ b/Source/CTest/cmCTestLaunch.h @@ -15,6 +15,8 @@ #include "cmStandardIncludes.h" #include <cmsys/RegularExpression.hxx> +class cmXMLWriter; + /** \class cmCTestLaunch * \brief Launcher for make rules to report results for ctest * @@ -92,11 +94,11 @@ private: // Methods to generate the xml fragment. void WriteXML(); - void WriteXMLAction(std::ostream& fxml); - void WriteXMLCommand(std::ostream& fxml); - void WriteXMLResult(std::ostream& fxml); - void WriteXMLLabels(std::ostream& fxml); - void DumpFileToXML(std::ostream& fxml, std::string const& fname); + void WriteXMLAction(cmXMLWriter& xml); + void WriteXMLCommand(cmXMLWriter& xml); + void WriteXMLResult(cmXMLWriter& xml); + void WriteXMLLabels(cmXMLWriter& xml); + void DumpFileToXML(cmXMLWriter& xml, std::string const& fname); // Configuration void LoadConfig(); diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx index 061f3fd..8f26716 100644 --- a/Source/CTest/cmCTestMemCheckHandler.cxx +++ b/Source/CTest/cmCTestMemCheckHandler.cxx @@ -21,7 +21,7 @@ #include <cmsys/Glob.hxx> #include <cmsys/FStream.hxx> #include "cmMakefile.h" -#include "cmXMLSafe.h" +#include "cmXMLWriter.h" #include <stdlib.h> #include <math.h> @@ -352,55 +352,52 @@ void cmCTestMemCheckHandler::PopulateCustomVectors(cmMakefile *mf) } //---------------------------------------------------------------------- -void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os) +void cmCTestMemCheckHandler::GenerateDartOutput(cmXMLWriter& xml) { if ( !this->CTest->GetProduceXML() ) { return; } - this->CTest->StartXML(os, this->AppendXML); - os << "<DynamicAnalysis Checker=\""; + this->CTest->StartXML(xml, this->AppendXML); + xml.StartElement("DynamicAnalysis"); switch ( this->MemoryTesterStyle ) { case cmCTestMemCheckHandler::VALGRIND: - os << "Valgrind"; + xml.Attribute("Checker", "Valgrind"); break; case cmCTestMemCheckHandler::PURIFY: - os << "Purify"; + xml.Attribute("Checker", "Purify"); break; case cmCTestMemCheckHandler::BOUNDS_CHECKER: - os << "BoundsChecker"; + xml.Attribute("Checker", "BoundsChecker"); break; case cmCTestMemCheckHandler::ADDRESS_SANITIZER: - os << "AddressSanitizer"; + xml.Attribute("Checker", "AddressSanitizer"); break; case cmCTestMemCheckHandler::THREAD_SANITIZER: - os << "ThreadSanitizer"; + xml.Attribute("Checker", "ThreadSanitizer"); break; case cmCTestMemCheckHandler::MEMORY_SANITIZER: - os << "MemorySanitizer"; + xml.Attribute("Checker", "MemorySanitizer"); break; case cmCTestMemCheckHandler::UB_SANITIZER: - os << "UndefinedBehaviorSanitizer"; + xml.Attribute("Checker", "UndefinedBehaviorSanitizer"); break; default: - os << "Unknown"; + xml.Attribute("Checker", "Unknown"); } - os << "\">" << std::endl; - os << "\t<StartDateTime>" << this->StartTest << "</StartDateTime>\n" - << "\t<StartTestTime>" << this->StartTestTime << "</StartTestTime>\n" - << "\t<TestList>\n"; + xml.Element("StartDateTime", this->StartTest); + xml.Element("StartTestTime", this->StartTestTime); + xml.StartElement("TestList"); cmCTestMemCheckHandler::TestResultsVector::size_type cc; for ( cc = 0; cc < this->TestResults.size(); cc ++ ) { cmCTestTestResult *result = &this->TestResults[cc]; std::string testPath = result->Path + "/" + result->Name; - os << "\t\t<Test>" << cmXMLSafe( - this->CTest->GetShortPathToFile(testPath.c_str())) - << "</Test>" << std::endl; + xml.Element("Test", this->CTest->GetShortPathToFile(testPath.c_str())); } - os << "\t</TestList>\n"; + xml.EndElement(); // TestList cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "-- Processing memory checking output: ", this->Quiet); size_t total = this->TestResults.size(); @@ -419,37 +416,33 @@ void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os) } this->CleanTestOutput(memcheckstr, static_cast<size_t>(this->CustomMaximumFailedTestOutputSize)); - this->WriteTestResultHeader(os, result); - os << "\t\t<Results>" << std::endl; + this->WriteTestResultHeader(xml, result); + xml.StartElement("Results"); for(std::vector<int>::size_type kk = 0; kk < memcheckresults.size(); ++kk) { if ( memcheckresults[kk] ) { - os << "\t\t\t<Defect type=\"" << this->ResultStringsLong[kk] - << "\">" - << memcheckresults[kk] - << "</Defect>" << std::endl; + xml.StartElement("Defect"); + xml.Attribute("type", this->ResultStringsLong[kk]); + xml.Content(memcheckresults[kk]); + xml.EndElement(); // Defect } this->GlobalResults[kk] += memcheckresults[kk]; } + xml.EndElement(); // Results - std::string logTag; + xml.StartElement("Log"); if(this->CTest->ShouldCompressMemCheckOutput()) { this->CTest->CompressString(memcheckstr); - logTag = "\t<Log compression=\"gzip\" encoding=\"base64\">\n"; - } - else - { - logTag = "\t<Log>\n"; + xml.Attribute("compression", "gzip"); + xml.Attribute("encoding", "base64"); } + xml.Content(memcheckstr); + xml.EndElement(); // Log - os - << "\t\t</Results>\n" - << logTag << cmXMLSafe(memcheckstr) << std::endl - << "\t</Log>\n"; - this->WriteTestResultFooter(os, result); + this->WriteTestResultFooter(xml, result); if ( current < cc ) { cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "#" << std::flush, @@ -460,7 +453,7 @@ void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os) cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, std::endl, this->Quiet); cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "Memory checking results:" << std::endl, this->Quiet); - os << "\t<DefectList>" << std::endl; + xml.StartElement("DefectList"); for ( cc = 0; cc < this->GlobalResults.size(); cc ++ ) { if ( this->GlobalResults[cc] ) @@ -473,21 +466,20 @@ void cmCTestMemCheckHandler::GenerateDartOutput(std::ostream& os) cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, this->ResultStringsLong[cc] << " - " << this->GlobalResults[cc] << std::endl, this->Quiet); - os << "\t\t<Defect Type=\"" << this->ResultStringsLong[cc] - << "\"/>" << std::endl; + xml.StartElement("Defect"); + xml.Attribute("Type", this->ResultStringsLong[cc]); + xml.EndElement(); } } - os << "\t</DefectList>" << std::endl; + xml.EndElement(); // DefectList - os << "\t<EndDateTime>" << this->EndTest << "</EndDateTime>" << std::endl; - os << "\t<EndTestTime>" << this->EndTestTime - << "</EndTestTime>" << std::endl; - os << "<ElapsedMinutes>" - << static_cast<int>(this->ElapsedTestingTime/6)/10.0 - << "</ElapsedMinutes>\n"; + xml.Element("EndDateTime", this->EndTest); + xml.Element("EndTestTime", this->EndTestTime); + xml.Element("ElapsedMinutes", + static_cast<int>(this->ElapsedTestingTime/6)/10.0); - os << "</DynamicAnalysis>" << std::endl; - this->CTest->EndXML(os); + xml.EndElement(); // DynamicAnalysis + this->CTest->EndXML(xml); } //---------------------------------------------------------------------- diff --git a/Source/CTest/cmCTestMemCheckHandler.h b/Source/CTest/cmCTestMemCheckHandler.h index 69fdd9f..f1ac794 100644 --- a/Source/CTest/cmCTestMemCheckHandler.h +++ b/Source/CTest/cmCTestMemCheckHandler.h @@ -21,6 +21,7 @@ #include <string> class cmMakefile; +class cmXMLWriter; /** \class cmCTestMemCheckHandler * \brief A class that handles ctest -S invocations @@ -119,7 +120,7 @@ private: /** * Generate the Dart compatible output */ - void GenerateDartOutput(std::ostream& os); + void GenerateDartOutput(cmXMLWriter& xml); std::vector<std::string> CustomPreMemCheck; std::vector<std::string> CustomPostMemCheck; diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index d7da2b4..d9e4bd4 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -607,7 +607,7 @@ void cmCTestRunTest::DartProcessing() { if (this->TestHandler->DartStuff.find(this->ProcessOutput.c_str())) { - std::string dartString = this->TestHandler->DartStuff.match(1); + this->TestResult.DartString = this->TestHandler->DartStuff.match(1); // keep searching and replacing until none are left while (this->TestHandler->DartStuff1.find(this->ProcessOutput.c_str())) { @@ -615,8 +615,6 @@ void cmCTestRunTest::DartProcessing() cmSystemTools::ReplaceString(this->ProcessOutput, this->TestHandler->DartStuff1.match(1).c_str(), ""); } - this->TestResult.RegressionImages - = this->TestHandler->GenerateRegressionImages(dartString); } } } diff --git a/Source/CTest/cmCTestSVN.cxx b/Source/CTest/cmCTestSVN.cxx index 86dc2f2..f7bd1f9 100644 --- a/Source/CTest/cmCTestSVN.cxx +++ b/Source/CTest/cmCTestSVN.cxx @@ -14,7 +14,7 @@ #include "cmCTest.h" #include "cmSystemTools.h" #include "cmXMLParser.h" -#include "cmXMLSafe.h" +#include "cmXMLWriter.h" #include <cmsys/RegularExpression.hxx> @@ -535,11 +535,11 @@ void cmCTestSVN::LoadModifications() } //---------------------------------------------------------------------------- -void cmCTestSVN::WriteXMLGlobal(std::ostream& xml) +void cmCTestSVN::WriteXMLGlobal(cmXMLWriter& xml) { this->cmCTestGlobalVC::WriteXMLGlobal(xml); - xml << "\t<SVNPath>" << this->RootInfo->Base << "</SVNPath>\n"; + xml.Element("SVNPath", this->RootInfo->Base); } //---------------------------------------------------------------------------- diff --git a/Source/CTest/cmCTestSVN.h b/Source/CTest/cmCTestSVN.h index 17bf7cb..f9febc5 100644 --- a/Source/CTest/cmCTestSVN.h +++ b/Source/CTest/cmCTestSVN.h @@ -84,7 +84,7 @@ private: void DoRevisionSVN(Revision const& revision, std::vector<Change> const& changes); - void WriteXMLGlobal(std::ostream& xml); + void WriteXMLGlobal(cmXMLWriter& xml); // Parsing helper classes. class InfoParser; diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx index 0a34be8..1e493b0 100644 --- a/Source/CTest/cmCTestScriptHandler.cxx +++ b/Source/CTest/cmCTestScriptHandler.cxx @@ -336,11 +336,12 @@ void cmCTestScriptHandler::CreateCMake() delete this->LocalGenerator; } this->CMake = new cmake; + this->CMake->SetHomeDirectory(""); + this->CMake->SetHomeOutputDirectory(""); this->CMake->AddCMakePaths(); - this->GlobalGenerator = new cmGlobalGenerator; - this->GlobalGenerator->SetCMakeInstance(this->CMake); + this->GlobalGenerator = new cmGlobalGenerator(this->CMake); - this->LocalGenerator = this->GlobalGenerator->CreateLocalGenerator(); + this->LocalGenerator = this->GlobalGenerator->MakeLocalGenerator(); this->Makefile = this->LocalGenerator->GetMakefile(); this->CMake->SetProgressCallback(ctestScriptProgressCallback, this->CTest); diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 95cdf3b..70b7f5c 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -27,7 +27,7 @@ #include "cmLocalGenerator.h" #include "cmCommand.h" #include "cmSystemTools.h" -#include "cmXMLSafe.h" +#include "cmXMLWriter.h" #include "cm_utf8.h" #include <stdlib.h> @@ -633,7 +633,8 @@ int cmCTestTestHandler::ProcessHandler() this->LogFile = 0; return 1; } - this->GenerateDartOutput(xmlfile); + cmXMLWriter xml(xmlfile); + this->GenerateDartOutput(xml); } if ( ! this->PostProcessHandler() ) @@ -1142,54 +1143,53 @@ void cmCTestTestHandler::GenerateTestCommand(std::vector<std::string>&, int) } //---------------------------------------------------------------------- -void cmCTestTestHandler::GenerateDartOutput(std::ostream& os) +void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml) { if ( !this->CTest->GetProduceXML() ) { return; } - this->CTest->StartXML(os, this->AppendXML); - os << "<Testing>\n" - << "\t<StartDateTime>" << this->StartTest << "</StartDateTime>\n" - << "\t<StartTestTime>" << this->StartTestTime << "</StartTestTime>\n" - << "\t<TestList>\n"; + this->CTest->StartXML(xml, this->AppendXML); + xml.StartElement("Testing"); + xml.Element("StartDateTime", this->StartTest); + xml.Element("StartTestTime", this->StartTestTime); + xml.StartElement("TestList"); cmCTestTestHandler::TestResultsVector::size_type cc; for ( cc = 0; cc < this->TestResults.size(); cc ++ ) { cmCTestTestResult *result = &this->TestResults[cc]; std::string testPath = result->Path + "/" + result->Name; - os << "\t\t<Test>" << cmXMLSafe( - this->CTest->GetShortPathToFile(testPath.c_str())) - << "</Test>" << std::endl; + xml.Element("Test", this->CTest->GetShortPathToFile(testPath.c_str())); } - os << "\t</TestList>\n"; + xml.EndElement(); // TestList for ( cc = 0; cc < this->TestResults.size(); cc ++ ) { cmCTestTestResult *result = &this->TestResults[cc]; - this->WriteTestResultHeader(os, result); - os << "\t\t<Results>" << std::endl; + this->WriteTestResultHeader(xml, result); + xml.StartElement("Results"); if ( result->Status != cmCTestTestHandler::NOT_RUN ) { if ( result->Status != cmCTestTestHandler::COMPLETED || result->ReturnValue ) { - os << "\t\t\t<NamedMeasurement type=\"text/string\" " - "name=\"Exit Code\"><Value>" - << cmXMLSafe(this->GetTestStatus(result->Status)) - << "</Value>" - "</NamedMeasurement>\n" - << "\t\t\t<NamedMeasurement type=\"text/string\" " - "name=\"Exit Value\"><Value>" - << result->ReturnValue - << "</Value></NamedMeasurement>" - << std::endl; + xml.StartElement("NamedMeasurement"); + xml.Attribute("type", "text/string"); + xml.Attribute("name", "Exit Code"); + xml.Element("Value", this->GetTestStatus(result->Status)); + xml.EndElement(); // NamedMeasurement + xml.StartElement("NamedMeasurement"); + xml.Attribute("type", "text/string"); + xml.Attribute("name", "Exit Value"); + xml.Element("Value", result->ReturnValue); + xml.EndElement(); // NamedMeasurement } - os << result->RegressionImages; - os << "\t\t\t<NamedMeasurement type=\"numeric/double\" " - << "name=\"Execution Time\"><Value>" - << result->ExecutionTime - << "</Value></NamedMeasurement>\n"; + this->GenerateRegressionImages(xml, result->DartString); + xml.StartElement("NamedMeasurement"); + xml.Attribute("type", "numeric/double"); + xml.Attribute("name", "Execution Time"); + xml.Element("Value", result->ExecutionTime); + xml.EndElement(); // NamedMeasurement if(!result->Reason.empty()) { const char* reasonType = "Pass Reason"; @@ -1198,109 +1198,103 @@ void cmCTestTestHandler::GenerateDartOutput(std::ostream& os) { reasonType = "Fail Reason"; } - os << "\t\t\t<NamedMeasurement type=\"text/string\" " - << "name=\"" << reasonType << "\"><Value>" - << cmXMLSafe(result->Reason) - << "</Value></NamedMeasurement>\n"; + xml.StartElement("NamedMeasurement"); + xml.Attribute("type", "text/string"); + xml.Attribute("name", reasonType); + xml.Element("Value", result->Reason); + xml.EndElement(); // NamedMeasurement } - os - << "\t\t\t<NamedMeasurement type=\"text/string\" " - << "name=\"Completion Status\"><Value>" - << cmXMLSafe(result->CompletionStatus) - << "</Value></NamedMeasurement>\n"; - } - os - << "\t\t\t<NamedMeasurement type=\"text/string\" " - << "name=\"Command Line\"><Value>" - << cmXMLSafe(result->FullCommandLine) - << "</Value></NamedMeasurement>\n"; + xml.StartElement("NamedMeasurement"); + xml.Attribute("type", "text/string"); + xml.Attribute("name", "Completion Status"); + xml.Element("Value", result->CompletionStatus); + xml.EndElement(); // NamedMeasurement + } + xml.StartElement("NamedMeasurement"); + xml.Attribute("type", "text/string"); + xml.Attribute("name", "Command Line"); + xml.Element("Value", result->FullCommandLine); + xml.EndElement(); // NamedMeasurement std::map<std::string,std::string>::iterator measureIt; for ( measureIt = result->Properties->Measurements.begin(); measureIt != result->Properties->Measurements.end(); ++ measureIt ) { - os - << "\t\t\t<NamedMeasurement type=\"text/string\" " - << "name=\"" << measureIt->first << "\"><Value>" - << cmXMLSafe(measureIt->second) - << "</Value></NamedMeasurement>\n"; - } - os - << "\t\t\t<Measurement>\n" - << "\t\t\t\t<Value" - << (result->CompressOutput ? - " encoding=\"base64\" compression=\"gzip\">" - : ">"); - os << cmXMLSafe(result->Output); - os - << "</Value>\n" - << "\t\t\t</Measurement>\n" - << "\t\t</Results>\n"; - - this->AttachFiles(os, result); - this->WriteTestResultFooter(os, result); - } - - os << "\t<EndDateTime>" << this->EndTest << "</EndDateTime>\n" - << "\t<EndTestTime>" << this->EndTestTime << "</EndTestTime>\n" - << "<ElapsedMinutes>" - << static_cast<int>(this->ElapsedTestingTime/6)/10.0 - << "</ElapsedMinutes>" - << "</Testing>" << std::endl; - this->CTest->EndXML(os); + xml.StartElement("NamedMeasurement"); + xml.Attribute("type", "text/string"); + xml.Attribute("name", measureIt->first); + xml.Element("Value", measureIt->second); + xml.EndElement(); // NamedMeasurement + } + xml.StartElement("Measurement"); + xml.StartElement("Value"); + if (result->CompressOutput) + { + xml.Attribute("encoding", "base64"); + xml.Attribute("compression", "gzip"); + } + xml.Content(result->Output); + xml.EndElement(); // Value + xml.EndElement(); // Measurement + xml.EndElement(); // Results + + this->AttachFiles(xml, result); + this->WriteTestResultFooter(xml, result); + } + + xml.Element("EndDateTime", this->EndTest); + xml.Element("EndTestTime", this->EndTestTime); + xml.Element("ElapsedMinutes", + static_cast<int>(this->ElapsedTestingTime/6)/10.0); + xml.EndElement(); // Testing + this->CTest->EndXML(xml); } //---------------------------------------------------------------------------- -void cmCTestTestHandler::WriteTestResultHeader(std::ostream& os, +void cmCTestTestHandler::WriteTestResultHeader(cmXMLWriter& xml, cmCTestTestResult* result) { - os << "\t<Test Status=\""; + xml.StartElement("Test"); if ( result->Status == cmCTestTestHandler::COMPLETED ) { - os << "passed"; + xml.Attribute("Status", "passed"); } else if ( result->Status == cmCTestTestHandler::NOT_RUN ) { - os << "notrun"; + xml.Attribute("Status", "notrun"); } else { - os << "failed"; + xml.Attribute("Status", "failed"); } std::string testPath = result->Path + "/" + result->Name; - os << "\">\n" - << "\t\t<Name>" << cmXMLSafe(result->Name) << "</Name>\n" - << "\t\t<Path>" << cmXMLSafe( - this->CTest->GetShortPathToFile(result->Path.c_str())) << "</Path>\n" - << "\t\t<FullName>" << cmXMLSafe( - this->CTest->GetShortPathToFile(testPath.c_str())) << "</FullName>\n" - << "\t\t<FullCommandLine>" - << cmXMLSafe(result->FullCommandLine) - << "</FullCommandLine>\n"; + xml.Element("Name", result->Name); + xml.Element("Path", this->CTest->GetShortPathToFile(result->Path.c_str())); + xml.Element("FullName", this->CTest->GetShortPathToFile(testPath.c_str())); + xml.Element("FullCommandLine", result->FullCommandLine); } //---------------------------------------------------------------------------- -void cmCTestTestHandler::WriteTestResultFooter(std::ostream& os, +void cmCTestTestHandler::WriteTestResultFooter(cmXMLWriter& xml, cmCTestTestResult* result) { if(!result->Properties->Labels.empty()) { - os << "\t\t<Labels>\n"; + xml.StartElement("Labels"); std::vector<std::string> const& labels = result->Properties->Labels; for(std::vector<std::string>::const_iterator li = labels.begin(); li != labels.end(); ++li) { - os << "\t\t\t<Label>" << cmXMLSafe(*li) << "</Label>\n"; + xml.Element("Label", *li); } - os << "\t\t</Labels>\n"; + xml.EndElement(); // Labels } - os - << "\t</Test>" << std::endl; + xml.EndElement(); // Test } //---------------------------------------------------------------------- -void cmCTestTestHandler::AttachFiles(std::ostream& os, +void cmCTestTestHandler::AttachFiles(cmXMLWriter& xml, cmCTestTestResult* result) { if(result->Status != cmCTestTestHandler::COMPLETED @@ -1317,11 +1311,14 @@ void cmCTestTestHandler::AttachFiles(std::ostream& os, { const std::string &base64 = this->CTest->Base64GzipEncodeFile(*file); std::string fname = cmSystemTools::GetFilenameName(*file); - os << "\t\t<NamedMeasurement name=\"Attached File\" encoding=\"base64\" " - "compression=\"tar/gzip\" filename=\"" << fname << "\" type=\"file\">" - "\n\t\t\t<Value>\n\t\t\t" - << base64 - << "\n\t\t\t</Value>\n\t\t</NamedMeasurement>\n"; + xml.StartElement("NamedMeasurement"); + xml.Attribute("name", "Attached File"); + xml.Attribute("encoding", "base64"); + xml.Attribute("compression", "tar/gzip"); + xml.Attribute("filename", fname); + xml.Attribute("type", "file"); + xml.Element("Value", base64); + xml.EndElement(); // NamedMeasurement } } @@ -1571,9 +1568,10 @@ void cmCTestTestHandler::GetListOfTests() cmCTestOptionalLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "Constructing a list of tests" << std::endl, this->Quiet); cmake cm; - cmGlobalGenerator gg; - gg.SetCMakeInstance(&cm); - cmsys::auto_ptr<cmLocalGenerator> lg(gg.CreateLocalGenerator()); + cm.SetHomeDirectory(""); + cm.SetHomeOutputDirectory(""); + cmGlobalGenerator gg(&cm); + cmsys::auto_ptr<cmLocalGenerator> lg(gg.MakeLocalGenerator()); cmMakefile *mf = lg->GetMakefile(); mf->AddDefinition("CTEST_CONFIGURATION_TYPE", this->CTest->GetConfigType().c_str()); @@ -1826,8 +1824,8 @@ void cmCTestTestHandler::ExpandTestsToRunInformationForRerunFailed() // Just for convenience #define SPACE_REGEX "[ \t\r\n]" //---------------------------------------------------------------------- -std::string cmCTestTestHandler::GenerateRegressionImages( - const std::string& xml) +void cmCTestTestHandler::GenerateRegressionImages( + cmXMLWriter& xml, const std::string& dart) { cmsys::RegularExpression twoattributes( "<DartMeasurement" @@ -1862,71 +1860,62 @@ std::string cmCTestTestHandler::GenerateRegressionImages( SPACE_REGEX "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX "*>([^<]*)</DartMeasurementFile>"); - std::ostringstream ostr; bool done = false; - std::string cxml = xml; + std::string cxml = dart; while ( ! done ) { if ( twoattributes.find(cxml) ) { - ostr - << "\t\t\t<NamedMeasurement" - << " " << twoattributes.match(1) << "=\"" - << twoattributes.match(2) << "\"" - << " " << twoattributes.match(3) << "=\"" - << twoattributes.match(4) << "\"" - << "><Value>" << twoattributes.match(5) - << "</Value></NamedMeasurement>" - << std::endl; + xml.StartElement("NamedMeasurement"); + xml.Attribute(twoattributes.match(1).c_str(), + twoattributes.match(2)); + xml.Attribute(twoattributes.match(3).c_str(), + twoattributes.match(4)); + xml.Element("Value", twoattributes.match(5)); + xml.EndElement(); cxml.erase(twoattributes.start(), twoattributes.end() - twoattributes.start()); } else if ( threeattributes.find(cxml) ) { - ostr - << "\t\t\t<NamedMeasurement" - << " " << threeattributes.match(1) << "=\"" - << threeattributes.match(2) << "\"" - << " " << threeattributes.match(3) << "=\"" - << threeattributes.match(4) << "\"" - << " " << threeattributes.match(5) << "=\"" - << threeattributes.match(6) << "\"" - << "><Value>" << threeattributes.match(7) - << "</Value></NamedMeasurement>" - << std::endl; + xml.StartElement("NamedMeasurement"); + xml.Attribute(threeattributes.match(1).c_str(), + threeattributes.match(2)); + xml.Attribute(threeattributes.match(3).c_str(), + threeattributes.match(4)); + xml.Attribute(threeattributes.match(5).c_str(), + threeattributes.match(6)); + xml.Element("Value", twoattributes.match(7)); + xml.EndElement(); cxml.erase(threeattributes.start(), threeattributes.end() - threeattributes.start()); } else if ( fourattributes.find(cxml) ) { - ostr - << "\t\t\t<NamedMeasurement" - << " " << fourattributes.match(1) << "=\"" - << fourattributes.match(2) << "\"" - << " " << fourattributes.match(3) << "=\"" - << fourattributes.match(4) << "\"" - << " " << fourattributes.match(5) << "=\"" - << fourattributes.match(6) << "\"" - << " " << fourattributes.match(7) << "=\"" - << fourattributes.match(8) << "\"" - << "><Value>" << fourattributes.match(9) - << "</Value></NamedMeasurement>" - << std::endl; + xml.StartElement("NamedMeasurement"); + xml.Attribute(fourattributes.match(1).c_str(), + fourattributes.match(2)); + xml.Attribute(fourattributes.match(3).c_str(), + fourattributes.match(4)); + xml.Attribute(fourattributes.match(5).c_str(), + fourattributes.match(6)); + xml.Attribute(fourattributes.match(7).c_str(), + fourattributes.match(8)); + xml.Element("Value", twoattributes.match(9)); + xml.EndElement(); cxml.erase(fourattributes.start(), fourattributes.end() - fourattributes.start()); } else if ( cdatastart.find(cxml) && cdataend.find(cxml) ) { - ostr - << "\t\t\t<NamedMeasurement" - << " " << cdatastart.match(1) << "=\"" - << cdatastart.match(2) << "\"" - << " " << cdatastart.match(3) << "=\"" - << cdatastart.match(4) << "\"" - << "><Value><![CDATA[" - << cxml.substr(cdatastart.end(), cdataend.start() - cdatastart.end()) - << "]]></Value></NamedMeasurement>" - << std::endl; + xml.StartElement("NamedMeasurement"); + xml.Attribute(cdatastart.match(1).c_str(), cdatastart.match(2)); + xml.Attribute(cdatastart.match(3).c_str(), cdatastart.match(4)); + xml.StartElement("Value"); + xml.CData( + cxml.substr(cdatastart.end(), cdataend.start() - cdatastart.end())); + xml.EndElement(); // Value + xml.EndElement(); // NamedMeasurement cxml.erase(cdatastart.start(), cdataend.end() - cdatastart.start()); } @@ -1952,13 +1941,12 @@ std::string cmCTestTestHandler::GenerateRegressionImages( v2 = "text/string"; } - ostr - << "\t\t\t<NamedMeasurement" - << " " << k1 << "=\"" << v1 << "\"" - << " " << k2 << "=\"" << v2 << "\"" - << " encoding=\"none\"" - << "><Value>Image " << filename - << " is empty</Value></NamedMeasurement>"; + xml.StartElement("NamedMeasurement"); + xml.Attribute(k1.c_str(), v1); + xml.Attribute(k2.c_str(), v2); + xml.Attribute("encoding", "none"); + xml.Element("Value", "Image " + filename + " is empty"); + xml.EndElement(); } else { @@ -1976,14 +1964,13 @@ std::string cmCTestTestHandler::GenerateRegressionImages( size_t rlen = cmsysBase64_Encode(file_buffer, len, encoded_buffer, 1); - ostr - << "\t\t\t<NamedMeasurement" - << " " << measurementfile.match(1) << "=\"" - << measurementfile.match(2) << "\"" - << " " << measurementfile.match(3) << "=\"" - << measurementfile.match(4) << "\"" - << " encoding=\"base64\"" - << ">" << std::endl << "\t\t\t\t<Value>"; + xml.StartElement("NamedMeasurement"); + xml.Attribute(measurementfile.match(1).c_str(), + measurementfile.match(2)); + xml.Attribute(measurementfile.match(3).c_str(), + measurementfile.match(4)); + xml.Attribute("encoding", "base64"); + std::stringstream ostr; for (size_t cc = 0; cc < rlen; cc ++ ) { ostr << encoded_buffer[cc]; @@ -1992,9 +1979,8 @@ std::string cmCTestTestHandler::GenerateRegressionImages( ostr << std::endl; } } - ostr - << "</Value>" << std::endl << "\t\t\t</NamedMeasurement>" - << std::endl; + xml.Element("Value", ostr.str()); + xml.EndElement(); // NamedMeasurement delete [] file_buffer; delete [] encoded_buffer; } @@ -2006,13 +1992,11 @@ std::string cmCTestTestHandler::GenerateRegressionImages( { idx = 2; } - ostr - << "\t\t\t<NamedMeasurement" - << " name=\"" << measurementfile.match(idx) << "\"" - << " text=\"text/string\"" - << "><Value>File " << filename - << " not found</Value></NamedMeasurement>" - << std::endl; + xml.StartElement("NamedMeasurement"); + xml.Attribute("name", measurementfile.match(idx)); + xml.Attribute("text", "text/string"); + xml.Element("Value", "File " + filename + " not found"); + xml.EndElement(); cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "File \"" << filename << "\" not found." << std::endl, this->Quiet); } @@ -2024,7 +2008,6 @@ std::string cmCTestTestHandler::GenerateRegressionImages( done = true; } } - return ostr.str(); } //---------------------------------------------------------------------- diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index fe43bb8..14067d5 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -18,6 +18,7 @@ #include <cmsys/RegularExpression.hxx> class cmMakefile; +class cmXMLWriter; /** \class cmCTestTestHandler * \brief A class that handles ctest -S invocations @@ -128,7 +129,7 @@ public: bool CompressOutput; std::string CompletionStatus; std::string Output; - std::string RegressionImages; + std::string DartString; int TestCount; cmCTestTestProperties* Properties; }; @@ -164,10 +165,10 @@ protected: virtual void GenerateTestCommand(std::vector<std::string>& args, int test); int ExecuteCommands(std::vector<std::string>& vec); - void WriteTestResultHeader(std::ostream& os, cmCTestTestResult* result); - void WriteTestResultFooter(std::ostream& os, cmCTestTestResult* result); + void WriteTestResultHeader(cmXMLWriter& xml, cmCTestTestResult* result); + void WriteTestResultFooter(cmXMLWriter& xml, cmCTestTestResult* result); // Write attached test files into the xml - void AttachFiles(std::ostream& os, cmCTestTestResult* result); + void AttachFiles(cmXMLWriter& xml, cmCTestTestResult* result); //! Clean test output to specified length bool CleanTestOutput(std::string& output, size_t length); @@ -204,7 +205,7 @@ private: /** * Generate the Dart compatible output */ - virtual void GenerateDartOutput(std::ostream& os); + virtual void GenerateDartOutput(cmXMLWriter& xml); void PrintLabelSummary(); /** @@ -270,7 +271,7 @@ private: cmsys::RegularExpression IncludeTestsRegularExpression; cmsys::RegularExpression ExcludeTestsRegularExpression; - std::string GenerateRegressionImages(const std::string& xml); + void GenerateRegressionImages(cmXMLWriter& xml, const std::string& dart); cmsys::RegularExpression DartStuff1; void CheckLabelFilter(cmCTestTestProperties& it); void CheckLabelFilterExclude(cmCTestTestProperties& it); diff --git a/Source/CTest/cmCTestUpdateHandler.cxx b/Source/CTest/cmCTestUpdateHandler.cxx index 10927e7..8494d28 100644 --- a/Source/CTest/cmCTestUpdateHandler.cxx +++ b/Source/CTest/cmCTestUpdateHandler.cxx @@ -20,7 +20,7 @@ #include "cmVersion.h" #include "cmGeneratedFileStream.h" #include "cmXMLParser.h" -#include "cmXMLSafe.h" +#include "cmXMLWriter.h" #include "cmCLocaleEnvironmentScope.h" #include "cmCTestVC.h" @@ -224,24 +224,24 @@ int cmCTestUpdateHandler::ProcessHandler() bool updated = vc->Update(); std::string buildname = cmCTest::SafeBuildIdField( this->CTest->GetCTestConfiguration("BuildName")); - os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" - << "<Update mode=\"Client\" Generator=\"ctest-" - << cmVersion::GetCMakeVersion() << "\">\n" - << "\t<Site>" << this->CTest->GetCTestConfiguration("Site") << "</Site>\n" - << "\t<BuildName>" << buildname - << "</BuildName>\n" - << "\t<BuildStamp>" << this->CTest->GetCurrentTag() << "-" - << this->CTest->GetTestModelString() << "</BuildStamp>" << std::endl; - os << "\t<StartDateTime>" << start_time << "</StartDateTime>\n" - << "\t<StartTime>" << start_time_time << "</StartTime>\n" - << "\t<UpdateCommand>" - << cmXMLSafe(vc->GetUpdateCommandLine()).Quotes(false) - << "</UpdateCommand>\n" - << "\t<UpdateType>" << cmXMLSafe( - cmCTestUpdateHandlerUpdateToString(this->UpdateType)) - << "</UpdateType>\n"; - - vc->WriteXML(os); + + cmXMLWriter xml(os); + xml.StartDocument(); + xml.StartElement("Update"); + xml.Attribute("mode", "Client"); + xml.Attribute("Generator", + std::string("ctest-") + cmVersion::GetCMakeVersion()); + xml.Element("Site", this->CTest->GetCTestConfiguration("Site")); + xml.Element("BuildName", buildname); + xml.Element("BuildStamp", this->CTest->GetCurrentTag() + "-" + + this->CTest->GetTestModelString()); + xml.Element("StartDateTime", start_time); + xml.Element("StartTime", start_time_time); + xml.Element("UpdateCommand", vc->GetUpdateCommandLine()); + xml.Element("UpdateType", + cmCTestUpdateHandlerUpdateToString(this->UpdateType)); + + vc->WriteXML(xml); int localModifications = 0; int numUpdated = vc->GetPathCount(cmCTestVC::PathUpdated); @@ -265,29 +265,30 @@ int cmCTestUpdateHandler::ProcessHandler() cmCTestOptionalLog(this->CTest, DEBUG, "End" << std::endl, this->Quiet); std::string end_time = this->CTest->CurrentTime(); - os << "\t<EndDateTime>" << end_time << "</EndDateTime>\n" - << "\t<EndTime>" << static_cast<unsigned int>(cmSystemTools::GetTime()) - << "</EndTime>\n" - << "<ElapsedMinutes>" << - static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0 - << "</ElapsedMinutes>\n" - << "\t<UpdateReturnStatus>"; + xml.Element("EndDateTime", end_time); + xml.Element("EndTime", static_cast<unsigned int>(cmSystemTools::GetTime())); + xml.Element("ElapsedMinutes", + static_cast<int>((cmSystemTools::GetTime() - elapsed_time_start)/6)/10.0); + + xml.StartElement("UpdateReturnStatus"); if(localModifications) { - os << "Update error: There are modified or conflicting files in the " - "repository"; + xml.Content("Update error: " + "There are modified or conflicting files in the repository"); cmCTestLog(this->CTest, ERROR_MESSAGE, " There are modified or conflicting files in the repository" << std::endl); } if(!updated) { - os << "Update command failed:\n" << vc->GetUpdateCommandLine(); + xml.Content("Update command failed:\n"); + xml.Content(vc->GetUpdateCommandLine()); cmCTestLog(this->CTest, ERROR_MESSAGE, " Update command failed: " << vc->GetUpdateCommandLine() << "\n"); } - os << "</UpdateReturnStatus>" << std::endl; - os << "</Update>" << std::endl; + xml.EndElement(); // UpdateReturnStatus + xml.EndElement(); // Update + xml.EndDocument(); return numUpdated; } diff --git a/Source/CTest/cmCTestUploadHandler.cxx b/Source/CTest/cmCTestUploadHandler.cxx index 579190a..5c6b229 100644 --- a/Source/CTest/cmCTestUploadHandler.cxx +++ b/Source/CTest/cmCTestUploadHandler.cxx @@ -13,7 +13,7 @@ #include "cmGeneratedFileStream.h" #include "cmVersion.h" -#include "cmXMLSafe.h" +#include "cmXMLWriter.h" //---------------------------------------------------------------------------- cmCTestUploadHandler::cmCTestUploadHandler() @@ -47,32 +47,36 @@ int cmCTestUploadHandler::ProcessHandler() std::string buildname = cmCTest::SafeBuildIdField( this->CTest->GetCTestConfiguration("BuildName")); cmCTest::SetOfStrings::const_iterator it; - ofs << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" - << "<?xml-stylesheet type=\"text/xsl\" " + + cmXMLWriter xml(ofs); + xml.StartDocument(); + xml.ProcessingInstruction("xml-stylesheet", "type=\"text/xsl\" " "href=\"Dart/Source/Server/XSL/Build.xsl " - "<file:///Dart/Source/Server/XSL/Build.xsl> \"?>\n" - << "<Site BuildName=\"" - << buildname - << "\" BuildStamp=\"" - << this->CTest->GetCurrentTag() << "-" - << this->CTest->GetTestModelString() << "\" Name=\"" - << this->CTest->GetCTestConfiguration("Site") << "\" Generator=\"ctest" - << cmVersion::GetCMakeVersion() - << "\">\n"; - this->CTest->AddSiteProperties(ofs); - ofs << "<Upload>\n"; + "<file:///Dart/Source/Server/XSL/Build.xsl> \""); + xml.StartElement("Site"); + xml.Attribute("BuildName", buildname); + xml.Attribute("BuildStamp", + this->CTest->GetCurrentTag() + "-" + this->CTest->GetTestModelString()); + xml.Attribute("Name", this->CTest->GetCTestConfiguration("Site")); + xml.Attribute("Generator", + std::string("ctest") + cmVersion::GetCMakeVersion()); + this->CTest->AddSiteProperties(xml); + xml.StartElement("Upload"); for ( it = this->Files.begin(); it != this->Files.end(); it ++ ) { cmCTestOptionalLog(this->CTest, OUTPUT, "\tUpload file: " << *it << std::endl, this->Quiet); - ofs << "<File filename=\"" << cmXMLSafe(*it) << "\">\n" - << "<Content encoding=\"base64\">\n"; - ofs << this->CTest->Base64EncodeFile(*it); - ofs << "\n</Content>\n" - << "</File>\n"; + xml.StartElement("File"); + xml.Attribute("filename", *it); + xml.StartElement("Content"); + xml.Attribute("encoding", "base64"); + xml.Content(this->CTest->Base64EncodeFile(*it)); + xml.EndElement(); // Content + xml.EndElement(); // File } - ofs << "</Upload>\n" - << "</Site>\n"; + xml.EndElement(); // Upload + xml.EndElement(); // Site + xml.EndDocument(); return 0; } diff --git a/Source/CTest/cmCTestVC.cxx b/Source/CTest/cmCTestVC.cxx index 6e93e95..8eff4d6 100644 --- a/Source/CTest/cmCTestVC.cxx +++ b/Source/CTest/cmCTestVC.cxx @@ -13,7 +13,7 @@ #include "cmCTest.h" #include "cmSystemTools.h" -#include "cmXMLSafe.h" +#include "cmXMLWriter.h" #include <cmsys/Process.h> @@ -202,7 +202,7 @@ bool cmCTestVC::UpdateImpl() } //---------------------------------------------------------------------------- -bool cmCTestVC::WriteXML(std::ostream& xml) +bool cmCTestVC::WriteXML(cmXMLWriter& xml) { this->Log << "--- Begin Revisions ---\n"; bool result = this->WriteXMLUpdates(xml); @@ -211,7 +211,7 @@ bool cmCTestVC::WriteXML(std::ostream& xml) } //---------------------------------------------------------------------------- -bool cmCTestVC::WriteXMLUpdates(std::ostream&) +bool cmCTestVC::WriteXMLUpdates(cmXMLWriter&) { cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, "* CTest cannot extract updates for this VCS tool.\n"); @@ -219,7 +219,7 @@ bool cmCTestVC::WriteXMLUpdates(std::ostream&) } //---------------------------------------------------------------------------- -void cmCTestVC::WriteXMLEntry(std::ostream& xml, +void cmCTestVC::WriteXMLEntry(cmXMLWriter& xml, std::string const& path, std::string const& name, std::string const& full, @@ -228,21 +228,19 @@ void cmCTestVC::WriteXMLEntry(std::ostream& xml, static const char* desc[3] = { "Updated", "Modified", "Conflicting"}; Revision const& rev = f.Rev? *f.Rev : this->Unknown; std::string prior = f.PriorRev? f.PriorRev->Rev : std::string("Unknown"); - xml << "\t\t<" << desc[f.Status] << ">\n" - << "\t\t\t<File>" << cmXMLSafe(name) << "</File>\n" - << "\t\t\t<Directory>" << cmXMLSafe(path) << "</Directory>\n" - << "\t\t\t<FullName>" << cmXMLSafe(full) << "</FullName>\n" - << "\t\t\t<CheckinDate>" << cmXMLSafe(rev.Date) << "</CheckinDate>\n" - << "\t\t\t<Author>" << cmXMLSafe(rev.Author) << "</Author>\n" - << "\t\t\t<Email>" << cmXMLSafe(rev.EMail) << "</Email>\n" - << "\t\t\t<Committer>" << cmXMLSafe(rev.Committer) << "</Committer>\n" - << "\t\t\t<CommitterEmail>" << cmXMLSafe(rev.CommitterEMail) - << "</CommitterEmail>\n" - << "\t\t\t<CommitDate>" << cmXMLSafe(rev.CommitDate) - << "</CommitDate>\n" - << "\t\t\t<Log>" << cmXMLSafe(rev.Log) << "</Log>\n" - << "\t\t\t<Revision>" << cmXMLSafe(rev.Rev) << "</Revision>\n" - << "\t\t\t<PriorRevision>" << cmXMLSafe(prior) << "</PriorRevision>\n" - << "\t\t</" << desc[f.Status] << ">\n"; + xml.StartElement(desc[f.Status]); + xml.Element("File", name); + xml.Element("Directory", path); + xml.Element("FullName", full); + xml.Element("CheckinDate", rev.Date); + xml.Element("Author", rev.Author); + xml.Element("Email", rev.EMail); + xml.Element("Committer", rev.Committer); + xml.Element("CommitterEmail", rev.CommitterEMail); + xml.Element("CommitDate", rev.CommitDate); + xml.Element("Log", rev.Log); + xml.Element("Revision", rev.Rev); + xml.Element("PriorRevision", prior); + xml.EndElement(); ++this->PathCount[f.Status]; } diff --git a/Source/CTest/cmCTestVC.h b/Source/CTest/cmCTestVC.h index 9dd0651..bc89302 100644 --- a/Source/CTest/cmCTestVC.h +++ b/Source/CTest/cmCTestVC.h @@ -15,6 +15,7 @@ #include "cmProcessTools.h" class cmCTest; +class cmXMLWriter; /** \class cmCTestVC * \brief Base class for version control system handlers @@ -51,7 +52,7 @@ public: { return this->UpdateCommandLine; } /** Write Update.xml entries for the updates found. */ - bool WriteXML(std::ostream& xml); + bool WriteXML(cmXMLWriter& xml); /** Enumerate non-trivial working tree states during update. */ enum PathStatus { PathUpdated, PathModified, PathConflicting }; @@ -65,7 +66,7 @@ protected: virtual void NoteOldRevision(); virtual bool UpdateImpl(); virtual void NoteNewRevision(); - virtual bool WriteXMLUpdates(std::ostream& xml); + virtual bool WriteXMLUpdates(cmXMLWriter& xml); #if defined(__SUNPRO_CC) && __SUNPRO_CC <= 0x510 public: // Sun CC 5.1 needs help to allow cmCTestSVN::Revision to see this @@ -110,7 +111,7 @@ protected: OutputParser* out, OutputParser* err = 0); /** Write xml element for one file. */ - void WriteXMLEntry(std::ostream& xml, std::string const& path, + void WriteXMLEntry(cmXMLWriter& xml, std::string const& path, std::string const& name, std::string const& full, File const& f); diff --git a/Source/Checks/cm_cxx11_unordered_map.cmake b/Source/Checks/cm_cxx11_unordered_map.cmake new file mode 100644 index 0000000..80fe391 --- /dev/null +++ b/Source/Checks/cm_cxx11_unordered_map.cmake @@ -0,0 +1,25 @@ + +if(CMAKE_CXX_STANDARD AND NOT DEFINED CMake_HAVE_CXX11_UNORDERED_MAP) + message(STATUS "Checking if compiler supports C++11 unordered_map") + try_compile(CMake_HAVE_CXX11_UNORDERED_MAP + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_LIST_DIR}/cm_cxx11_unordered_map.cpp + CMAKE_FLAGS -DCMAKE_CXX_STANDARD=${CMAKE_CXX_STANDARD} + OUTPUT_VARIABLE OUTPUT + ) + if(CMake_HAVE_CXX11_UNORDERED_MAP) + message(STATUS "Checking if compiler supports C++11 unordered_map - yes") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Determining if compiler supports C++11 unordered_map passed with the following output:\n" + "${OUTPUT}\n" + "\n" + ) + else() + message(STATUS "Checking if compiler supports C++11 unordered_map - no") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Determining if compiler supports C++11 unordered_map failed with the following output:\n" + "${OUTPUT}\n" + "\n" + ) + endif() +endif() diff --git a/Source/Checks/cm_cxx11_unordered_map.cpp b/Source/Checks/cm_cxx11_unordered_map.cpp new file mode 100644 index 0000000..beeb31b --- /dev/null +++ b/Source/Checks/cm_cxx11_unordered_map.cpp @@ -0,0 +1,6 @@ +#include <unordered_map> +int main() { + std::unordered_map<int, int> map; + map[0] = 0; + return 0; +} diff --git a/Source/Checks/cm_cxx14_cstdio.cmake b/Source/Checks/cm_cxx14_cstdio.cmake new file mode 100644 index 0000000..73f7e2e --- /dev/null +++ b/Source/Checks/cm_cxx14_cstdio.cmake @@ -0,0 +1,33 @@ +set(CMake_CXX14_CSTDIO_BROKEN 0) +if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang" AND CMAKE_CXX14_STANDARD_COMPILE_OPTION) + if(NOT DEFINED CMake_CXX14_CSTDIO_WORKS) + message(STATUS "Checking if compiler supports C++14 cstdio") + try_compile(CMake_CXX14_CSTDIO_WORKS + ${CMAKE_CURRENT_BINARY_DIR} + ${CMAKE_CURRENT_LIST_DIR}/cm_cxx14_cstdio.cpp + CMAKE_FLAGS -DCMAKE_CXX_STANDARD=14 + OUTPUT_VARIABLE OUTPUT + ) + if(CMake_CXX14_CSTDIO_WORKS AND "${OUTPUT}" MATCHES "error: no member named.*gets.*in the global namespace") + set_property(CACHE CMake_CXX14_CSTDIO_WORKS PROPERTY VALUE 0) + endif() + if(CMake_CXX14_CSTDIO_WORKS) + message(STATUS "Checking if compiler supports C++14 cstdio - yes") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeOutput.log + "Determining if compiler supports C++14 cstdio passed with the following output:\n" + "${OUTPUT}\n" + "\n" + ) + else() + message(STATUS "Checking if compiler supports C++14 cstdio - no") + file(APPEND ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log + "Determining if compiler supports C++14 cstdio failed with the following output:\n" + "${OUTPUT}\n" + "\n" + ) + endif() + endif() + if(NOT CMake_CXX14_CSTDIO_WORKS) + set(CMake_CXX14_CSTDIO_BROKEN 1) + endif() +endif() diff --git a/Source/Checks/cm_cxx14_cstdio.cpp b/Source/Checks/cm_cxx14_cstdio.cpp new file mode 100644 index 0000000..3a6a699 --- /dev/null +++ b/Source/Checks/cm_cxx14_cstdio.cpp @@ -0,0 +1,2 @@ +#include <cstdio> +int main() { return 0; } diff --git a/Source/CursesDialog/ccmake.cxx b/Source/CursesDialog/ccmake.cxx index e013f81..5236e57 100644 --- a/Source/CursesDialog/ccmake.cxx +++ b/Source/CursesDialog/ccmake.cxx @@ -104,6 +104,8 @@ int main(int argc, char const* const* argv) if(doc.CheckOptions(argc, argv)) { cmake hcm; + hcm.SetHomeDirectory(""); + hcm.SetHomeOutputDirectory(""); hcm.AddCMakePaths(); std::vector<cmDocumentationEntry> generators; hcm.GetGeneratorDocumentation(generators); diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt index 9cc993a..168f57d 100644 --- a/Source/QtDialog/CMakeLists.txt +++ b/Source/QtDialog/CMakeLists.txt @@ -99,15 +99,12 @@ set(SRCS QCMakeCacheView.h QCMakeWidgets.cxx QCMakeWidgets.h - QMacInstallDialog.cxx - QMacInstallDialog.h ) QT4_WRAP_UI(UI_SRCS CMakeSetupDialog.ui Compilers.ui CrossCompiler.ui AddCacheEntry.ui - MacInstallDialog.ui ) QT4_WRAP_CPP(MOC_SRCS AddCacheEntry.h @@ -117,7 +114,6 @@ QT4_WRAP_CPP(MOC_SRCS QCMake.h QCMakeCacheView.h QCMakeWidgets.h - QMacInstallDialog.h ) QT4_ADD_RESOURCES(RC_SRCS CMakeSetup.qrc) diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx index 8a72a24..38d6d44 100644 --- a/Source/QtDialog/CMakeSetup.cxx +++ b/Source/QtDialog/CMakeSetup.cxx @@ -15,11 +15,11 @@ #include <QTranslator> #include <QLocale> #include <QTextCodec> -#include "QMacInstallDialog.h" #include "CMakeSetupDialog.h" #include "cmDocumentation.h" #include "cmake.h" #include "cmVersion.h" +#include "cmAlgorithms.h" #include <cmsys/CommandLineArguments.hxx> #include <cmsys/SystemTools.hxx> #include <cmsys/Encoding.hxx> @@ -48,6 +48,10 @@ static const char * cmDocumentationOptions[][2] = {0,0} }; +#if defined(Q_OS_MAC) +static int cmOSXInstall(std::string dir); +#endif + int main(int argc, char** argv) { cmsys::Encoding::CommandLineArguments encoding_args = @@ -64,6 +68,8 @@ int main(int argc, char** argv) { // Construct and print requested documentation. cmake hcm; + hcm.SetHomeDirectory(""); + hcm.SetHomeOutputDirectory(""); hcm.AddCMakePaths(); std::vector<cmDocumentationEntry> generators; @@ -77,6 +83,17 @@ int main(int argc, char** argv) return (doc.PrintRequestedDocumentation(std::cout)? 0:1); } +#if defined(Q_OS_MAC) + if (argc2 == 2 && strcmp(argv2[1], "--install") == 0) + { + return cmOSXInstall("/usr/bin"); + } + if (argc2 == 2 && cmHasLiteralPrefix(argv2[1], "--install=")) + { + return cmOSXInstall(argv2[1]+10); + } +#endif + QApplication app(argc, argv); #if defined(CMAKE_ENCODING_UTF8) @@ -91,16 +108,6 @@ int main(int argc, char** argv) QApplication::removeLibraryPath(p); } - // if arg for install - for(int i =0; i < argc2; i++) - { - if(strcmp(argv2[i], "--mac-install") == 0) - { - QMacInstallDialog setupdialog(0); - setupdialog.exec(); - return 0; - } - } // tell the cmake library where cmake is QDir cmExecDir(QApplication::applicationDirPath()); #if defined(Q_OS_MAC) @@ -187,3 +194,54 @@ int main(int argc, char** argv) return app.exec(); } +#if defined(Q_OS_MAC) +# include <errno.h> +# include <string.h> +# include <sys/stat.h> +# include <unistd.h> +static bool cmOSXInstall(std::string const& dir, std::string const& tool) +{ + if (tool.empty()) + { + return true; + } + std::string link = dir + cmSystemTools::GetFilenameName(tool); + struct stat st; + if (lstat(link.c_str(), &st) == 0 && S_ISLNK(st.st_mode)) + { + char buf[4096]; + ssize_t s = readlink(link.c_str(), buf, sizeof(buf)-1); + if (s >= 0 && std::string(buf, s) == tool) + { + std::cerr << "Exists: '" << link << "' -> '" << tool << "'\n"; + return true; + } + } + if (symlink(tool.c_str(), link.c_str()) == 0) + { + std::cerr << "Linked: '" << link << "' -> '" << tool << "'\n"; + return true; + } + else + { + int err = errno; + std::cerr << "Failed: '" << link << "' -> '" << tool << "': " + << strerror(err) << "\n"; + return false; + } +} +static int cmOSXInstall(std::string dir) +{ + if (!cmHasLiteralSuffix(dir, "/")) + { + dir += "/"; + } + return ( + cmOSXInstall(dir, cmSystemTools::GetCMakeCommand()) && + cmOSXInstall(dir, cmSystemTools::GetCTestCommand()) && + cmOSXInstall(dir, cmSystemTools::GetCPackCommand()) && + cmOSXInstall(dir, cmSystemTools::GetCMakeGUICommand()) && + cmOSXInstall(dir, cmSystemTools::GetCMakeCursesCommand()) + ) ? 0 : 1; +} +#endif diff --git a/Source/QtDialog/CMakeSetupDialog.cxx b/Source/QtDialog/CMakeSetupDialog.cxx index b8077f2..426fa12 100644 --- a/Source/QtDialog/CMakeSetupDialog.cxx +++ b/Source/QtDialog/CMakeSetupDialog.cxx @@ -27,7 +27,6 @@ #include <QUrl> #include <QShortcut> #include <QKeySequence> -#include <QMacInstallDialog.h> #include <QInputDialog> #include "QCMake.h" @@ -121,7 +120,7 @@ CMakeSetupDialog::CMakeSetupDialog() this, SLOT(showUserChanges())); #if defined(Q_WS_MAC) || defined(Q_OS_MAC) this->InstallForCommandLineAction - = ToolsMenu->addAction(tr("&Install For Command Line Use")); + = ToolsMenu->addAction(tr("&How to Install For Command Line Use")); QObject::connect(this->InstallForCommandLineAction, SIGNAL(triggered(bool)), this, SLOT(doInstallForCommandLine())); #endif @@ -420,8 +419,37 @@ bool CMakeSetupDialog::doConfigureInternal() void CMakeSetupDialog::doInstallForCommandLine() { - QMacInstallDialog setupdialog(0); - setupdialog.exec(); + QString title = tr("How to Install For Command Line Use"); + QString msg = tr( + "One may add CMake to the PATH:\n" + "\n" + " PATH=\"%1\":\"$PATH\"\n" + "\n" + "Or, to install symlinks to '/usr/bin', run:\n" + "\n" + " sudo \"%2\" --install\n" + "\n" + "Or, to install symlinks to another directory, run:\n" + "\n" + " sudo \"%3\" --install=/path/to/bin\n" + ); + msg = msg.arg(cmSystemTools::GetFilenamePath( + cmSystemTools::GetCMakeCommand()).c_str()); + msg = msg.arg(cmSystemTools::GetCMakeGUICommand().c_str()); + msg = msg.arg(cmSystemTools::GetCMakeGUICommand().c_str()); + + QDialog dialog; + dialog.setWindowTitle(title); + QVBoxLayout* l = new QVBoxLayout(&dialog); + QLabel* lab = new QLabel(&dialog); + l->addWidget(lab); + lab->setText(msg); + lab->setWordWrap(false); + QDialogButtonBox* btns = new QDialogButtonBox(QDialogButtonBox::Ok, + Qt::Horizontal, &dialog); + QObject::connect(btns, SIGNAL(accepted()), &dialog, SLOT(accept())); + l->addWidget(btns); + dialog.exec(); } bool CMakeSetupDialog::doGenerateInternal() diff --git a/Source/QtDialog/MacInstallDialog.ui b/Source/QtDialog/MacInstallDialog.ui deleted file mode 100644 index c7e31db..0000000 --- a/Source/QtDialog/MacInstallDialog.ui +++ /dev/null @@ -1,103 +0,0 @@ -<ui version="4.0" > - <class>Dialog</class> - <widget class="QDialog" name="Dialog" > - <property name="geometry" > - <rect> - <x>0</x> - <y>0</y> - <width>470</width> - <height>159</height> - </rect> - </property> - <property name="windowTitle" > - <string>Install Command Line Tools</string> - </property> - <layout class="QGridLayout" > - <property name="margin" > - <number>9</number> - </property> - <property name="spacing" > - <number>6</number> - </property> - <item row="3" column="1" > - <spacer> - <property name="orientation" > - <enum>Qt::Vertical</enum> - </property> - <property name="sizeHint" > - <size> - <width>20</width> - <height>40</height> - </size> - </property> - </spacer> - </item> - <item row="2" column="0" colspan="3" > - <layout class="QHBoxLayout" > - <property name="margin" > - <number>0</number> - </property> - <property name="spacing" > - <number>6</number> - </property> - <item> - <spacer> - <property name="orientation" > - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" > - <size> - <width>40</width> - <height>20</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="skipInstallButton" > - <property name="text" > - <string>Skip Install Command Line </string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="doInstallButton" > - <property name="text" > - <string>Install Command Line Links</string> - </property> - </widget> - </item> - </layout> - </item> - <item row="0" column="2" > - <widget class="QPushButton" name="choosePathButton" > - <property name="text" > - <string>Choose...</string> - </property> - </widget> - </item> - <item row="0" column="0" > - <widget class="QLabel" name="label" > - <property name="text" > - <string>Install Folder:</string> - </property> - </widget> - </item> - <item row="0" column="1" > - <widget class="QLineEdit" name="InstallPrefix" /> - </item> - <item row="1" column="0" colspan="3" > - <widget class="QLabel" name="label_2" > - <property name="text" > - <string>This will create symbolic links to the command line tools of cmake into the specified install folder.</string> - </property> - <property name="wordWrap" > - <bool>true</bool> - </property> - </widget> - </item> - </layout> - </widget> - <resources/> - <connections/> -</ui> diff --git a/Source/QtDialog/QMacInstallDialog.cxx b/Source/QtDialog/QMacInstallDialog.cxx deleted file mode 100644 index fa7df43..0000000 --- a/Source/QtDialog/QMacInstallDialog.cxx +++ /dev/null @@ -1,121 +0,0 @@ -#include "QMacInstallDialog.h" -#include <QMessageBox> -#include "cmSystemTools.h" -#include <iostream> -#include <QFileDialog> -#include "ui_MacInstallDialog.h" - -class QMacInstallDialog::QMacInstallDialogInternals : public Ui::Dialog -{ -public: -}; - -QMacInstallDialog::QMacInstallDialog(QWidget*w) - :QDialog(w) -{ - this->Internals = new QMacInstallDialogInternals; - this->Internals->setupUi(this); - QObject::connect(this->Internals->choosePathButton, SIGNAL(clicked(bool)), - this, SLOT(ShowBrowser())); - QObject::connect(this->Internals->skipInstallButton, SIGNAL(clicked(bool)), - this, SLOT(SkipInstall())); - QObject::connect(this->Internals->doInstallButton, SIGNAL(clicked(bool)), - this, SLOT(DoInstall())); - this->Internals->InstallPrefix->setText("/usr/bin/"); - -} - -QMacInstallDialog::~QMacInstallDialog() -{ - delete this->Internals; -} - -void QMacInstallDialog::DoInstall() -{ - QDir installDir(this->Internals->InstallPrefix->text()); - QString installTo = installDir.path(); - if(!cmSystemTools::FileExists(installTo.toLocal8Bit().data())) - { - QString message = tr("Build install does not exist, " - "should I create it?\n\n" - "Directory: "); - message += installDir.path(); - QString title = tr("Create Directory"); - QMessageBox::StandardButton btn; - btn = QMessageBox::information(this, title, message, - QMessageBox::Yes | QMessageBox::No); - if(btn == QMessageBox::Yes) - { - cmSystemTools::MakeDirectory(installTo.toLocal8Bit().data()); - } - } - QDir cmExecDir(QApplication::applicationDirPath()); - cmExecDir.cd("../bin"); - QFileInfoList list = cmExecDir.entryInfoList(); - for (int i = 0; i < list.size(); ++i) - { - QFileInfo fileInfo = list.at(i); - QString filename = fileInfo.fileName(); - if(filename.size() && filename[0] == '.') - { - continue; - } - QString file = fileInfo.absoluteFilePath(); - QString newName = installTo; - newName += "/"; - newName += filename; - // Remove the old files - if(cmSystemTools::FileExists(newName.toLocal8Bit().data())) - { - std::cout << "rm [" << newName.toLocal8Bit().data() << "]\n"; - if(!cmSystemTools::RemoveFile(newName.toLocal8Bit().data())) - { - QString message = tr("Failed to remove file " - "installation may be incomplete: "); - message += newName; - QString title = tr("Error Removing file"); - QMessageBox::StandardButton btn = - QMessageBox::critical(this, title, message, - QMessageBox::Ok|QMessageBox::Abort); - if(btn == QMessageBox::Abort) - { - return; - } - } - } - std::cout << "ln -s [" << file.toLocal8Bit().data() << "] ["; - std::cout << newName.toLocal8Bit().data() << "]\n"; - if(!cmSystemTools::CreateSymlink(file.toLocal8Bit().data(), - newName.toLocal8Bit().data())) - { - QString message = tr("Failed create symlink " - "installation may be incomplete: "); - message += newName; - QString title = tr("Error Creating Symlink"); - QMessageBox::StandardButton btn = - QMessageBox::critical(this, title, message, - QMessageBox::Ok|QMessageBox::Abort); - if(btn == QMessageBox::Abort) - { - return; - } - } - } - this->done(0); -} - -void QMacInstallDialog::SkipInstall() -{ - this->done(0); -} - - -void QMacInstallDialog::ShowBrowser() -{ - QString dir = QFileDialog::getExistingDirectory(this, - tr("Enter Install Prefix"), this->Internals->InstallPrefix->text()); - if(!dir.isEmpty()) - { - this->Internals->InstallPrefix->setText(dir); - } -} diff --git a/Source/QtDialog/QMacInstallDialog.h b/Source/QtDialog/QMacInstallDialog.h deleted file mode 100644 index efe67df..0000000 --- a/Source/QtDialog/QMacInstallDialog.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef QMacInstallDialog_h -#define QMacInstallDialog_h -#include <QDialog> - -class QMacInstallDialog : public QDialog -{ - Q_OBJECT; -public: - QMacInstallDialog(QWidget*w); - ~QMacInstallDialog(); -private slots: - void ShowBrowser(); - void SkipInstall(); - void DoInstall(); -private: - class QMacInstallDialogInternals; - QMacInstallDialogInternals* Internals; -}; - -#endif diff --git a/Source/QtIFW/controlscript.qs b/Source/QtIFW/controlscript.qs new file mode 100644 index 0000000..d1a9b10 --- /dev/null +++ b/Source/QtIFW/controlscript.qs @@ -0,0 +1,6 @@ +// controlscript.qs - CMake installation control script + +function Controller() +{ + // do nothing now +} diff --git a/Source/QtIFW/installscript.qs.in b/Source/QtIFW/installscript.qs.in index 5491611..570dba1 100644 --- a/Source/QtIFW/installscript.qs.in +++ b/Source/QtIFW/installscript.qs.in @@ -18,7 +18,7 @@ Component.prototype.createOperations = function() installer.value("StartMenuDir") + "/CMake Web Site.lnk"); component.addOperation("CreateShortcut", - installer.value("TargetDir") + "/uninstall.exe", - installer.value("StartMenuDir") + "/Uninstall.lnk"); + installer.value("TargetDir") + "/cmake-maintenance.exe", + installer.value("StartMenuDir") + "/CMake Maintenance Tool.lnk"); } } diff --git a/Source/cmAddCustomCommandCommand.cxx b/Source/cmAddCustomCommandCommand.cxx index ba9e663..fe516ea 100644 --- a/Source/cmAddCustomCommandCommand.cxx +++ b/Source/cmAddCustomCommandCommand.cxx @@ -380,8 +380,7 @@ bool cmAddCustomCommandCommand switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0050)) { case cmPolicies::WARN: - e << (this->Makefile->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0050)) << "\n"; + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0050) << "\n"; break; case cmPolicies::OLD: issueMessage = false; diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx index c246aee..42bd71c 100644 --- a/Source/cmAddCustomTargetCommand.cxx +++ b/Source/cmAddCustomTargetCommand.cxx @@ -194,8 +194,7 @@ bool cmAddCustomTargetCommand switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0037)) { case cmPolicies::WARN: - e << (this->Makefile->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0037)) << "\n"; + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0037) << "\n"; issueMessage = true; case cmPolicies::OLD: break; diff --git a/Source/cmAddExecutableCommand.cxx b/Source/cmAddExecutableCommand.cxx index 74dc8eb..d15fc1e 100644 --- a/Source/cmAddExecutableCommand.cxx +++ b/Source/cmAddExecutableCommand.cxx @@ -84,8 +84,7 @@ bool cmAddExecutableCommand switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0037)) { case cmPolicies::WARN: - e << (this->Makefile->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0037)) << "\n"; + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0037) << "\n"; issueMessage = true; case cmPolicies::OLD: break; diff --git a/Source/cmAddLibraryCommand.cxx b/Source/cmAddLibraryCommand.cxx index 74e1a93..a844cf1 100644 --- a/Source/cmAddLibraryCommand.cxx +++ b/Source/cmAddLibraryCommand.cxx @@ -222,8 +222,7 @@ bool cmAddLibraryCommand case cmPolicies::WARN: if(type != cmTarget::INTERFACE_LIBRARY) { - e << (this->Makefile->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0037)) << "\n"; + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0037) << "\n"; issueMessage = true; } case cmPolicies::OLD: diff --git a/Source/cmBreakCommand.cxx b/Source/cmBreakCommand.cxx index 34245b3..fc0c3f5 100644 --- a/Source/cmBreakCommand.cxx +++ b/Source/cmBreakCommand.cxx @@ -23,8 +23,7 @@ bool cmBreakCommand::InitialPass(std::vector<std::string> const &args, switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0055)) { case cmPolicies::WARN: - e << (this->Makefile->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0055)) << "\n"; + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0055) << "\n"; break; case cmPolicies::OLD: issueMessage = false; @@ -58,8 +57,7 @@ bool cmBreakCommand::InitialPass(std::vector<std::string> const &args, switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0055)) { case cmPolicies::WARN: - e << (this->Makefile->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0055)) << "\n"; + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0055) << "\n"; break; case cmPolicies::OLD: issueMessage = false; diff --git a/Source/cmBuildCommand.cxx b/Source/cmBuildCommand.cxx index cdca792..62fafa5 100644 --- a/Source/cmBuildCommand.cxx +++ b/Source/cmBuildCommand.cxx @@ -105,9 +105,9 @@ bool cmBuildCommand "Ignoring PROJECT_NAME option because it has no effect."); } - std::string makecommand = this->Makefile->GetLocalGenerator() - ->GetGlobalGenerator()->GenerateCMakeBuildCommand(target, configuration, - "", true); + std::string makecommand = this->Makefile->GetGlobalGenerator() + ->GenerateCMakeBuildCommand(target, configuration, "", + this->Makefile->IgnoreErrorsCMP0061()); this->Makefile->AddDefinition(variable, makecommand.c_str()); @@ -130,14 +130,14 @@ bool cmBuildCommand std::string configType = "Release"; const char* cfg = getenv("CMAKE_CONFIG_TYPE"); - if ( cfg ) + if ( cfg && *cfg ) { configType = cfg; } - std::string makecommand = this->Makefile->GetLocalGenerator() - ->GetGlobalGenerator()->GenerateCMakeBuildCommand("", configType, - "", true); + std::string makecommand = this->Makefile->GetGlobalGenerator() + ->GenerateCMakeBuildCommand("", configType, "", + this->Makefile->IgnoreErrorsCMP0061()); if(cacheValue) { diff --git a/Source/cmBuildCommand.h b/Source/cmBuildCommand.h index 3fb618f..979abc0 100644 --- a/Source/cmBuildCommand.h +++ b/Source/cmBuildCommand.h @@ -53,6 +53,8 @@ public: virtual std::string GetName() const {return "build_command";} cmTypeMacro(cmBuildCommand, cmCommand); +private: + bool IgnoreErrors() const; }; #endif diff --git a/Source/cmCMakePolicyCommand.cxx b/Source/cmCMakePolicyCommand.cxx index 9662fbf..3c878bf 100644 --- a/Source/cmCMakePolicyCommand.cxx +++ b/Source/cmCMakePolicyCommand.cxx @@ -111,7 +111,7 @@ bool cmCMakePolicyCommand::HandleGetMode(std::vector<std::string> const& args) // Lookup the policy number. cmPolicies::PolicyID pid; - if(!this->Makefile->GetPolicies()->GetPolicyID(id.c_str(), pid)) + if(!cmPolicies::GetPolicyID(id.c_str(), pid)) { std::ostringstream e; e << "GET given policy \"" << id << "\" which is not known to this " @@ -141,7 +141,7 @@ bool cmCMakePolicyCommand::HandleGetMode(std::vector<std::string> const& args) // The policy is required to be set before anything needs it. { std::ostringstream e; - e << this->Makefile->GetPolicies()->GetRequiredPolicyError(pid) + e << cmPolicies::GetRequiredPolicyError(pid) << "\n" << "The call to cmake_policy(GET " << id << " ...) at which this " << "error appears requests the policy, and this version of CMake " diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 403a459..e3b7a2b 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -28,6 +28,7 @@ #include "cmCTestStartCommand.h" #include "cmAlgorithms.h" #include "cmState.h" +#include "cmXMLWriter.h" #include "cmCTestBuildHandler.h" #include "cmCTestBuildAndTestHandler.h" @@ -510,9 +511,10 @@ int cmCTest::Initialize(const char* binary_dir, cmCTestStartCommand* command) } cmake cm; - cmGlobalGenerator gg; - gg.SetCMakeInstance(&cm); - cmsys::auto_ptr<cmLocalGenerator> lg(gg.CreateLocalGenerator()); + cm.SetHomeDirectory(""); + cm.SetHomeOutputDirectory(""); + cmGlobalGenerator gg(&cm); + cmsys::auto_ptr<cmLocalGenerator> lg(gg.MakeLocalGenerator()); cmMakefile *mf = lg->GetMakefile(); if ( !this->ReadCustomConfigurationFileTree(this->BinaryDir.c_str(), mf) ) { @@ -1488,7 +1490,7 @@ std::string cmCTest::SafeBuildIdField(const std::string& value) } //---------------------------------------------------------------------- -void cmCTest::StartXML(std::ostream& ostr, bool append) +void cmCTest::StartXML(cmXMLWriter& xml, bool append) { if(this->CurrentTag.empty()) { @@ -1511,42 +1513,45 @@ void cmCTest::StartXML(std::ostream& ostr, bool append) std::string site = cmCTest::SafeBuildIdField( this->GetCTestConfiguration("Site")); - ostr << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" - << "<Site BuildName=\"" << buildname << "\"\n" - << "\tBuildStamp=\"" << stamp << "\"\n" - << "\tName=\"" << site << "\"\n" - << "\tGenerator=\"ctest-" << cmVersion::GetCMakeVersion() << "\"\n" - << (append? "\tAppend=\"true\"\n":"") - << "\tCompilerName=\"" << this->GetCTestConfiguration("Compiler") - << "\"\n" + xml.StartDocument(); + xml.StartElement("Site"); + xml.Attribute("BuildName", buildname); + xml.BreakAttributes(); + xml.Attribute("BuildStamp", stamp); + xml.Attribute("Name", site); + xml.Attribute("Generator", + std::string("ctest-") + cmVersion::GetCMakeVersion()); + if(append) + { + xml.Attribute("Append", "true"); + } + xml.Attribute("CompilerName", this->GetCTestConfiguration("Compiler")); #ifdef _COMPILER_VERSION - << "\tCompilerVersion=\"_COMPILER_VERSION\"\n" + xml.Attribute("CompilerVersion", _COMPILER_VERSION); #endif - << "\tOSName=\"" << info.GetOSName() << "\"\n" - << "\tHostname=\"" << info.GetHostname() << "\"\n" - << "\tOSRelease=\"" << info.GetOSRelease() << "\"\n" - << "\tOSVersion=\"" << info.GetOSVersion() << "\"\n" - << "\tOSPlatform=\"" << info.GetOSPlatform() << "\"\n" - << "\tIs64Bits=\"" << info.Is64Bits() << "\"\n" - << "\tVendorString=\"" << info.GetVendorString() << "\"\n" - << "\tVendorID=\"" << info.GetVendorID() << "\"\n" - << "\tFamilyID=\"" << info.GetFamilyID() << "\"\n" - << "\tModelID=\"" << info.GetModelID() << "\"\n" - << "\tProcessorCacheSize=\"" << info.GetProcessorCacheSize() << "\"\n" - << "\tNumberOfLogicalCPU=\"" << info.GetNumberOfLogicalCPU() << "\"\n" - << "\tNumberOfPhysicalCPU=\""<< info.GetNumberOfPhysicalCPU() << "\"\n" - << "\tTotalVirtualMemory=\"" << info.GetTotalVirtualMemory() << "\"\n" - << "\tTotalPhysicalMemory=\""<< info.GetTotalPhysicalMemory() << "\"\n" - << "\tLogicalProcessorsPerPhysical=\"" - << info.GetLogicalProcessorsPerPhysical() << "\"\n" - << "\tProcessorClockFrequency=\"" - << info.GetProcessorClockFrequency() << "\"\n" - << ">" << std::endl; - this->AddSiteProperties(ostr); -} - -//---------------------------------------------------------------------- -void cmCTest::AddSiteProperties(std::ostream& ostr) + xml.Attribute("OSName", info.GetOSName()); + xml.Attribute("Hostname", info.GetHostname()); + xml.Attribute("OSRelease", info.GetOSRelease()); + xml.Attribute("OSVersion", info.GetOSVersion()); + xml.Attribute("OSPlatform", info.GetOSPlatform()); + xml.Attribute("Is64Bits", info.Is64Bits()); + xml.Attribute("VendorString", info.GetVendorString()); + xml.Attribute("VendorID", info.GetVendorID()); + xml.Attribute("FamilyID", info.GetFamilyID()); + xml.Attribute("ModelID", info.GetModelID()); + xml.Attribute("ProcessorCacheSize", info.GetProcessorCacheSize()); + xml.Attribute("NumberOfLogicalCPU", info.GetNumberOfLogicalCPU()); + xml.Attribute("NumberOfPhysicalCPU", info.GetNumberOfPhysicalCPU()); + xml.Attribute("TotalVirtualMemory", info.GetTotalVirtualMemory()); + xml.Attribute("TotalPhysicalMemory", info.GetTotalPhysicalMemory()); + xml.Attribute("LogicalProcessorsPerPhysical", + info.GetLogicalProcessorsPerPhysical()); + xml.Attribute("ProcessorClockFrequency", info.GetProcessorClockFrequency()); + this->AddSiteProperties(xml); +} + +//---------------------------------------------------------------------- +void cmCTest::AddSiteProperties(cmXMLWriter& xml) { cmCTestScriptHandler* ch = static_cast<cmCTestScriptHandler*>(this->GetHandler("script")); @@ -1562,92 +1567,95 @@ void cmCTest::AddSiteProperties(std::ostream& ostr) ->GetGlobalProperty("SubProject"); if(subproject) { - ostr << "<Subproject name=\"" << subproject << "\">\n"; + xml.StartElement("Subproject"); + xml.Attribute("name", subproject); const char* labels = ch->GetCMake()->GetState() ->GetGlobalProperty("SubProjectLabels"); if(labels) { - ostr << " <Labels>\n"; + xml.StartElement("Labels"); std::string l = labels; std::vector<std::string> args; cmSystemTools::ExpandListArgument(l, args); for(std::vector<std::string>::iterator i = args.begin(); i != args.end(); ++i) { - ostr << " <Label>" << *i << "</Label>\n"; + xml.Element("Label", *i); } - ostr << " </Labels>\n"; + xml.EndElement(); } - ostr << "</Subproject>\n"; + xml.EndElement(); } // This code should stay when cdash only does label based sub-projects const char* label = cm->GetState()->GetGlobalProperty("Label"); if(label) { - ostr << "<Labels>\n"; - ostr << " <Label>" << label << "</Label>\n"; - ostr << "</Labels>\n"; + xml.StartElement("Labels"); + xml.Element("Label", label); + xml.EndElement(); } } - //---------------------------------------------------------------------- -void cmCTest::EndXML(std::ostream& ostr) +void cmCTest::EndXML(cmXMLWriter& xml) { - ostr << "</Site>" << std::endl; + xml.EndElement(); // Site + xml.EndDocument(); } //---------------------------------------------------------------------- -int cmCTest::GenerateCTestNotesOutput(std::ostream& os, +int cmCTest::GenerateCTestNotesOutput(cmXMLWriter& xml, const cmCTest::VectorOfStrings& files) { std::string buildname = cmCTest::SafeBuildIdField( this->GetCTestConfiguration("BuildName")); cmCTest::VectorOfStrings::const_iterator it; - os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" - << "<?xml-stylesheet type=\"text/xsl\" " + xml.StartDocument(); + xml.ProcessingInstruction("xml-stylesheet", "type=\"text/xsl\" " "href=\"Dart/Source/Server/XSL/Build.xsl " - "<file:///Dart/Source/Server/XSL/Build.xsl> \"?>\n" - << "<Site BuildName=\"" << buildname - << "\" BuildStamp=\"" - << this->CurrentTag << "-" << this->GetTestModelString() << "\" Name=\"" - << this->GetCTestConfiguration("Site") << "\" Generator=\"ctest" - << cmVersion::GetCMakeVersion() - << "\">\n"; - this->AddSiteProperties(os); - os << "<Notes>" << std::endl; + "<file:///Dart/Source/Server/XSL/Build.xsl> \""); + xml.StartElement("Site"); + xml.Attribute("BuildName", buildname); + xml.Attribute("BuildStamp", this->CurrentTag+"-"+this->GetTestModelString()); + xml.Attribute("Name", this->GetCTestConfiguration("Site")); + xml.Attribute("Generator",std::string("ctest")+cmVersion::GetCMakeVersion()); + this->AddSiteProperties(xml); + xml.StartElement("Notes"); for ( it = files.begin(); it != files.end(); it ++ ) { cmCTestLog(this, OUTPUT, "\tAdd file: " << *it << std::endl); std::string note_time = this->CurrentTime(); - os << "<Note Name=\"" << cmXMLSafe(*it) << "\">\n" - << "<Time>" << cmSystemTools::GetTime() << "</Time>\n" - << "<DateTime>" << note_time << "</DateTime>\n" - << "<Text>" << std::endl; + xml.StartElement("Note"); + xml.Attribute("Name", *it); + xml.Element("Time", cmSystemTools::GetTime()); + xml.Element("DateTime", note_time); + xml.StartElement("Text"); cmsys::ifstream ifs(it->c_str()); if ( ifs ) { std::string line; while ( cmSystemTools::GetLineFromStream(ifs, line) ) { - os << cmXMLSafe(line) << std::endl; + xml.Content(line); + xml.Content("\n"); } ifs.close(); } else { - os << "Problem reading file: " << *it << std::endl; + xml.Content("Problem reading file: " + *it + "\n"); cmCTestLog(this, ERROR_MESSAGE, "Problem reading file: " << *it << " while creating notes" << std::endl); } - os << "</Text>\n" - << "</Note>" << std::endl; + xml.EndElement(); // Text + xml.EndElement(); // Note } - os << "</Notes>\n" - << "</Site>" << std::endl; + xml.EndElement(); // Notes + xml.EndElement(); // Site + xml.EndDocument(); return 1; } @@ -1660,8 +1668,8 @@ int cmCTest::GenerateNotesFile(const VectorOfStrings &files) cmCTestLog(this, ERROR_MESSAGE, "Cannot open notes file" << std::endl); return 1; } - - this->GenerateCTestNotesOutput(ofs, files); + cmXMLWriter xml(ofs); + this->GenerateCTestNotesOutput(xml, files); return 0; } diff --git a/Source/cmCTest.h b/Source/cmCTest.h index 3f033d9..db3ea10 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -24,6 +24,7 @@ class cmGeneratedFileStream; class cmCTestCommand; class cmCTestScriptHandler; class cmCTestStartCommand; +class cmXMLWriter; #define cmCTestLog(ctSelf, logType, msg) \ do { \ @@ -273,10 +274,10 @@ public: static std::string SafeBuildIdField(const std::string& value); //! Start CTest XML output file - void StartXML(std::ostream& ostr, bool append); + void StartXML(cmXMLWriter& xml, bool append); //! End CTest XML output file - void EndXML(std::ostream& ostr); + void EndXML(cmXMLWriter& xml); //! Run command specialized for make and configure. Returns process status // and retVal is return value or exception. @@ -420,7 +421,7 @@ public: /** Direct process output to given streams. */ void SetStreams(std::ostream* out, std::ostream* err) { this->StreamOut = out; this->StreamErr = err; } - void AddSiteProperties(std::ostream& ); + void AddSiteProperties(cmXMLWriter& xml); bool GetLabelSummary() { return this->LabelSummary;} std::string GetCostDataFile(); @@ -553,7 +554,7 @@ private: bool UpdateCTestConfiguration(); //! Create note from files. - int GenerateCTestNotesOutput(std::ostream& os, + int GenerateCTestNotesOutput(cmXMLWriter& xml, const VectorOfStrings& files); //! Check if the argument is the one specified diff --git a/Source/cmCacheManager.cxx b/Source/cmCacheManager.cxx index 289d0dc..108208e 100644 --- a/Source/cmCacheManager.cxx +++ b/Source/cmCacheManager.cxx @@ -407,14 +407,9 @@ bool cmCacheManager::SaveCache(const std::string& path) " was created", cmState::INTERNAL); fout << "# This is the CMakeCache file.\n" - << "# For build in directory: " << currentcwd << "\n"; - cmCacheManager::CacheEntry* cmakeCacheEntry - = this->GetCacheEntry("CMAKE_COMMAND"); - if ( cmakeCacheEntry ) - { - fout << "# It was generated by CMake: " << - cmakeCacheEntry->Value << std::endl; - } + << "# For build in directory: " << currentcwd << "\n" + << "# It was generated by CMake: " + << cmSystemTools::GetCMakeCommand() << std::endl; fout << "# You can edit this file to change values found and used by cmake." << std::endl diff --git a/Source/cmCommand.h b/Source/cmCommand.h index 6689243..0548c6b 100644 --- a/Source/cmCommand.h +++ b/Source/cmCommand.h @@ -180,7 +180,7 @@ public: { case cmPolicies::WARN: this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, - this->Makefile->GetPolicies()->GetPolicyWarning(pol)); + cmPolicies::GetPolicyWarning(pol)); case cmPolicies::OLD: return false; case cmPolicies::REQUIRED_IF_USED: diff --git a/Source/cmCommandArgumentParserHelper.cxx b/Source/cmCommandArgumentParserHelper.cxx index 0d1c86d..bd098a5 100644 --- a/Source/cmCommandArgumentParserHelper.cxx +++ b/Source/cmCommandArgumentParserHelper.cxx @@ -14,6 +14,7 @@ #include "cmSystemTools.h" #include "cmMakefile.h" #include "cmState.h" +#include "cmLocalGenerator.h" #include "cmCommandArgumentLexer.h" @@ -139,14 +140,14 @@ char* cmCommandArgumentParserHelper::ExpandVariable(const char* var) this->Makefile->GetHomeOutputDirectory())) { std::ostringstream msg; - cmListFileBacktrace bt(this->Makefile->GetLocalGenerator()); cmListFileContext lfc; - lfc.FilePath = this->FileName; + lfc.FilePath = this->Makefile->GetLocalGenerator() + ->Convert(this->FileName, cmLocalGenerator::HOME); + lfc.Line = this->FileLine; - bt.push_back(lfc); msg << "uninitialized variable \'" << var << "\'"; this->Makefile->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, - msg.str(), bt); + msg.str(), lfc); } } return 0; diff --git a/Source/cmComputeLinkDepends.cxx b/Source/cmComputeLinkDepends.cxx index 6005d5f..abd9877 100644 --- a/Source/cmComputeLinkDepends.cxx +++ b/Source/cmComputeLinkDepends.cxx @@ -13,7 +13,6 @@ #include "cmComputeComponentGraph.h" #include "cmGlobalGenerator.h" -#include "cmLocalGenerator.h" #include "cmMakefile.h" #include "cmTarget.h" #include "cmake.h" @@ -179,8 +178,7 @@ cmComputeLinkDepends // Store context information. this->Target = target; this->Makefile = this->Target->GetMakefile(); - this->LocalGenerator = this->Makefile->GetLocalGenerator(); - this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator(); + this->GlobalGenerator = this->Makefile->GetGlobalGenerator(); this->CMakeInstance = this->GlobalGenerator->GetCMakeInstance(); // The configuration being linked. diff --git a/Source/cmComputeLinkDepends.h b/Source/cmComputeLinkDepends.h index a931726..09b9d70 100644 --- a/Source/cmComputeLinkDepends.h +++ b/Source/cmComputeLinkDepends.h @@ -21,7 +21,6 @@ class cmComputeComponentGraph; class cmGlobalGenerator; -class cmLocalGenerator; class cmMakefile; class cmTarget; class cmake; @@ -60,7 +59,6 @@ private: // Context information. cmTarget const* Target; cmMakefile* Makefile; - cmLocalGenerator* LocalGenerator; cmGlobalGenerator const* GlobalGenerator; cmake* CMakeInstance; bool DebugMode; diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index 83d38ef..e6cbe60 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -247,7 +247,7 @@ cmComputeLinkInformation this->Target = target; this->Makefile = this->Target->GetMakefile(); this->LocalGenerator = this->Makefile->GetLocalGenerator(); - this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator(); + this->GlobalGenerator = this->Makefile->GetGlobalGenerator(); this->CMakeInstance = this->GlobalGenerator->GetCMakeInstance(); // Check whether to recognize OpenBSD-style library versioned names. @@ -556,8 +556,7 @@ bool cmComputeLinkInformation::Compute() if (!this->CMP0060WarnItems.empty()) { std::ostringstream w; - w << (this->Makefile->GetCMakeInstance()->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0060)) << "\n" + w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0060) << "\n" "Some library files are in directories implicitly searched by " "the linker when invoked for " << this->LinkLanguage << ":\n" " " << cmJoin(this->CMP0060WarnItems, "\n ") << "\n" @@ -653,6 +652,13 @@ void cmComputeLinkInformation::AddItem(std::string const& item, this->Items.push_back(Item(linkItem, true, tgt)); this->Depends.push_back(exe); } + else if(tgt->GetType() == cmTarget::INTERFACE_LIBRARY) + { + // Add the interface library as an item so it can be considered as part + // of COMPATIBLE_INTERFACE_ enforcement. The generators will ignore + // this for the actual link line. + this->Items.push_back(Item(std::string(), true, tgt)); + } else { // Decide whether to use an import library. @@ -660,11 +666,6 @@ void cmComputeLinkInformation::AddItem(std::string const& item, (this->UseImportLibrary && (impexe || tgt->GetType() == cmTarget::SHARED_LIBRARY)); - if(tgt->GetType() == cmTarget::INTERFACE_LIBRARY) - { - this->Items.push_back(Item(std::string(), true, tgt)); - return; - } // Pass the full path to the target file. std::string lib = tgt->GetFullPath(config, implib, true); if(!this->LinkDependsNoShared || @@ -1532,8 +1533,7 @@ void cmComputeLinkInformation::HandleBadFullItem(std::string const& item, { this->CMakeInstance->GetState()->SetGlobalProperty(wid, "1"); std::ostringstream w; - w << (this->Makefile->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0008)) << "\n" + w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0008) << "\n" << "Target \"" << this->Target->GetName() << "\" links to item\n" << " " << item << "\n" << "which is a full-path but not a valid library file name."; @@ -1551,8 +1551,7 @@ void cmComputeLinkInformation::HandleBadFullItem(std::string const& item, case cmPolicies::REQUIRED_ALWAYS: { std::ostringstream e; - e << (this->Makefile->GetPolicies()-> - GetRequiredPolicyError(cmPolicies::CMP0008)) << "\n" + e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0008) << "\n" << "Target \"" << this->Target->GetName() << "\" links to item\n" << " " << item << "\n" << "which is a full-path but not a valid library file name."; @@ -1598,8 +1597,7 @@ bool cmComputeLinkInformation::FinishLinkerSearchDirectories() case cmPolicies::REQUIRED_ALWAYS: { std::ostringstream e; - e << (this->Makefile->GetPolicies()-> - GetRequiredPolicyError(cmPolicies::CMP0003)) << "\n"; + e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0003) << "\n"; this->PrintLinkPolicyDiagnosis(e); this->CMakeInstance->IssueMessage(cmake::FATAL_ERROR, e.str(), this->Target->GetBacktrace()); diff --git a/Source/cmComputeTargetDepends.cxx b/Source/cmComputeTargetDepends.cxx index 11056cd..87b47b4 100644 --- a/Source/cmComputeTargetDepends.cxx +++ b/Source/cmComputeTargetDepends.cxx @@ -216,9 +216,7 @@ void cmComputeTargetDepends::CollectTargetDepends(int depender_index) // deal with config-specific dependencies. { std::set<std::string> emitted; - cmGeneratorTarget* gt = depender->GetMakefile()->GetLocalGenerator() - ->GetGlobalGenerator() - ->GetGeneratorTarget(depender); + cmGeneratorTarget* gt = this->GlobalGenerator->GetGeneratorTarget(depender); std::vector<std::string> configs; depender->GetMakefile()->GetConfigurations(configs); @@ -361,15 +359,13 @@ void cmComputeTargetDepends::AddTargetDepend( if(!dependee && !linking && (depender->GetType() != cmTarget::GLOBAL_TARGET)) { - cmMakefile *makefile = depender->GetMakefile(); cmake::MessageType messageType = cmake::AUTHOR_WARNING; bool issueMessage = false; std::ostringstream e; switch(depender->GetPolicyStatusCMP0046()) { case cmPolicies::WARN: - e << (makefile->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0046)) << "\n"; + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0046) << "\n"; issueMessage = true; case cmPolicies::OLD: break; diff --git a/Source/cmConditionEvaluator.cxx b/Source/cmConditionEvaluator.cxx index 0a71c60..61847d4 100644 --- a/Source/cmConditionEvaluator.cxx +++ b/Source/cmConditionEvaluator.cxx @@ -15,7 +15,8 @@ cmConditionEvaluator::cmConditionEvaluator(cmMakefile& makefile): Makefile(makefile), Policy12Status(makefile.GetPolicyStatus(cmPolicies::CMP0012)), - Policy54Status(makefile.GetPolicyStatus(cmPolicies::CMP0054)) + Policy54Status(makefile.GetPolicyStatus(cmPolicies::CMP0054)), + Policy57Status(makefile.GetPolicyStatus(cmPolicies::CMP0057)) { } @@ -111,14 +112,10 @@ const char* cmConditionEvaluator::GetDefinitionIfUnquoted( if(def && argument.WasQuoted() && this->Policy54Status == cmPolicies::WARN) { - bool hasBeenReported = this->Makefile.HasCMP0054AlreadyBeenReported( - this->Makefile.GetBacktrace()[0]); - - if(!hasBeenReported) + if(!this->Makefile.HasCMP0054AlreadyBeenReported()) { std::ostringstream e; - e << (this->Makefile.GetPolicies()->GetPolicyWarning( - cmPolicies::CMP0054)) << "\n"; + e << (cmPolicies::GetPolicyWarning(cmPolicies::CMP0054)) << "\n"; e << "Quoted variables like \"" << argument.GetValue() << "\" will no longer be dereferenced " "when the policy is set to NEW. " @@ -161,14 +158,10 @@ bool cmConditionEvaluator::IsKeyword(std::string const& keyword, if(isKeyword && argument.WasQuoted() && this->Policy54Status == cmPolicies::WARN) { - bool hasBeenReported = this->Makefile.HasCMP0054AlreadyBeenReported( - this->Makefile.GetBacktrace()[0]); - - if(!hasBeenReported) + if(!this->Makefile.HasCMP0054AlreadyBeenReported()) { std::ostringstream e; - e << (this->Makefile.GetPolicies()->GetPolicyWarning( - cmPolicies::CMP0054)) << "\n"; + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0054) << "\n"; e << "Quoted keywords like \"" << argument.GetValue() << "\" will no longer be interpreted as keywords " "when the policy is set to NEW. " @@ -279,10 +272,9 @@ bool cmConditionEvaluator::GetBooleanValueWithAutoDereference( { case cmPolicies::WARN: { - cmPolicies* policies = this->Makefile.GetPolicies(); errorString = "An argument named \"" + newArg.GetValue() + "\" appears in a conditional statement. " - + policies->GetPolicyWarning(cmPolicies::CMP0012); + + cmPolicies::GetPolicyWarning(cmPolicies::CMP0012); status = cmake::AUTHOR_WARNING; } case cmPolicies::OLD: @@ -290,10 +282,9 @@ bool cmConditionEvaluator::GetBooleanValueWithAutoDereference( case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: { - cmPolicies* policies = this->Makefile.GetPolicies(); errorString = "An argument named \"" + newArg.GetValue() + "\" appears in a conditional statement. " - + policies->GetRequiredPolicyError(cmPolicies::CMP0012); + + cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0012); status = cmake::FATAL_ERROR; } case cmPolicies::NEW: @@ -492,8 +483,7 @@ bool cmConditionEvaluator::HandleLevel1(cmArgumentList &newArgs, { cmPolicies::PolicyID pid; this->HandlePredicate( - this->Makefile.GetPolicies()->GetPolicyID( - argP1->c_str(), pid), + cmPolicies::GetPolicyID(argP1->c_str(), pid), reducible, arg, newArgs, argP1, argP2); } // does a target exist @@ -676,6 +666,40 @@ bool cmConditionEvaluator::HandleLevel2(cmArgumentList &newArgs, reducible, arg, newArgs, argP1, argP2); } + if (argP1 != newArgs.end() && argP2 != newArgs.end() && + this->IsKeyword("IN_LIST", *argP1)) + { + if(this->Policy57Status != cmPolicies::OLD && + this->Policy57Status != cmPolicies::WARN) + { + bool result = false; + + def = this->GetVariableOrString(*arg); + def2 = this->Makefile.GetDefinition(argP2->GetValue()); + + if(def2) + { + std::vector<std::string> list; + cmSystemTools::ExpandListArgument(def2, list, true); + + result = std::find(list.begin(), list.end(), def) != list.end(); + } + + this->HandleBinaryOp(result, + reducible, arg, newArgs, argP1, argP2); + } + else if(this->Policy57Status == cmPolicies::WARN) + { + std::ostringstream e; + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0057) << "\n"; + e << "IN_LIST will be interpreted as an operator " + "when the policy is set to NEW. " + "Since the policy is not set the OLD behavior will be used."; + + this->Makefile.IssueMessage(cmake::AUTHOR_WARNING, e.str()); + } + } + ++arg; } } diff --git a/Source/cmConditionEvaluator.h b/Source/cmConditionEvaluator.h index fcef234..c923d76 100644 --- a/Source/cmConditionEvaluator.h +++ b/Source/cmConditionEvaluator.h @@ -93,6 +93,7 @@ private: cmMakefile& Makefile; cmPolicies::PolicyStatus Policy12Status; cmPolicies::PolicyStatus Policy54Status; + cmPolicies::PolicyStatus Policy57Status; }; #endif diff --git a/Source/cmConfigure.cmake.h.in b/Source/cmConfigure.cmake.h.in index c0a1aa9..62128a7 100644 --- a/Source/cmConfigure.cmake.h.in +++ b/Source/cmConfigure.cmake.h.in @@ -14,4 +14,5 @@ #cmakedefine CMAKE_USE_ELF_PARSER #cmakedefine CMAKE_USE_MACH_PARSER #cmakedefine CMAKE_ENCODING_UTF8 +#cmakedefine CMake_HAVE_CXX11_UNORDERED_MAP #define CMAKE_DATA_DIR "/@CMAKE_DATA_DIR@" diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 56a884c..dd276a8 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -242,8 +242,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv) } // Detect languages to enable. - cmLocalGenerator* lg = this->Makefile->GetLocalGenerator(); - cmGlobalGenerator* gg = lg->GetGlobalGenerator(); + cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator(); std::set<std::string> testLangs; for(std::vector<std::string>::iterator si = sources.begin(); si != sources.end(); ++si) @@ -323,7 +322,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv) std::string langFlags = "CMAKE_" + *li + "_FLAGS"; const char* flags = this->Makefile->GetDefinition(langFlags); fprintf(fout, "set(CMAKE_%s_FLAGS %s)\n", li->c_str(), - lg->EscapeForCMake(flags?flags:"").c_str()); + cmLocalGenerator::EscapeForCMake(flags?flags:"").c_str()); fprintf(fout, "set(CMAKE_%s_FLAGS \"${CMAKE_%s_FLAGS}" " ${COMPILE_DEFINITIONS}\")\n", li->c_str(), li->c_str()); } @@ -334,8 +333,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv) "CMAKE_POLICY_WARNING_CMP0056")) { std::ostringstream w; - w << (this->Makefile->GetCMakeInstance()->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0056)) << "\n" + w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0056) << "\n" "For compatibility with older versions of CMake, try_compile " "is not honoring caller link flags (e.g. CMAKE_EXE_LINKER_FLAGS) " "in the test project." @@ -349,8 +347,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv) case cmPolicies::REQUIRED_ALWAYS: this->Makefile->IssueMessage( cmake::FATAL_ERROR, - this->Makefile->GetCMakeInstance()->GetPolicies() - ->GetRequiredPolicyError(cmPolicies::CMP0056) + cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0056) ); case cmPolicies::NEW: // NEW behavior is to pass linker flags. @@ -358,7 +355,8 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv) const char* exeLinkFlags = this->Makefile->GetDefinition("CMAKE_EXE_LINKER_FLAGS"); fprintf(fout, "set(CMAKE_EXE_LINKER_FLAGS %s)\n", - lg->EscapeForCMake(exeLinkFlags?exeLinkFlags:"").c_str()); + cmLocalGenerator::EscapeForCMake( + exeLinkFlags ? exeLinkFlags : "").c_str()); } break; } fprintf(fout, "set(CMAKE_EXE_LINKER_FLAGS \"${CMAKE_EXE_LINKER_FLAGS}" diff --git a/Source/cmCustomCommandGenerator.cxx b/Source/cmCustomCommandGenerator.cxx index 162d7a1..d23f815 100644 --- a/Source/cmCustomCommandGenerator.cxx +++ b/Source/cmCustomCommandGenerator.cxx @@ -51,6 +51,35 @@ std::string cmCustomCommandGenerator::GetCommand(unsigned int c) const } //---------------------------------------------------------------------------- +std::string escapeForShellOldStyle(const std::string& str) +{ + std::string result; +#if defined(_WIN32) && !defined(__CYGWIN__) + // if there are spaces + std::string temp = str; + if (temp.find(" ") != std::string::npos && + temp.find("\"")==std::string::npos) + { + result = "\""; + result += str; + result += "\""; + return result; + } + return str; +#else + for(const char* ch = str.c_str(); *ch != '\0'; ++ch) + { + if(*ch == ' ') + { + result += '\\'; + } + result += *ch; + } + return result; +#endif +} + +//---------------------------------------------------------------------------- void cmCustomCommandGenerator ::AppendArguments(unsigned int c, std::string& cmd) const @@ -63,7 +92,7 @@ cmCustomCommandGenerator cmd += " "; if(this->OldStyle) { - cmd += this->LG->EscapeForShellOldStyle(arg); + cmd += escapeForShellOldStyle(arg); } else { diff --git a/Source/cmDefinitions.cxx b/Source/cmDefinitions.cxx index abb46b3..2dab169 100644 --- a/Source/cmDefinitions.cxx +++ b/Source/cmDefinitions.cxx @@ -11,145 +11,138 @@ ============================================================================*/ #include "cmDefinitions.h" -//---------------------------------------------------------------------------- -cmDefinitions::Def cmDefinitions::NoDef; +#include <assert.h> //---------------------------------------------------------------------------- -cmDefinitions::cmDefinitions(cmDefinitions* parent) - : Up(parent) -{ -} +cmDefinitions::Def cmDefinitions::NoDef; //---------------------------------------------------------------------------- -cmDefinitions::Def const& -cmDefinitions::GetInternal(const std::string& key) +cmDefinitions::Def const& cmDefinitions::GetInternal( + const std::string& key, StackIter begin, StackIter end, bool raise) { - MapType::const_iterator i = this->Map.find(key); - if(i != this->Map.end()) + assert(begin != end); + MapType::iterator i = begin->Map.find(key); + if (i != begin->Map.end()) { + i->second.Used = true; return i->second; } - if(cmDefinitions* up = this->Up) + StackIter it = begin; + ++it; + if (it == end) + { + return cmDefinitions::NoDef; + } + Def const& def = cmDefinitions::GetInternal(key, it, end, raise); + if (!raise) { - // Query the parent scope and store the result locally. - Def def = up->GetInternal(key); - return this->Map.insert(MapType::value_type(key, def)).first->second; + return def; } - return this->NoDef; + return begin->Map.insert(MapType::value_type(key, def)).first->second; } //---------------------------------------------------------------------------- -const char* cmDefinitions::Get(const std::string& key) +const char* cmDefinitions::Get(const std::string& key, + StackIter begin, StackIter end) { - Def const& def = this->GetInternal(key); + Def const& def = cmDefinitions::GetInternal(key, begin, end, false); return def.Exists? def.c_str() : 0; } +void cmDefinitions::Raise(const std::string& key, + StackIter begin, StackIter end) +{ + cmDefinitions::GetInternal(key, begin, end, true); +} + +bool cmDefinitions::HasKey(const std::string& key, + StackConstIter begin, StackConstIter end) +{ + for (StackConstIter it = begin; it != end; ++it) + { + MapType::const_iterator i = it->Map.find(key); + if (i != it->Map.end()) + { + return true; + } + } + return false; +} + //---------------------------------------------------------------------------- void cmDefinitions::Set(const std::string& key, const char* value) { Def def(value); - if(this->Up || def.Exists) - { - // In lower scopes we store keys, defined or not. - this->Map[key] = def; - } - else - { - // In the top-most scope we need not store undefined keys. - this->Map.erase(key); - } + this->Map[key] = def; } //---------------------------------------------------------------------------- -std::set<std::string> cmDefinitions::LocalKeys() const +std::vector<std::string> cmDefinitions::UnusedKeys() const { - std::set<std::string> keys; + std::vector<std::string> keys; + keys.reserve(this->Map.size()); // Consider local definitions. for(MapType::const_iterator mi = this->Map.begin(); mi != this->Map.end(); ++mi) { - if (mi->second.Exists) + if (!mi->second.Used) { - keys.insert(mi->first); + keys.push_back(mi->first); } } return keys; } //---------------------------------------------------------------------------- -cmDefinitions cmDefinitions::Closure() const -{ - return cmDefinitions(ClosureTag(), this); -} - -//---------------------------------------------------------------------------- -cmDefinitions::cmDefinitions(ClosureTag const&, cmDefinitions const* root): - Up(0) +cmDefinitions cmDefinitions::MakeClosure(StackConstIter begin, + StackConstIter end) { + cmDefinitions closure; std::set<std::string> undefined; - this->ClosureImpl(undefined, root); -} - -//---------------------------------------------------------------------------- -void cmDefinitions::ClosureImpl(std::set<std::string>& undefined, - cmDefinitions const* defs) -{ - // Consider local definitions. - for(MapType::const_iterator mi = defs->Map.begin(); - mi != defs->Map.end(); ++mi) + for (StackConstIter it = begin; it != end; ++it) { - // Use this key if it is not already set or unset. - if(this->Map.find(mi->first) == this->Map.end() && - undefined.find(mi->first) == undefined.end()) + // Consider local definitions. + for(MapType::const_iterator mi = it->Map.begin(); + mi != it->Map.end(); ++mi) { - if(mi->second.Exists) + // Use this key if it is not already set or unset. + if(closure.Map.find(mi->first) == closure.Map.end() && + undefined.find(mi->first) == undefined.end()) { - this->Map.insert(*mi); - } - else - { - undefined.insert(mi->first); + if(mi->second.Exists) + { + closure.Map.insert(*mi); + } + else + { + undefined.insert(mi->first); + } } } } - - // Traverse parents. - if(cmDefinitions const* up = defs->Up) - { - this->ClosureImpl(undefined, up); - } + return closure; } //---------------------------------------------------------------------------- -std::set<std::string> cmDefinitions::ClosureKeys() const +std::vector<std::string> +cmDefinitions::ClosureKeys(StackConstIter begin, StackConstIter end) { - std::set<std::string> defined; - std::set<std::string> undefined; - this->ClosureKeys(defined, undefined); - return defined; -} + std::set<std::string> bound; + std::vector<std::string> defined; -//---------------------------------------------------------------------------- -void cmDefinitions::ClosureKeys(std::set<std::string>& defined, - std::set<std::string>& undefined) const -{ - // Consider local definitions. - for(MapType::const_iterator mi = this->Map.begin(); - mi != this->Map.end(); ++mi) + for (StackConstIter it = begin; it != end; ++it) { - // Use this key if it is not already set or unset. - if(defined.find(mi->first) == defined.end() && - undefined.find(mi->first) == undefined.end()) + defined.reserve(defined.size() + it->Map.size()); + for(MapType::const_iterator mi = it->Map.begin(); + mi != it->Map.end(); ++mi) { - std::set<std::string>& m = mi->second.Exists? defined : undefined; - m.insert(mi->first); + // Use this key if it is not already set or unset. + if(bound.insert(mi->first).second && mi->second.Exists) + { + defined.push_back(mi->first); + } } } - // Traverse parents. - if(cmDefinitions const* up = this->Up) - { - up->ClosureKeys(defined, undefined); - } + return defined; } diff --git a/Source/cmDefinitions.h b/Source/cmDefinitions.h index 83cd0d9..5fdcaab 100644 --- a/Source/cmDefinitions.h +++ b/Source/cmDefinitions.h @@ -14,8 +14,14 @@ #include "cmStandardIncludes.h" #if defined(CMAKE_BUILD_WITH_CMAKE) +#ifdef CMake_HAVE_CXX11_UNORDERED_MAP +#include <unordered_map> +#else #include "cmsys/hash_map.hxx" #endif +#endif + +#include <list> /** \class cmDefinitions * \brief Store a scope of variable definitions for CMake language. @@ -26,29 +32,26 @@ */ class cmDefinitions { + typedef std::list<cmDefinitions>::reverse_iterator StackIter; + typedef std::list<cmDefinitions>::const_reverse_iterator StackConstIter; public: - /** Construct with the given parent scope. */ - cmDefinitions(cmDefinitions* parent = 0); + static const char* Get(const std::string& key, + StackIter begin, StackIter end); - /** Returns the parent scope, if any. */ - cmDefinitions* GetParent() const { return this->Up; } + static void Raise(const std::string& key, StackIter begin, StackIter end); - /** Get the value associated with a key; null if none. - Store the result locally if it came from a parent. */ - const char* Get(const std::string& key); + static bool HasKey(const std::string& key, + StackConstIter begin, StackConstIter end); /** Set (or unset if null) a value associated with a key. */ void Set(const std::string& key, const char* value); - /** Get the set of all local keys. */ - std::set<std::string> LocalKeys() const; + std::vector<std::string> UnusedKeys() const; - /** Compute the closure of all defined keys with values. - This flattens the scope. The result has no parent. */ - cmDefinitions Closure() const; + static std::vector<std::string> ClosureKeys(StackConstIter begin, + StackConstIter end); - /** Compute the set of all defined keys. */ - std::set<std::string> ClosureKeys() const; + static cmDefinitions MakeClosure(StackConstIter begin, StackConstIter end); private: // String with existence boolean. @@ -57,37 +60,32 @@ private: private: typedef std::string std_string; public: - Def(): std_string(), Exists(false) {} - Def(const char* v): std_string(v?v:""), Exists(v?true:false) {} - Def(const std_string& v): std_string(v), Exists(true) {} - Def(Def const& d): std_string(d), Exists(d.Exists) {} + Def(): std_string(), Exists(false), Used(false) {} + Def(const char* v) + : std_string(v ? v : ""), + Exists(v ? true : false), + Used(false) + {} + Def(const std_string& v): std_string(v), Exists(true), Used(false) {} + Def(Def const& d): std_string(d), Exists(d.Exists), Used(d.Used) {} bool Exists; + bool Used; }; static Def NoDef; - // Parent scope, if any. - cmDefinitions* Up; - - // Local definitions, set or unset. #if defined(CMAKE_BUILD_WITH_CMAKE) +#ifdef CMake_HAVE_CXX11_UNORDERED_MAP + typedef std::unordered_map<std::string, Def> MapType; +#else typedef cmsys::hash_map<std::string, Def> MapType; +#endif #else typedef std::map<std::string, Def> MapType; #endif MapType Map; - // Internal query and update methods. - Def const& GetInternal(const std::string& key); - - // Implementation of Closure() method. - struct ClosureTag {}; - cmDefinitions(ClosureTag const&, cmDefinitions const* root); - void ClosureImpl(std::set<std::string>& undefined, - cmDefinitions const* defs); - - // Implementation of ClosureKeys() method. - void ClosureKeys(std::set<std::string>& defined, - std::set<std::string>& undefined) const; + static Def const& GetInternal(const std::string& key, + StackIter begin, StackIter end, bool raise); }; #endif diff --git a/Source/cmExecuteProcessCommand.cxx b/Source/cmExecuteProcessCommand.cxx index 1225992..a371390 100644 --- a/Source/cmExecuteProcessCommand.cxx +++ b/Source/cmExecuteProcessCommand.cxx @@ -255,7 +255,7 @@ bool cmExecuteProcessCommand cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1); // Check the output variables. - bool merge_output = (output_variable == error_variable); + bool merge_output = false; if(!input_file.empty()) { cmsysProcess_SetPipeFile(cp, cmsysProcess_Pipe_STDIN, input_file.c_str()); @@ -267,8 +267,23 @@ bool cmExecuteProcessCommand } if(!error_file.empty()) { - cmsysProcess_SetPipeFile(cp, cmsysProcess_Pipe_STDERR, - error_file.c_str()); + if (error_file == output_file) + { + merge_output = true; + } + else + { + cmsysProcess_SetPipeFile(cp, cmsysProcess_Pipe_STDERR, + error_file.c_str()); + } + } + if (!output_variable.empty() && output_variable == error_variable) + { + merge_output = true; + } + if (merge_output) + { + cmsysProcess_SetOption(cp, cmsysProcess_Option_MergeOutput, 1); } // Set the timeout if any. @@ -289,8 +304,7 @@ bool cmExecuteProcessCommand while((p = cmsysProcess_WaitForData(cp, &data, &length, 0), p)) { // Put the output in the right place. - if((p == cmsysProcess_Pipe_STDOUT && !output_quiet) || - (p == cmsysProcess_Pipe_STDERR && !error_quiet && merge_output)) + if (p == cmsysProcess_Pipe_STDOUT && !output_quiet) { if(output_variable.empty()) { diff --git a/Source/cmExecutionStatus.h b/Source/cmExecutionStatus.h index d4da5a4..201465d 100644 --- a/Source/cmExecutionStatus.h +++ b/Source/cmExecutionStatus.h @@ -12,47 +12,44 @@ #ifndef cmExecutionStatus_h #define cmExecutionStatus_h -#include "cmObject.h" +#include "cmStandardIncludes.h" /** \class cmExecutionStatus * \brief Superclass for all command status classes * * when a command is involked it may set values on a command status instance */ -class cmExecutionStatus : public cmObject +class cmExecutionStatus { public: - cmTypeMacro(cmExecutionStatus, cmObject); + cmExecutionStatus() { this->Clear(); } - cmExecutionStatus() { this->Clear();} - - virtual void SetReturnInvoked(bool val) + void SetReturnInvoked(bool val) { this->ReturnInvoked = val; } - virtual bool GetReturnInvoked() + bool GetReturnInvoked() { return this->ReturnInvoked; } - virtual void SetBreakInvoked(bool val) + void SetBreakInvoked(bool val) { this->BreakInvoked = val; } - virtual bool GetBreakInvoked() + bool GetBreakInvoked() { return this->BreakInvoked; } - virtual void SetContinueInvoked(bool val) + void SetContinueInvoked(bool val) { this->ContinueInvoked = val; } - virtual bool GetContinueInvoked() + bool GetContinueInvoked() { return this->ContinueInvoked; } - virtual void Clear() + void Clear() { this->ReturnInvoked = false; this->BreakInvoked = false; this->ContinueInvoked = false; this->NestedError = false; } - virtual void SetNestedError(bool val) { this->NestedError = val; } - virtual bool GetNestedError() { return this->NestedError; } - + void SetNestedError(bool val) { this->NestedError = val; } + bool GetNestedError() { return this->NestedError; } -protected: +private: bool ReturnInvoked; bool BreakInvoked; bool ContinueInvoked; diff --git a/Source/cmExportBuildFileGenerator.cxx b/Source/cmExportBuildFileGenerator.cxx index b1203dd..bf18deb 100644 --- a/Source/cmExportBuildFileGenerator.cxx +++ b/Source/cmExportBuildFileGenerator.cxx @@ -274,7 +274,7 @@ cmExportBuildFileGenerator ::FindNamespaces(cmMakefile* mf, const std::string& name) { std::vector<std::string> namespaces; - cmGlobalGenerator* gg = mf->GetLocalGenerator()->GetGlobalGenerator(); + cmGlobalGenerator* gg = mf->GetGlobalGenerator(); std::map<std::string, cmExportBuildFileGenerator*>& exportSets = gg->GetBuildExportSets(); diff --git a/Source/cmExportCommand.cxx b/Source/cmExportCommand.cxx index 06541c0..43d26f9 100644 --- a/Source/cmExportCommand.cxx +++ b/Source/cmExportCommand.cxx @@ -119,8 +119,7 @@ bool cmExportCommand std::vector<std::string> targets; - cmGlobalGenerator *gg = this->Makefile->GetLocalGenerator() - ->GetGlobalGenerator(); + cmGlobalGenerator *gg = this->Makefile->GetGlobalGenerator(); if(args[0] == "EXPORT") { diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index b4fad98..a51fb2a 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -257,8 +257,7 @@ static bool checkInterfaceDirs(const std::string &prepro, { case cmPolicies::WARN: messageType = cmake::WARNING; - e << target->GetMakefile()->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0041) << "\n"; + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0041) << "\n"; break; case cmPolicies::OLD: continue; @@ -306,8 +305,7 @@ static bool checkInterfaceDirs(const std::string &prepro, case cmPolicies::WARN: { std::ostringstream s; - s << target->GetMakefile()->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0052) << "\n"; + s << cmPolicies::GetPolicyWarning(cmPolicies::CMP0052) << "\n"; s << "Directory:\n \"" << *li << "\"\nin " "INTERFACE_INCLUDE_DIRECTORIES of target \"" << target->GetName() << "\" is a subdirectory of the install " diff --git a/Source/cmExportInstallFileGenerator.cxx b/Source/cmExportInstallFileGenerator.cxx index 6d639c9..89c6ca2 100644 --- a/Source/cmExportInstallFileGenerator.cxx +++ b/Source/cmExportInstallFileGenerator.cxx @@ -479,7 +479,7 @@ cmExportInstallFileGenerator ::FindNamespaces(cmMakefile* mf, const std::string& name) { std::vector<std::string> namespaces; - cmGlobalGenerator* gg = mf->GetLocalGenerator()->GetGlobalGenerator(); + cmGlobalGenerator* gg = mf->GetGlobalGenerator(); const cmExportSetMap& exportSets = gg->GetExportSets(); for(cmExportSetMap::const_iterator expIt = exportSets.begin(); diff --git a/Source/cmExtraEclipseCDT4Generator.cxx b/Source/cmExtraEclipseCDT4Generator.cxx index 72a6a30..a81e53c 100644 --- a/Source/cmExtraEclipseCDT4Generator.cxx +++ b/Source/cmExtraEclipseCDT4Generator.cxx @@ -1008,7 +1008,6 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const const std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM"); const std::string makeArgs = mf->GetSafeDefinition( "CMAKE_ECLIPSE_MAKE_ARGUMENTS"); - const std::string cmake = mf->GetRequiredDefinition("CMAKE_COMMAND"); cmGlobalGenerator* generator = const_cast<cmGlobalGenerator*>(this->GlobalGenerator); @@ -1096,11 +1095,12 @@ void cmExtraEclipseCDT4Generator::CreateCProjectFile() const std::string cleanArgs = "-E chdir \""; cleanArgs += makefile->GetCurrentBinaryDirectory(); cleanArgs += "\" \""; - cleanArgs += cmake; + cleanArgs += cmSystemTools::GetCMakeCommand(); cleanArgs += "\" -P \""; cleanArgs += (*it)->GetTargetDirectory(ti->second); cleanArgs += "/cmake_clean.cmake\""; - this->AppendTarget(fout, "Clean", cmake, cleanArgs, virtDir, "", ""); + this->AppendTarget(fout, "Clean", cmSystemTools::GetCMakeCommand(), + cleanArgs, virtDir, "", ""); } } break; diff --git a/Source/cmExtraKateGenerator.cxx b/Source/cmExtraKateGenerator.cxx index ec141a9..578e7d3 100644 --- a/Source/cmExtraKateGenerator.cxx +++ b/Source/cmExtraKateGenerator.cxx @@ -247,7 +247,7 @@ cmExtraKateGenerator::CreateDummyKateProjectFile(const cmMakefile* mf) const return; } - fout << "#Generated by " << mf->GetRequiredDefinition("CMAKE_COMMAND") + fout << "#Generated by " << cmSystemTools::GetCMakeCommand() << ", do not edit.\n"; } diff --git a/Source/cmExtraQbsGenerator.cxx b/Source/cmExtraQbsGenerator.cxx deleted file mode 100644 index 4cc4650..0000000 --- a/Source/cmExtraQbsGenerator.cxx +++ /dev/null @@ -1,260 +0,0 @@ -#include "cmExtraQbsGenerator.h" - -#include "cmGlobalGenerator.h" -#include "cmLocalGenerator.h" -#include "cmMakefile.h" -#include "cmGeneratedFileStream.h" -#include "cmSourceFile.h" - -cmExtraQbsGenerator::cmExtraQbsGenerator() -{ -#if defined(_WIN32) - this->SupportedGlobalGenerators.push_back("MinGW Makefiles"); - this->SupportedGlobalGenerators.push_back("NMake Makefiles"); -#endif - this->SupportedGlobalGenerators.push_back("Ninja"); - this->SupportedGlobalGenerators.push_back("Unix Makefiles"); -} - -cmExtraQbsGenerator::~cmExtraQbsGenerator() {} - -void cmExtraQbsGenerator::GetDocumentation(cmDocumentationEntry &entry, - const std::string &) const -{ - entry.Name = this->GetName(); - entry.Brief = "Generates Qbs project files."; -} - -void cmExtraQbsGenerator::Generate() -{ - for (std::map<std::string, std::vector<cmLocalGenerator *> >::const_iterator - it = this->GlobalGenerator->GetProjectMap().begin(); - it != this->GlobalGenerator->GetProjectMap().end(); ++it) - { - // create a project file - this->CreateProjectFile(it->first, it->second); - } -} - -void cmExtraQbsGenerator::CreateProjectFile( - const std::string &name, - const std::vector<cmLocalGenerator *> &lgs) -{ - const cmMakefile *mf = lgs[0]->GetMakefile(); - std::string outputDir = mf->GetCurrentBinaryDirectory(); - - const std::string filename = outputDir + "/" + name + ".qbs"; - - this->CreateNewProjectFile(name, lgs, filename); -} - -void cmExtraQbsGenerator::CreateNewProjectFile( - const std::string &projectName, const std::vector<cmLocalGenerator *> &lgs, - const std::string &filename) -{ - cmGeneratedFileStream fout(filename.c_str()); - if (!fout) - { - return; - } - - fout << "import qbs\n" - << "import qbs.File\n\n" - << "Project {\n" - << "\tname:\"" << projectName << "\"\n"; - std::vector<cmLocalGenerator *>::const_iterator itr = lgs.begin(); - for (; itr != lgs.end(); ++itr) - { - cmLocalGenerator *lg = (*itr); - this->AppendSubProject(fout, lg); - } - fout << "}\n"; -} - -void cmExtraQbsGenerator::AppendSubProject(cmGeneratedFileStream &fout, - cmLocalGenerator *lg) -{ - const cmMakefile *mk = lg->GetMakefile(); - if (!mk || mk->GetTargets().size() == 0) - { - return; - } - - const std::string &relativePath = cmSystemTools::RelativePath( - mk->GetHomeDirectory(), mk->GetCurrentSourceDirectory()); - fout << "\tProject {\n" - << "\t\tname:\"" << relativePath << "\"\n"; - this->AppendProduct(fout, lg); - fout << "\t}\n"; -} - -void cmExtraQbsGenerator::AppendProduct(cmGeneratedFileStream &fout, - cmLocalGenerator *lg) -{ - const cmMakefile *mk = lg->GetMakefile(); - const cmTargets &ts = mk->GetTargets(); - std::string cfg = mk->GetSafeDefinition("CMAKE_BUILD_TYPE"); - cmTargets::const_iterator itr = ts.begin(); - for (; itr != ts.end(); ++itr) - { - const cmTarget &t = itr->second; - this->AppendTarget(fout, lg, t, cfg); - } -} - -void cmExtraQbsGenerator::AppendTarget(cmGeneratedFileStream &fout, - cmLocalGenerator *lg, const cmTarget &t, - const std::string &cfg) -{ - std::string type; - bool isBuildable = true; - switch (t.GetType()) - { - case cmTarget::EXECUTABLE: - type = "application"; - break; - case cmTarget::SHARED_LIBRARY: - type = "dynamiclibrary"; - break; - case cmTarget::STATIC_LIBRARY: - type = "staticlibrary"; - break; - default: - isBuildable = false; - break; - } - - if (type.empty()) - { - fout << "\t\tProject {\n"; - } - else - { - fout << "\t\tProduct {\n"; - fout << "\t\t\tdestinationDirectory: \"" << t.GetDirectory(cfg) << "\"\n"; - } - fout << "\t\t\tname:\"" << t.GetName() << "\"\n"; - - if (!type.empty()) - { - fout << "\t\t\ttype: \"" << type << "\"\n"; - fout << "\t\t\ttargetName: \"" << t.GetName() << "\"\n"; - } - - if (isBuildable) - { - fout << "\t\t\tDepends { name: \"cpp\" }\n"; - cmGeneratorTarget *gt = this->GlobalGenerator->GetGeneratorTarget(&t); - this->AppendSources(fout, gt, t, cfg); - - std::set<std::string> langs, incPaths, defs; - t.GetLanguages(langs, cfg); - for (std::set<std::string>::const_iterator lang = langs.begin(); - lang != langs.end(); - ++ lang) - { - const std::vector<std::string> &paths = - gt->GetIncludeDirectories(cfg, *lang); - std::copy(paths.begin(), paths.end(), - std::inserter(incPaths, incPaths.end())); - - lg->AddCompileDefinitions(defs, &t, cfg, *lang); - } - this->AppendIncludePaths(fout, incPaths); - this->AppendCompileDefinitions(fout, defs); - } - - fout << "\t\t}\n"; -} - -void cmExtraQbsGenerator::AppendSources(cmGeneratedFileStream &fout, - cmGeneratorTarget *gt, - const cmTarget &t, - const std::string &cfg) -{ - std::vector<cmSourceFile *> sources; - gt->GetSourceFiles(sources, cfg); - if (sources.empty()) - { - return; - } - - std::vector<cmSourceFile *> genSources; - std::vector<cmSourceFile *>::const_iterator itr = sources.begin(); - fout << "\t\t\tfiles: [\n" - << "\t\t\t\t\"" << t.GetMakefile()->GetCurrentListFile() << "\",\n"; - for (; itr != sources.end(); ++itr) - { - if (!(*itr)->GetPropertyAsBool("GENERATED")) - { - fout << "\t\t\t\t\"" << (*itr)->GetFullPath() << "\",\n"; - } - else - { - genSources.push_back(*itr); - } - } - fout << "\t\t\t]\n"; - - if (!genSources.empty()) - { - fout << "\t\t\tGroup {\n" - << "\t\t\t\tname:\"Generated\"\n" - << "\t\t\t\tfiles: [\n"; - itr = genSources.begin(); - std::string groupCondition; - bool initialCondition = true; - for (; itr != genSources.end(); ++itr) - { - const std::string &path = (*itr)->GetFullPath(); - fout << "\t\t\t\t\t\"" << path << "\",\n"; - if (initialCondition) - { - initialCondition = false; - } - else - { - groupCondition += "\t\t\t\t\t && "; - } - groupCondition += "File.exists(\"" + path + "\")\n"; - } - fout << "\t\t\t\t]\n" - << "\t\t\t\tcondition: " << groupCondition << "\t\t\t}\n"; - } -} - -void cmExtraQbsGenerator::AppendIncludePaths( - cmGeneratedFileStream &fout, - const std::set<std::string> &paths) -{ - if (paths.empty()) - { - return; - } - - std::set<std::string>::const_iterator itr = paths.begin(); - fout << "\t\t\tcpp.includePaths: [\n"; - for (; itr != paths.end(); ++ itr) - { - fout << "\t\t\t\t\"" << (*itr) << "\",\n"; - } - fout << "\t\t\t]\n"; -} - -void cmExtraQbsGenerator::AppendCompileDefinitions( - cmGeneratedFileStream &fout, - const std::set<std::string> &defs) -{ - if (defs.empty()) - { - return; - } - - std::set<std::string>::const_iterator itr = defs.begin(); - fout << "\t\t\tcpp.defines: [\n"; - for (; itr != defs.end(); ++ itr) - { - fout << "\t\t\t\t'" << (*itr) << "',\n"; - } - fout << "\t\t\t]\n"; -} diff --git a/Source/cmExtraQbsGenerator.h b/Source/cmExtraQbsGenerator.h deleted file mode 100644 index 531ccc9..0000000 --- a/Source/cmExtraQbsGenerator.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef CMEXTRAQBSGENERATOR_H -#define CMEXTRAQBSGENERATOR_H - -#include "cmExternalMakefileProjectGenerator.h" - -class cmGeneratorTarget; - -class cmExtraQbsGenerator : public cmExternalMakefileProjectGenerator -{ -public: - cmExtraQbsGenerator(); - ~cmExtraQbsGenerator(); - - virtual std::string GetName() const - { return cmExtraQbsGenerator::GetActualName(); } - static std::string GetActualName() { return "Qbs"; } - static cmExternalMakefileProjectGenerator *New() - { return new cmExtraQbsGenerator; } - - /** Get the documentation entry for this generator. */ - virtual void GetDocumentation(cmDocumentationEntry &entry, - const std::string &fullName) const; - - virtual void Generate(); - -private: - void CreateProjectFile(const std::string &name, - const std::vector<cmLocalGenerator *> &lgs); - void CreateNewProjectFile(const std::string &projectName, - const std::vector<cmLocalGenerator *> &lgs, - const std::string &filename); - void AppendSubProject(cmGeneratedFileStream &fout, cmLocalGenerator *lg); - void AppendProduct(cmGeneratedFileStream &fout, cmLocalGenerator *lg); - void AppendTarget(cmGeneratedFileStream &fout, - cmLocalGenerator *lg, - const cmTarget &t, - const std::string &cfg); - void AppendSources(cmGeneratedFileStream &fout, - cmGeneratorTarget *gt, - const cmTarget &t, - const std::string &cfg); - void AppendIncludePaths(cmGeneratedFileStream &fout, - const std::set<std::string> &paths); - void AppendCompileDefinitions(cmGeneratedFileStream &fout, - const std::set<std::string> &defs); -}; - -#endif // CMEXTRAQBSGENERATOR_H diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 14f397c..4698468 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -1056,16 +1056,14 @@ bool cmFileCommand::HandleGlobCommand(std::vector<std::string> const& args, if(g.GetFollowedSymlinkCount() != 0) { this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, - this->Makefile->GetPolicies()-> - GetPolicyWarning(cmPolicies::CMP0009)); + cmPolicies::GetPolicyWarning(cmPolicies::CMP0009)); } break; case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: this->SetError("policy CMP0009 error"); this->Makefile->IssueMessage(cmake::FATAL_ERROR, - this->Makefile->GetPolicies()-> - GetRequiredPolicyError(cmPolicies::CMP0009)); + cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0009)); return false; } } @@ -2800,13 +2798,36 @@ namespace { static size_t - cmFileCommandCurlDebugCallback(CURL *, curl_infotype, char *chPtr, + cmFileCommandCurlDebugCallback(CURL *, curl_infotype type, char *chPtr, size_t size, void *data) { cmFileCommandVectorOfChar *vec = static_cast<cmFileCommandVectorOfChar*>(data); - vec->insert(vec->end(), chPtr, chPtr + size); - return size; + switch(type) + { + case CURLINFO_TEXT: + case CURLINFO_HEADER_IN: + case CURLINFO_HEADER_OUT: + vec->insert(vec->end(), chPtr, chPtr + size); + break; + case CURLINFO_DATA_IN: + case CURLINFO_DATA_OUT: + case CURLINFO_SSL_DATA_IN: + case CURLINFO_SSL_DATA_OUT: + { + char buf[128]; + int n = sprintf(buf, "[%" cmIML_INT_PRIu64 " bytes data]\n", + static_cast<cmIML_INT_uint64_t>(size)); + if (n > 0) + { + vec->insert(vec->end(), buf, buf + n); + } + } + break; + default: + break; + } + return 0; } @@ -2965,7 +2986,7 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) long timeout = 0; long inactivity_timeout = 0; - std::string verboseLog; + std::string logVar; std::string statusVar; bool tls_verify = this->Makefile->IsOn("CMAKE_TLS_VERIFY"); const char* cainfo = this->Makefile->GetDefinition("CMAKE_TLS_CAINFO"); @@ -3010,7 +3031,7 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) this->SetError("DOWNLOAD missing VAR for LOG."); return false; } - verboseLog = *i; + logVar = *i; } else if(*i == "STATUS") { @@ -3202,7 +3223,7 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) res = ::curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L); check_curl_result(res, "DOWNLOAD cannot set follow-redirect option: "); - if(!verboseLog.empty()) + if(!logVar.empty()) { res = ::curl_easy_setopt(curl, CURLOPT_VERBOSE, 1); check_curl_result(res, "DOWNLOAD cannot set verbose: "); @@ -3289,22 +3310,10 @@ cmFileCommand::HandleDownloadCommand(std::vector<std::string> const& args) } } - if(!chunkDebug.empty()) + if (!logVar.empty()) { chunkDebug.push_back(0); - if(CURLE_OPERATION_TIMEOUTED == res) - { - std::string output = &*chunkDebug.begin(); - - if(!verboseLog.empty()) - { - this->Makefile->AddDefinition(verboseLog, - &*chunkDebug.begin()); - } - } - - this->Makefile->AddDefinition(verboseLog, - &*chunkDebug.begin()); + this->Makefile->AddDefinition(logVar, &*chunkDebug.begin()); } return true; @@ -3568,8 +3577,7 @@ void cmFileCommand::AddEvaluationFile(const std::string &inputName, cmsys::auto_ptr<cmCompiledGeneratorExpression> conditionCge = conditionGe.Parse(condition); - this->Makefile->GetLocalGenerator() - ->GetGlobalGenerator()->AddEvaluationFile(inputName, + this->Makefile->GetGlobalGenerator()->AddEvaluationFile(inputName, outputCge, this->Makefile, conditionCge, @@ -3772,8 +3780,8 @@ bool cmFileCommand::HandleLockCommand( fclose(file); // Actual lock/unlock - cmFileLockPool& lockPool = this->Makefile->GetLocalGenerator()-> - GetGlobalGenerator()->GetFileLockPool(); + cmFileLockPool& lockPool = this->Makefile->GetGlobalGenerator() + ->GetFileLockPool(); cmFileLockResult fileLockResult(cmFileLockResult::MakeOk()); if (release) diff --git a/Source/cmFileTimeComparison.cxx b/Source/cmFileTimeComparison.cxx index 5727470..13e2a66 100644 --- a/Source/cmFileTimeComparison.cxx +++ b/Source/cmFileTimeComparison.cxx @@ -13,8 +13,12 @@ // Use a hash table to avoid duplicate file time checks from disk. #if defined(CMAKE_BUILD_WITH_CMAKE) +#ifdef CMake_HAVE_CXX11_UNORDERED_MAP +#include <unordered_map> +#else # include <cmsys/hash_map.hxx> #endif +#endif #include <cmsys/Encoding.hxx> @@ -47,9 +51,17 @@ private: { return h(s.c_str()); } +#ifdef CMake_HAVE_CXX11_UNORDERED_MAP + std::hash<const char*> h; +#else cmsys::hash<const char*> h; +#endif }; +#ifdef CMake_HAVE_CXX11_UNORDERED_MAP + typedef std::unordered_map<std::string, +#else typedef cmsys::hash_map<std::string, +#endif cmFileTimeComparison_Type, HashString> FileStatsMap; FileStatsMap Files; #endif diff --git a/Source/cmFindLibraryCommand.cxx b/Source/cmFindLibraryCommand.cxx index 507d011..0a66732 100644 --- a/Source/cmFindLibraryCommand.cxx +++ b/Source/cmFindLibraryCommand.cxx @@ -212,7 +212,7 @@ struct cmFindLibraryHelper cmFindLibraryHelper::cmFindLibraryHelper(cmMakefile* mf): Makefile(mf) { - this->GG = this->Makefile->GetLocalGenerator()->GetGlobalGenerator(); + this->GG = this->Makefile->GetGlobalGenerator(); // Collect the list of library name prefixes/suffixes to try. const char* prefixes_list = diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index 4d568e9..68a6558 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -42,7 +42,6 @@ cmFindPackageCommand::cmFindPackageCommand() this->Required = false; this->NoUserRegistry = false; this->NoSystemRegistry = false; - this->NoBuilds = false; this->UseConfigFiles = true; this->UseFindModules = true; this->DebugMode = false; @@ -246,7 +245,7 @@ bool cmFindPackageCommand } else if(args[i] == "NO_CMAKE_BUILDS_PATH") { - this->NoBuilds = true; + // Ignore legacy option. configArgs.insert(i); doing = DoingNone; } @@ -1142,10 +1141,6 @@ void cmFindPackageCommand::ComputePrefixes() { this->FillPrefixesUserRegistry(); } - if(!this->NoBuilds) - { - this->FillPrefixesBuilds(); - } if(!this->NoCMakeSystemPath) { this->FillPrefixesCMakeSystemVariable(); @@ -1438,29 +1433,6 @@ bool cmFindPackageCommand::CheckPackageRegistryEntry(const std::string& fname, } //---------------------------------------------------------------------------- -void cmFindPackageCommand::FillPrefixesBuilds() -{ - cmSearchPath &paths = this->LabeledPaths[PathLabel::Builds]; - - // It is likely that CMake will have recently built the project. - for(int i=0; i <= 10; ++i) - { - std::ostringstream r; - r << - "[HKEY_CURRENT_USER\\Software\\Kitware\\CMakeSetup\\" - "Settings\\StartPath;WhereBuild" << i << "]"; - std::string f = r.str(); - cmSystemTools::ExpandRegistryValues(f); - cmSystemTools::ConvertToUnixSlashes(f); - if(cmSystemTools::FileIsFullPath(f.c_str()) && - cmSystemTools::FileIsDirectory(f)) - { - paths.AddPath(f); - } - } -} - -//---------------------------------------------------------------------------- void cmFindPackageCommand::FillPrefixesCMakeSystemVariable() { cmSearchPath &paths = this->LabeledPaths[PathLabel::CMakeSystem]; diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h index 949dcb1..3eee404 100644 --- a/Source/cmFindPackageCommand.h +++ b/Source/cmFindPackageCommand.h @@ -89,7 +89,6 @@ private: void FillPrefixesSystemEnvironment(); void FillPrefixesUserRegistry(); void FillPrefixesSystemRegistry(); - void FillPrefixesBuilds(); void FillPrefixesCMakeSystemVariable(); void FillPrefixesUserGuess(); void FillPrefixesUserHints(); @@ -138,7 +137,6 @@ private: bool UseFindModules; bool NoUserRegistry; bool NoSystemRegistry; - bool NoBuilds; bool DebugMode; bool UseLib64Paths; bool PolicyScope; diff --git a/Source/cmForEachCommand.cxx b/Source/cmForEachCommand.cxx index 8e3510d..0dcda4d 100644 --- a/Source/cmForEachCommand.cxx +++ b/Source/cmForEachCommand.cxx @@ -44,8 +44,6 @@ IsFunctionBlocked(const cmListFileFunction& lff, cmMakefile &mf, std::vector<std::string>::const_iterator j = this->Args.begin(); ++j; - std::string tmps; - cmListFileArgument arg; for( ; j != this->Args.end(); ++j) { // set the variable to the loop value diff --git a/Source/cmFunctionCommand.cxx b/Source/cmFunctionCommand.cxx index fdd1018..001adb1 100644 --- a/Source/cmFunctionCommand.cxx +++ b/Source/cmFunctionCommand.cxx @@ -94,8 +94,8 @@ bool cmFunctionHelperCommand::InvokeInitialPass } // we push a scope on the makefile - cmMakefile::LexicalPushPop lexScope(this->Makefile); cmMakefile::ScopePushPop varScope(this->Makefile); + cmMakefile::LexicalPushPop lexScope(this->Makefile); static_cast<void>(varScope); // Push a weak policy scope which restores the policies recorded at diff --git a/Source/cmGeneratorExpressionEvaluationFile.cxx b/Source/cmGeneratorExpressionEvaluationFile.cxx index fa00283..c726995 100644 --- a/Source/cmGeneratorExpressionEvaluationFile.cxx +++ b/Source/cmGeneratorExpressionEvaluationFile.cxx @@ -103,8 +103,7 @@ void cmGeneratorExpressionEvaluationFile::CreateOutputFile( std::string const& config) { std::vector<std::string> enabledLanguages; - cmGlobalGenerator *gg - = this->Makefile->GetLocalGenerator()->GetGlobalGenerator(); + cmGlobalGenerator *gg = this->Makefile->GetGlobalGenerator(); gg->GetEnabledLanguages(enabledLanguages); for(std::vector<std::string>::const_iterator le = enabledLanguages.begin(); @@ -168,8 +167,7 @@ void cmGeneratorExpressionEvaluationFile::Generate() } std::vector<std::string> enabledLanguages; - cmGlobalGenerator *gg - = this->Makefile->GetLocalGenerator()->GetGlobalGenerator(); + cmGlobalGenerator *gg = this->Makefile->GetGlobalGenerator(); gg->GetEnabledLanguages(enabledLanguages); for(std::vector<std::string>::const_iterator le = enabledLanguages.begin(); diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 2654851..293eb41 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -395,8 +395,7 @@ struct CompilerIdNode : public cmGeneratorExpressionNode case cmPolicies::WARN: { std::ostringstream e; - e << context->Makefile->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0044); + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0044); context->Makefile->GetCMakeInstance() ->IssueMessage(cmake::AUTHOR_WARNING, e.str(), context->Backtrace); @@ -768,8 +767,7 @@ static const struct CompileLanguageNode : public cmGeneratorExpressionNode } std::vector<std::string> enabledLanguages; - cmGlobalGenerator* gg - = context->Makefile->GetLocalGenerator()->GetGlobalGenerator(); + cmGlobalGenerator* gg = context->Makefile->GetGlobalGenerator(); gg->GetEnabledLanguages(enabledLanguages); if (!parameters.empty() && std::find(enabledLanguages.begin(), enabledLanguages.end(), @@ -1495,8 +1493,7 @@ static const struct TargetPolicyNode : public cmGeneratorExpressionNode { case cmPolicies::WARN: mf->IssueMessage(cmake::AUTHOR_WARNING, - mf->GetPolicies()-> - GetPolicyWarning(policyForString(policy))); + cmPolicies::GetPolicyWarning(policyForString(policy))); case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: case cmPolicies::OLD: diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 1a4f9c4..e2b8c45 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -132,8 +132,7 @@ struct TagVisitor TagVisitor(cmTarget *target, DataType& data) : Data(data), Target(target), - GlobalGenerator(target->GetMakefile() - ->GetLocalGenerator()->GetGlobalGenerator()), + GlobalGenerator(target->GetMakefile()->GetGlobalGenerator()), Header(CM_HEADER_REGEX), IsObjLib(target->GetType() == cmTarget::OBJECT_LIBRARY) { @@ -226,7 +225,7 @@ cmGeneratorTarget::cmGeneratorTarget(cmTarget* t): Target(t), { this->Makefile = this->Target->GetMakefile(); this->LocalGenerator = this->Makefile->GetLocalGenerator(); - this->GlobalGenerator = this->LocalGenerator->GetGlobalGenerator(); + this->GlobalGenerator = this->Makefile->GetGlobalGenerator(); } //---------------------------------------------------------------------------- @@ -648,8 +647,7 @@ cmTargetTraceDependencies { // Convenience. this->Makefile = this->Target->GetMakefile(); - this->GlobalGenerator = - this->Makefile->GetLocalGenerator()->GetGlobalGenerator(); + this->GlobalGenerator = this->Makefile->GetGlobalGenerator(); this->CurrentEntry = 0; // Queue all the source files already specified for the target. @@ -1025,8 +1023,7 @@ void cmGeneratorTarget::GenerateTargetManifest( return; } cmMakefile* mf = this->Target->GetMakefile(); - cmLocalGenerator* lg = mf->GetLocalGenerator(); - cmGlobalGenerator* gg = lg->GetGlobalGenerator(); + cmGlobalGenerator* gg = mf->GetGlobalGenerator(); // Get the names. std::string name; diff --git a/Source/cmGetCMakePropertyCommand.cxx b/Source/cmGetCMakePropertyCommand.cxx index b035750..76803c1 100644 --- a/Source/cmGetCMakePropertyCommand.cxx +++ b/Source/cmGetCMakePropertyCommand.cxx @@ -47,8 +47,7 @@ bool cmGetCMakePropertyCommand else if ( args[1] == "COMPONENTS" ) { const std::set<std::string>* components - = this->Makefile->GetLocalGenerator()->GetGlobalGenerator() - ->GetInstallComponents(); + = this->Makefile->GetGlobalGenerator()->GetInstallComponents(); output = cmJoin(*components, ";"); } else diff --git a/Source/cmGetDirectoryPropertyCommand.cxx b/Source/cmGetDirectoryPropertyCommand.cxx index 881b2ae..4fe3318 100644 --- a/Source/cmGetDirectoryPropertyCommand.cxx +++ b/Source/cmGetDirectoryPropertyCommand.cxx @@ -53,7 +53,7 @@ bool cmGetDirectoryPropertyCommand // lookup the makefile from the directory name cmLocalGenerator *lg = - this->Makefile->GetLocalGenerator()->GetGlobalGenerator()-> + this->Makefile->GetGlobalGenerator()-> FindLocalGenerator(sd); if (!lg) { diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx index 00dbdd3..250bd35 100644 --- a/Source/cmGetPropertyCommand.cxx +++ b/Source/cmGetPropertyCommand.cxx @@ -265,8 +265,7 @@ bool cmGetPropertyCommand::HandleDirectoryMode() // Lookup the generator. if(cmLocalGenerator* lg = - (this->Makefile->GetLocalGenerator() - ->GetGlobalGenerator()->FindLocalGenerator(dir))) + (this->Makefile->GetGlobalGenerator()->FindLocalGenerator(dir))) { // Use the makefile for the directory found. mf = lg->GetMakefile(); diff --git a/Source/cmGetTargetPropertyCommand.cxx b/Source/cmGetTargetPropertyCommand.cxx index eed19f4..315e851 100644 --- a/Source/cmGetTargetPropertyCommand.cxx +++ b/Source/cmGetTargetPropertyCommand.cxx @@ -56,8 +56,7 @@ bool cmGetTargetPropertyCommand { case cmPolicies::WARN: issueMessage = true; - e << this->Makefile->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0045) << "\n"; + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0045) << "\n"; case cmPolicies::OLD: break; case cmPolicies::REQUIRED_IF_USED: diff --git a/Source/cmGlobalBorlandMakefileGenerator.cxx b/Source/cmGlobalBorlandMakefileGenerator.cxx index 597e08e..87665a0 100644 --- a/Source/cmGlobalBorlandMakefileGenerator.cxx +++ b/Source/cmGlobalBorlandMakefileGenerator.cxx @@ -14,13 +14,19 @@ #include "cmMakefile.h" #include "cmake.h" -cmGlobalBorlandMakefileGenerator::cmGlobalBorlandMakefileGenerator() +cmGlobalBorlandMakefileGenerator::cmGlobalBorlandMakefileGenerator(cmake* cm) + : cmGlobalUnixMakefileGenerator3(cm) { this->EmptyRuleHackDepends = "NUL"; this->FindMakeProgramFile = "CMakeBorlandFindMake.cmake"; this->ForceUnixPaths = false; this->ToolSupportsColor = true; this->UseLinkScript = false; + cm->GetState()->SetWindowsShell(true); + this->IncludeDirective = "!include"; + this->DefineWindowsNULL = true; + this->PassMakeflags = true; + this->UnixCD = false; } @@ -38,17 +44,11 @@ void cmGlobalBorlandMakefileGenerator ///! Create a local generator appropriate to this Global Generator cmLocalGenerator *cmGlobalBorlandMakefileGenerator::CreateLocalGenerator( - cmLocalGenerator* parent) + cmLocalGenerator* parent, cmState::Snapshot snapshot) { cmLocalUnixMakefileGenerator3* lg = - new cmLocalUnixMakefileGenerator3(parent); - lg->SetIncludeDirective("!include"); - lg->SetWindowsShell(true); - lg->SetDefineWindowsNULL(true); + new cmLocalUnixMakefileGenerator3(this, parent, snapshot); lg->SetMakefileVariableSize(32); - lg->SetPassMakeflags(true); - lg->SetGlobalGenerator(this); - lg->SetUnixCD(false); lg->SetMakeCommandEscapeTargetTwice(true); lg->SetBorlandMakeCurlyHack(true); return lg; diff --git a/Source/cmGlobalBorlandMakefileGenerator.h b/Source/cmGlobalBorlandMakefileGenerator.h index 3f79414..2ec510d 100644 --- a/Source/cmGlobalBorlandMakefileGenerator.h +++ b/Source/cmGlobalBorlandMakefileGenerator.h @@ -19,10 +19,10 @@ * * cmGlobalBorlandMakefileGenerator manages nmake build process for a tree */ -class cmGlobalBorlandMakefileGenerator : public cmGlobalNMakeMakefileGenerator +class cmGlobalBorlandMakefileGenerator : public cmGlobalUnixMakefileGenerator3 { public: - cmGlobalBorlandMakefileGenerator(); + cmGlobalBorlandMakefileGenerator(cmake* cm); static cmGlobalGeneratorFactory* NewFactory() { return new cmGlobalGeneratorSimpleFactory <cmGlobalBorlandMakefileGenerator>(); } @@ -36,7 +36,8 @@ public: static void GetDocumentation(cmDocumentationEntry& entry); ///! Create a local generator appropriate to this Global Generator - virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent = 0); + virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent, + cmState::Snapshot snapshot); /** * Try to determine system information such as shared library diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 384f023..cd05c54 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -48,7 +48,8 @@ #include <assert.h> -cmGlobalGenerator::cmGlobalGenerator() +cmGlobalGenerator::cmGlobalGenerator(cmake* cm) + : CMakeInstance(cm) { // By default the .SYMBOLIC dependency is not needed on symbolic rules. this->NeedSymbolicMark = false; @@ -826,7 +827,6 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility(cmMakefile* mf, if(strcmp(compilerId, "AppleClang") == 0) { - cmPolicies* policies = this->CMakeInstance->GetPolicies(); switch(mf->GetPolicyStatus(cmPolicies::CMP0025)) { case cmPolicies::WARN: @@ -834,7 +834,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility(cmMakefile* mf, mf->PolicyOptionalWarningEnabled("CMAKE_POLICY_WARNING_CMP0025")) { std::ostringstream w; - w << policies->GetPolicyWarning(cmPolicies::CMP0025) << "\n" + w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0025) << "\n" "Converting " << lang << " compiler id \"AppleClang\" to \"Clang\" for compatibility." ; @@ -848,7 +848,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility(cmMakefile* mf, case cmPolicies::REQUIRED_ALWAYS: mf->IssueMessage( cmake::FATAL_ERROR, - policies->GetRequiredPolicyError(cmPolicies::CMP0025) + cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0025) ); case cmPolicies::NEW: // NEW behavior is to keep AppleClang. @@ -858,7 +858,6 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility(cmMakefile* mf, if(strcmp(compilerId, "QCC") == 0) { - cmPolicies* policies = this->CMakeInstance->GetPolicies(); switch(mf->GetPolicyStatus(cmPolicies::CMP0047)) { case cmPolicies::WARN: @@ -866,7 +865,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility(cmMakefile* mf, mf->PolicyOptionalWarningEnabled("CMAKE_POLICY_WARNING_CMP0047")) { std::ostringstream w; - w << policies->GetPolicyWarning(cmPolicies::CMP0047) << "\n" + w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0047) << "\n" "Converting " << lang << " compiler id \"QCC\" to \"GNU\" for compatibility." ; @@ -888,7 +887,7 @@ void cmGlobalGenerator::CheckCompilerIdCompatibility(cmMakefile* mf, case cmPolicies::REQUIRED_ALWAYS: mf->IssueMessage( cmake::FATAL_ERROR, - policies->GetRequiredPolicyError(cmPolicies::CMP0047) + cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0047) ); case cmPolicies::NEW: // NEW behavior is to keep QCC. @@ -1094,7 +1093,7 @@ void cmGlobalGenerator::Configure() this->ClearGeneratorMembers(); // start with this directory - cmLocalGenerator *lg = this->CreateLocalGenerator(); + cmLocalGenerator *lg = this->MakeLocalGenerator(); this->LocalGenerators.push_back(lg); // set the Start directories @@ -1327,9 +1326,7 @@ void cmGlobalGenerator::Generate() if(!this->CMP0042WarnTargets.empty()) { std::ostringstream w; - w << - (this->GetCMakeInstance()->GetPolicies()-> - GetPolicyWarning(cmPolicies::CMP0042)) << "\n"; + w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0042) << "\n"; w << "MACOSX_RPATH is not specified for" " the following targets:\n"; for(std::set<std::string>::iterator @@ -1370,10 +1367,18 @@ void cmGlobalGenerator::CreateQtAutoGeneratorsTargets(AutogensType &autogens) { cmTargets& targets = this->LocalGenerators[i]->GetMakefile()->GetTargets(); + std::vector<std::string> targetNames; + targetNames.reserve(targets.size()); for(cmTargets::iterator ti = targets.begin(); ti != targets.end(); ++ti) { - cmTarget& target = ti->second; + targetNames.push_back(ti->second.GetName()); + } + for(std::vector<std::string>::iterator ti = targetNames.begin(); + ti != targetNames.end(); ++ti) + { + cmTarget& target = *this->LocalGenerators[i] + ->GetMakefile()->FindTarget(*ti, true); if(target.GetType() == cmTarget::EXECUTABLE || target.GetType() == cmTarget::STATIC_LIBRARY || target.GetType() == cmTarget::SHARED_LIBRARY || @@ -1879,11 +1884,22 @@ void cmGlobalGenerator::EnableInstallTarget() } cmLocalGenerator * -cmGlobalGenerator::CreateLocalGenerator(cmLocalGenerator *parent) +cmGlobalGenerator::MakeLocalGenerator(cmState::Snapshot snapshot, + cmLocalGenerator *parent) +{ + if (!snapshot.IsValid()) + { + snapshot = this->CMakeInstance->GetCurrentSnapshot(); + } + + return this->CreateLocalGenerator(parent, snapshot); +} + +cmLocalGenerator* +cmGlobalGenerator::CreateLocalGenerator(cmLocalGenerator* parent, + cmState::Snapshot snapshot) { - cmLocalGenerator *lg = new cmLocalGenerator(parent); - lg->SetGlobalGenerator(this); - return lg; + return new cmLocalGenerator(this, parent, snapshot); } void cmGlobalGenerator::EnableLanguagesFromGenerator(cmGlobalGenerator *gen, @@ -1897,7 +1913,9 @@ void cmGlobalGenerator::EnableLanguagesFromGenerator(cmGlobalGenerator *gen, "make program", cmState::FILEPATH); // copy the enabled languages - this->LanguageEnabled = gen->LanguageEnabled; + this->GetCMakeInstance()->GetState()->SetEnabledLanguages( + gen->GetCMakeInstance()->GetState()->GetEnabledLanguages() + ); this->LanguagesReady = gen->LanguagesReady; this->ExtensionToLanguage = gen->ExtensionToLanguage; this->IgnoreExtensions = gen->IgnoreExtensions; @@ -2124,17 +2142,10 @@ inline std::string removeQuotes(const std::string& s) return s; } -void cmGlobalGenerator::SetCMakeInstance(cmake* cm) -{ - // Store a pointer to the cmake object instance. - this->CMakeInstance = cm; -} - void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets) { cmMakefile* mf = this->LocalGenerators[0]->GetMakefile(); const char* cmakeCfgIntDir = this->GetCMakeCFGIntDir(); - const char* cmakeCommand = mf->GetRequiredDefinition("CMAKE_COMMAND"); // CPack std::string workingDir = mf->GetCurrentBinaryDirectory(); @@ -2249,7 +2260,7 @@ void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets) } else { - singleLine.push_back(cmakeCommand); + singleLine.push_back(cmSystemTools::GetCMakeCommand()); singleLine.push_back("-E"); singleLine.push_back("echo"); singleLine.push_back("No interactive CMake dialog available."); @@ -2270,7 +2281,7 @@ void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets) cpackCommandLines.end()); singleLine.erase(singleLine.begin(), singleLine.end()); depends.erase(depends.begin(), depends.end()); - singleLine.push_back(cmakeCommand); + singleLine.push_back(cmSystemTools::GetCMakeCommand()); singleLine.push_back("-H$(CMAKE_SOURCE_DIR)"); singleLine.push_back("-B$(CMAKE_BINARY_DIR)"); cpackCommandLines.push_back(singleLine); @@ -2312,7 +2323,7 @@ void cmGlobalGenerator::CreateDefaultGlobalTargets(cmTargets* targets) ostr.str().c_str(), &cpackCommandLines, depends, 0, /*uses_terminal*/false); } - std::string cmd = cmakeCommand; + std::string cmd = cmSystemTools::GetCMakeCommand(); cpackCommandLines.erase(cpackCommandLines.begin(), cpackCommandLines.end()); singleLine.erase(singleLine.begin(), singleLine.end()); @@ -2423,38 +2434,6 @@ bool cmGlobalGenerator::UseFolderProperty() } //---------------------------------------------------------------------------- -void cmGlobalGenerator::EnableMinGWLanguage(cmMakefile *mf) -{ - this->FindMakeProgram(mf); - std::string makeProgram = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM"); - std::vector<std::string> locations; - locations.push_back(cmSystemTools::GetProgramPath(makeProgram)); - locations.push_back("/mingw/bin"); - locations.push_back("c:/mingw/bin"); - std::string tgcc = cmSystemTools::FindProgram("gcc", locations); - std::string gcc = "gcc.exe"; - if(!tgcc.empty()) - { - gcc = tgcc; - } - std::string tgxx = cmSystemTools::FindProgram("g++", locations); - std::string gxx = "g++.exe"; - if(!tgxx.empty()) - { - gxx = tgxx; - } - std::string trc = cmSystemTools::FindProgram("windres", locations); - std::string rc = "windres.exe"; - if(!trc.empty()) - { - rc = trc; - } - mf->AddDefinition("CMAKE_GENERATOR_CC", gcc.c_str()); - mf->AddDefinition("CMAKE_GENERATOR_CXX", gxx.c_str()); - mf->AddDefinition("CMAKE_GENERATOR_RC", rc.c_str()); -} - -//---------------------------------------------------------------------------- cmTarget cmGlobalGenerator::CreateGlobalTarget( const std::string& name, const char* message, const cmCustomCommandLines* commandLines, diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index b51bd47..979e971 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -21,10 +21,15 @@ #include "cmExportSetMap.h" // For cmExportSetMap #include "cmGeneratorTarget.h" #include "cmGeneratorExpression.h" +#include "cmState.h" #if defined(CMAKE_BUILD_WITH_CMAKE) # include "cmFileLockPool.h" -# include <cmsys/hash_map.hxx> +# ifdef CMake_HAVE_CXX11_UNORDERED_MAP +# include <unordered_map> +# else +# include <cmsys/hash_map.hxx> +# endif #endif class cmake; @@ -49,11 +54,12 @@ class cmGlobalGenerator { public: ///! Free any memory allocated with the GlobalGenerator - cmGlobalGenerator(); + cmGlobalGenerator(cmake* cm); virtual ~cmGlobalGenerator(); - ///! Create a local generator appropriate to this Global Generator - virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent = 0); + cmLocalGenerator* MakeLocalGenerator( + cmState::Snapshot snapshot = cmState::Snapshot(), + cmLocalGenerator* parent = 0); ///! Get the name for this generator virtual std::string GetName() const { return "Generic"; } @@ -118,7 +124,7 @@ public: * Try running cmake and building a file. This is used for dynamically * loaded commands, not as part of the usual build process. */ - virtual int TryCompile(const std::string& srcdir, const std::string& bindir, + int TryCompile(const std::string& srcdir, const std::string& bindir, const std::string& projectName, const std::string& targetName, bool fast, std::string& output, cmMakefile* mf); @@ -155,9 +161,6 @@ public: const std::string& native, bool ignoreErrors); - ///! Set the CMake instance - void SetCMakeInstance(cmake *cm); - ///! Get the CMake instance cmake *GetCMakeInstance() const { return this->CMakeInstance; } @@ -354,13 +357,14 @@ public: cmFileLockPool& GetFileLockPool() { return FileLockPool; } #endif + std::string MakeSilentFlag; protected: virtual void Generate(); typedef std::vector<cmLocalGenerator*> GeneratorVector; // for a project collect all its targets by following depend // information, and also collect all the targets - virtual void GetTargetSets(TargetDependSet& projectTargets, + void GetTargetSets(TargetDependSet& projectTargets, TargetDependSet& originalTargets, cmLocalGenerator* root, GeneratorVector const&); bool IsRootOnlyTarget(cmTarget* target) const; @@ -422,7 +426,11 @@ protected: // All targets in the entire project. #if defined(CMAKE_BUILD_WITH_CMAKE) +#ifdef CMake_HAVE_CXX11_UNORDERED_MAP + typedef std::unordered_map<std::string, cmTarget*> TargetMap; +#else typedef cmsys::hash_map<std::string, cmTarget*> TargetMap; +#endif #else typedef std::map<std::string,cmTarget *> TargetMap; #endif @@ -431,17 +439,19 @@ protected: TargetMap ImportedTargets; std::vector<cmGeneratorExpressionEvaluationFile*> EvaluationFiles; - virtual const char* GetPredefinedTargetsFolder(); + const char* GetPredefinedTargetsFolder(); virtual bool UseFolderProperty(); - void EnableMinGWLanguage(cmMakefile *mf); private: + ///! Create a local generator appropriate to this Global Generator + virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent, + cmState::Snapshot snapshot); + cmMakefile* TryCompileOuterMakefile; float FirstTimeProgress; // If you add a new map here, make sure it is copied // in EnableLanguagesFromGenerator std::map<std::string, bool> IgnoreExtensions; - std::vector<std::string> LanguageEnabled; std::set<std::string> LanguagesReady; // Ready for try_compile std::map<std::string, std::string> OutputExtensions; std::map<std::string, std::string> LanguageToOutputExtension; diff --git a/Source/cmGlobalGeneratorFactory.h b/Source/cmGlobalGeneratorFactory.h index 3c2cd60..ebba599 100644 --- a/Source/cmGlobalGeneratorFactory.h +++ b/Source/cmGlobalGeneratorFactory.h @@ -15,6 +15,7 @@ #include "cmStandardIncludes.h" +class cmake; class cmGlobalGenerator; struct cmDocumentationEntry; @@ -30,7 +31,7 @@ public: /** Create a GlobalGenerator */ virtual cmGlobalGenerator* CreateGlobalGenerator( - const std::string& n) const = 0; + const std::string& n, cmake* cm) const = 0; /** Get the documentation entry for this factory */ virtual void GetDocumentation(cmDocumentationEntry& entry) const = 0; @@ -44,10 +45,10 @@ class cmGlobalGeneratorSimpleFactory : public cmGlobalGeneratorFactory { public: /** Create a GlobalGenerator */ - virtual cmGlobalGenerator* CreateGlobalGenerator( - const std::string& name) const { + virtual cmGlobalGenerator* + CreateGlobalGenerator(const std::string& name, cmake* cm) const { if (name != T::GetActualName()) return 0; - return new T; } + return new T(cm); } /** Get the documentation entry for this factory */ virtual void GetDocumentation(cmDocumentationEntry& entry) const { diff --git a/Source/cmGlobalGhsMultiGenerator.cxx b/Source/cmGlobalGhsMultiGenerator.cxx index 181a517..f764418 100644 --- a/Source/cmGlobalGhsMultiGenerator.cxx +++ b/Source/cmGlobalGhsMultiGenerator.cxx @@ -21,8 +21,8 @@ const char *cmGlobalGhsMultiGenerator::FILE_EXTENSION = ".gpj"; const char *cmGlobalGhsMultiGenerator::DEFAULT_MAKE_PROGRAM = "gbuild"; -cmGlobalGhsMultiGenerator::cmGlobalGhsMultiGenerator() - : OSDirRelative(false) +cmGlobalGhsMultiGenerator::cmGlobalGhsMultiGenerator(cmake* cm) + : cmGlobalGenerator(cm), OSDirRelative(false) { this->GhsBuildCommandInitialized = false; } @@ -33,12 +33,10 @@ cmGlobalGhsMultiGenerator::~cmGlobalGhsMultiGenerator() } cmLocalGenerator * -cmGlobalGhsMultiGenerator::CreateLocalGenerator(cmLocalGenerator* parent) +cmGlobalGhsMultiGenerator::CreateLocalGenerator(cmLocalGenerator* parent, + cmState::Snapshot snapshot) { - cmLocalGenerator *lg = new cmLocalGhsMultiGenerator(parent); - lg->SetGlobalGenerator(this); - this->SetCurrentLocalGenerator(lg); - return lg; + return new cmLocalGhsMultiGenerator(this, parent, snapshot); } void cmGlobalGhsMultiGenerator::GetDocumentation(cmDocumentationEntry &entry) diff --git a/Source/cmGlobalGhsMultiGenerator.h b/Source/cmGlobalGhsMultiGenerator.h index 6464f5c..f1a3ed7 100644 --- a/Source/cmGlobalGhsMultiGenerator.h +++ b/Source/cmGlobalGhsMultiGenerator.h @@ -24,14 +24,15 @@ public: /// The default name of GHS MULTI's build file. Typically: monolith.gpj. static const char *FILE_EXTENSION; - cmGlobalGhsMultiGenerator(); + cmGlobalGhsMultiGenerator(cmake* cm); ~cmGlobalGhsMultiGenerator(); static cmGlobalGeneratorFactory *NewFactory() { return new cmGlobalGeneratorSimpleFactory<cmGlobalGhsMultiGenerator>(); } ///! create the correct local generator - virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent = 0); + virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent, + cmState::Snapshot snapshot); /// @return the name of this generator. static std::string GetActualName() { return "Green Hills MULTI"; } diff --git a/Source/cmGlobalJOMMakefileGenerator.cxx b/Source/cmGlobalJOMMakefileGenerator.cxx index cfa5072..50e7053 100644 --- a/Source/cmGlobalJOMMakefileGenerator.cxx +++ b/Source/cmGlobalJOMMakefileGenerator.cxx @@ -13,12 +13,19 @@ #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" -cmGlobalJOMMakefileGenerator::cmGlobalJOMMakefileGenerator() +cmGlobalJOMMakefileGenerator::cmGlobalJOMMakefileGenerator(cmake* cm) + : cmGlobalUnixMakefileGenerator3(cm) { this->FindMakeProgramFile = "CMakeJOMFindMake.cmake"; this->ForceUnixPaths = false; this->ToolSupportsColor = true; this->UseLinkScript = false; + cm->GetState()->SetWindowsShell(true); + cm->GetState()->SetNMake(true); + this->DefineWindowsNULL = true; + this->PassMakeflags = true; + this->UnixCD = false; + this->MakeSilentFlag = "/nologo"; } void cmGlobalJOMMakefileGenerator @@ -44,23 +51,6 @@ void cmGlobalJOMMakefileGenerator this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional); } -///! Create a local generator appropriate to this Global Generator -cmLocalGenerator * -cmGlobalJOMMakefileGenerator::CreateLocalGenerator(cmLocalGenerator* parent) -{ - cmLocalUnixMakefileGenerator3* lg - = new cmLocalUnixMakefileGenerator3(parent); - lg->SetDefineWindowsNULL(true); - lg->SetWindowsShell(true); - lg->SetMakeSilentFlag("/nologo"); - lg->SetGlobalGenerator(this); - lg->SetIgnoreLibPrefix(true); - lg->SetPassMakeflags(true); - lg->SetNMake(true); - lg->SetUnixCD(false); - return lg; -} - //---------------------------------------------------------------------------- void cmGlobalJOMMakefileGenerator ::GetDocumentation(cmDocumentationEntry& entry) diff --git a/Source/cmGlobalJOMMakefileGenerator.h b/Source/cmGlobalJOMMakefileGenerator.h index 4831309..2185b23 100644 --- a/Source/cmGlobalJOMMakefileGenerator.h +++ b/Source/cmGlobalJOMMakefileGenerator.h @@ -22,7 +22,7 @@ class cmGlobalJOMMakefileGenerator : public cmGlobalUnixMakefileGenerator3 { public: - cmGlobalJOMMakefileGenerator(); + cmGlobalJOMMakefileGenerator(cmake* cm); static cmGlobalGeneratorFactory* NewFactory() { return new cmGlobalGeneratorSimpleFactory <cmGlobalJOMMakefileGenerator>(); } @@ -36,9 +36,6 @@ public: /** Get the documentation entry for this generator. */ static void GetDocumentation(cmDocumentationEntry& entry); - ///! Create a local generator appropriate to this Global Generator - virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent = 0); - /** * Try to determine system information such as shared library * extension, pthreads, byte order etc. diff --git a/Source/cmGlobalMSYSMakefileGenerator.cxx b/Source/cmGlobalMSYSMakefileGenerator.cxx index fa23491..a84923b 100644 --- a/Source/cmGlobalMSYSMakefileGenerator.cxx +++ b/Source/cmGlobalMSYSMakefileGenerator.cxx @@ -15,12 +15,14 @@ #include "cmake.h" #include <cmsys/FStream.hxx> -cmGlobalMSYSMakefileGenerator::cmGlobalMSYSMakefileGenerator() +cmGlobalMSYSMakefileGenerator::cmGlobalMSYSMakefileGenerator(cmake* cm) + : cmGlobalUnixMakefileGenerator3(cm) { this->FindMakeProgramFile = "CMakeMSYSFindMake.cmake"; this->ForceUnixPaths = true; this->ToolSupportsColor = true; this->UseLinkScript = false; + cm->GetState()->SetMSYSShell(true); } std::string @@ -92,21 +94,6 @@ void cmGlobalMSYSMakefileGenerator } } -///! Create a local generator appropriate to this Global Generator -cmLocalGenerator * -cmGlobalMSYSMakefileGenerator::CreateLocalGenerator(cmLocalGenerator* parent) -{ - cmLocalUnixMakefileGenerator3* lg = - new cmLocalUnixMakefileGenerator3(parent); - lg->SetWindowsShell(false); - lg->SetMSYSShell(true); - lg->SetGlobalGenerator(this); - lg->SetIgnoreLibPrefix(true); - lg->SetPassMakeflags(false); - lg->SetUnixCD(true); - return lg; -} - //---------------------------------------------------------------------------- void cmGlobalMSYSMakefileGenerator ::GetDocumentation(cmDocumentationEntry& entry) diff --git a/Source/cmGlobalMSYSMakefileGenerator.h b/Source/cmGlobalMSYSMakefileGenerator.h index 1795d86..2cefc97 100644 --- a/Source/cmGlobalMSYSMakefileGenerator.h +++ b/Source/cmGlobalMSYSMakefileGenerator.h @@ -22,7 +22,7 @@ class cmGlobalMSYSMakefileGenerator : public cmGlobalUnixMakefileGenerator3 { public: - cmGlobalMSYSMakefileGenerator(); + cmGlobalMSYSMakefileGenerator(cmake* cm); static cmGlobalGeneratorFactory* NewFactory() { return new cmGlobalGeneratorSimpleFactory <cmGlobalMSYSMakefileGenerator>(); } @@ -35,9 +35,6 @@ public: /** Get the documentation entry for this generator. */ static void GetDocumentation(cmDocumentationEntry& entry); - ///! Create a local generator appropriate to this Global Generator - virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent = 0); - /** * Try to determine system information such as shared library * extension, pthreads, byte order etc. diff --git a/Source/cmGlobalMinGWMakefileGenerator.cxx b/Source/cmGlobalMinGWMakefileGenerator.cxx index c9389aa..b6e52d7 100644 --- a/Source/cmGlobalMinGWMakefileGenerator.cxx +++ b/Source/cmGlobalMinGWMakefileGenerator.cxx @@ -13,12 +13,15 @@ #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" -cmGlobalMinGWMakefileGenerator::cmGlobalMinGWMakefileGenerator() +cmGlobalMinGWMakefileGenerator::cmGlobalMinGWMakefileGenerator(cmake* cm) + : cmGlobalUnixMakefileGenerator3(cm) { this->FindMakeProgramFile = "CMakeMinGWFindMake.cmake"; this->ForceUnixPaths = true; this->ToolSupportsColor = true; this->UseLinkScript = true; + cm->GetState()->SetWindowsShell(true); + cm->GetState()->SetMinGWMake(true); } void cmGlobalMinGWMakefileGenerator @@ -26,25 +29,36 @@ void cmGlobalMinGWMakefileGenerator cmMakefile *mf, bool optional) { - this->EnableMinGWLanguage(mf); + this->FindMakeProgram(mf); + std::string makeProgram = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM"); + std::vector<std::string> locations; + locations.push_back(cmSystemTools::GetProgramPath(makeProgram)); + locations.push_back("/mingw/bin"); + locations.push_back("c:/mingw/bin"); + std::string tgcc = cmSystemTools::FindProgram("gcc", locations); + std::string gcc = "gcc.exe"; + if(!tgcc.empty()) + { + gcc = tgcc; + } + std::string tgxx = cmSystemTools::FindProgram("g++", locations); + std::string gxx = "g++.exe"; + if(!tgxx.empty()) + { + gxx = tgxx; + } + std::string trc = cmSystemTools::FindProgram("windres", locations); + std::string rc = "windres.exe"; + if(!trc.empty()) + { + rc = trc; + } + mf->AddDefinition("CMAKE_GENERATOR_CC", gcc.c_str()); + mf->AddDefinition("CMAKE_GENERATOR_CXX", gxx.c_str()); + mf->AddDefinition("CMAKE_GENERATOR_RC", rc.c_str()); this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional); } -///! Create a local generator appropriate to this Global Generator -cmLocalGenerator * -cmGlobalMinGWMakefileGenerator::CreateLocalGenerator(cmLocalGenerator* parent) -{ - cmLocalUnixMakefileGenerator3* lg = - new cmLocalUnixMakefileGenerator3(parent); - lg->SetWindowsShell(true); - lg->SetGlobalGenerator(this); - lg->SetIgnoreLibPrefix(true); - lg->SetPassMakeflags(false); - lg->SetUnixCD(true); - lg->SetMinGWMake(true); - return lg; -} - //---------------------------------------------------------------------------- void cmGlobalMinGWMakefileGenerator ::GetDocumentation(cmDocumentationEntry& entry) diff --git a/Source/cmGlobalMinGWMakefileGenerator.h b/Source/cmGlobalMinGWMakefileGenerator.h index 93f67be..3b00126 100644 --- a/Source/cmGlobalMinGWMakefileGenerator.h +++ b/Source/cmGlobalMinGWMakefileGenerator.h @@ -22,7 +22,7 @@ class cmGlobalMinGWMakefileGenerator : public cmGlobalUnixMakefileGenerator3 { public: - cmGlobalMinGWMakefileGenerator(); + cmGlobalMinGWMakefileGenerator(cmake* cm); static cmGlobalGeneratorFactory* NewFactory() { return new cmGlobalGeneratorSimpleFactory <cmGlobalMinGWMakefileGenerator>(); } @@ -34,9 +34,6 @@ public: /** Get the documentation entry for this generator. */ static void GetDocumentation(cmDocumentationEntry& entry); - ///! Create a local generator appropriate to this Global Generator - virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent = 0); - /** * Try to determine system information such as shared library * extension, pthreads, byte order etc. diff --git a/Source/cmGlobalNMakeMakefileGenerator.cxx b/Source/cmGlobalNMakeMakefileGenerator.cxx index a3b3dd7..4219c34 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.cxx +++ b/Source/cmGlobalNMakeMakefileGenerator.cxx @@ -13,12 +13,19 @@ #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" -cmGlobalNMakeMakefileGenerator::cmGlobalNMakeMakefileGenerator() +cmGlobalNMakeMakefileGenerator::cmGlobalNMakeMakefileGenerator(cmake* cm) + : cmGlobalUnixMakefileGenerator3(cm) { this->FindMakeProgramFile = "CMakeNMakeFindMake.cmake"; this->ForceUnixPaths = false; this->ToolSupportsColor = true; this->UseLinkScript = false; + cm->GetState()->SetWindowsShell(true); + cm->GetState()->SetNMake(true); + this->DefineWindowsNULL = true; + this->PassMakeflags = true; + this->UnixCD = false; + this->MakeSilentFlag = "/nologo"; } void cmGlobalNMakeMakefileGenerator @@ -44,23 +51,6 @@ void cmGlobalNMakeMakefileGenerator this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional); } -///! Create a local generator appropriate to this Global Generator -cmLocalGenerator * -cmGlobalNMakeMakefileGenerator::CreateLocalGenerator(cmLocalGenerator* parent) -{ - cmLocalUnixMakefileGenerator3* lg = - new cmLocalUnixMakefileGenerator3(parent); - lg->SetDefineWindowsNULL(true); - lg->SetWindowsShell(true); - lg->SetMakeSilentFlag("/nologo"); - lg->SetGlobalGenerator(this); - lg->SetIgnoreLibPrefix(true); - lg->SetPassMakeflags(true); - lg->SetNMake(true); - lg->SetUnixCD(false); - return lg; -} - //---------------------------------------------------------------------------- void cmGlobalNMakeMakefileGenerator ::GetDocumentation(cmDocumentationEntry& entry) diff --git a/Source/cmGlobalNMakeMakefileGenerator.h b/Source/cmGlobalNMakeMakefileGenerator.h index cb898ba..dd72c49 100644 --- a/Source/cmGlobalNMakeMakefileGenerator.h +++ b/Source/cmGlobalNMakeMakefileGenerator.h @@ -22,7 +22,7 @@ class cmGlobalNMakeMakefileGenerator : public cmGlobalUnixMakefileGenerator3 { public: - cmGlobalNMakeMakefileGenerator(); + cmGlobalNMakeMakefileGenerator(cmake* cm); static cmGlobalGeneratorFactory* NewFactory() { return new cmGlobalGeneratorSimpleFactory <cmGlobalNMakeMakefileGenerator>(); } @@ -34,9 +34,6 @@ public: /** Get the documentation entry for this generator. */ static void GetDocumentation(cmDocumentationEntry& entry); - ///! Create a local generator appropriate to this Global Generator - virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent = 0); - /** * Try to determine system information such as shared library * extension, pthreads, byte order etc. diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 074c4d1..103d75a 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -21,6 +21,7 @@ #include <algorithm> #include <assert.h> +#include <ctype.h> const char* cmGlobalNinjaGenerator::NINJA_BUILD_FILE = "build.ninja"; const char* cmGlobalNinjaGenerator::NINJA_RULES_FILE = "rules.ninja"; @@ -57,6 +58,28 @@ void cmGlobalNinjaGenerator::WriteComment(std::ostream& os, os << "# " << replace.substr(lpos) << "\n\n"; } +std::string cmGlobalNinjaGenerator::EncodeRuleName(std::string const& name) +{ + // Ninja rule names must match "[a-zA-Z0-9_.-]+". Use ".xx" to encode + // "." and all invalid characters as hexadecimal. + std::string encoded; + for (std::string::const_iterator i = name.begin(); + i != name.end(); ++i) + { + if (isalnum(*i) || *i == '_' || *i == '-') + { + encoded += *i; + } + else + { + char buf[16]; + sprintf(buf, ".%02x", static_cast<unsigned int>(*i)); + encoded += buf; + } + } + return encoded; +} + static bool IsIdentChar(char c) { return @@ -96,7 +119,7 @@ std::string cmGlobalNinjaGenerator::EncodePath(const std::string &path) { std::string result = path; #ifdef _WIN32 - if(UsingMinGW) + if (this->IsGCCOnWindows()) cmSystemTools::ReplaceString(result, "\\", "/"); else cmSystemTools::ReplaceString(result, "/", "\\"); @@ -120,7 +143,8 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os, const cmNinjaDeps& orderOnlyDeps, const cmNinjaVars& variables, const std::string& rspfile, - int cmdLineLimit) + int cmdLineLimit, + bool* usedResponseFile) { // Make sure there is a rule. if(rule.empty()) @@ -205,15 +229,20 @@ void cmGlobalNinjaGenerator::WriteBuild(std::ostream& os, std::string buildstr = build; std::string assignments = variable_assignments.str(); const std::string& args = arguments; + bool useResponseFile = false; if (cmdLineLimit > 0 && args.size() + buildstr.size() + assignments.size() > (size_t) cmdLineLimit) { - buildstr += "_RSP_FILE"; variable_assignments.str(std::string()); cmGlobalNinjaGenerator::WriteVariable(variable_assignments, "RSP_FILE", rspfile, "", 1); assignments += variable_assignments.str(); + useResponseFile = true; } + if (usedResponseFile) + { + *usedResponseFile = useResponseFile; + } os << buildstr << args << assignments; } @@ -300,12 +329,10 @@ void cmGlobalNinjaGenerator::AddMacOSXContentRule() { cmLocalGenerator *lg = this->LocalGenerators[0]; - cmMakefile* mfRoot = lg->GetMakefile(); std::ostringstream cmd; - cmd << lg->ConvertToOutputFormat( - mfRoot->GetRequiredDefinition("CMAKE_COMMAND"), - cmLocalGenerator::SHELL) + cmd << lg->ConvertToOutputFormat(cmSystemTools::GetCMakeCommand(), + cmLocalGenerator::SHELL) << " -E copy $in $out"; this->AddRule("COPY_OSX_CONTENT", @@ -477,16 +504,20 @@ void cmGlobalNinjaGenerator::WriteDefault(std::ostream& os, } -cmGlobalNinjaGenerator::cmGlobalNinjaGenerator() - : cmGlobalGenerator() +cmGlobalNinjaGenerator::cmGlobalNinjaGenerator(cmake* cm) + : cmGlobalGenerator(cm) , BuildFileStream(0) , RulesFileStream(0) , CompileCommandsStream(0) , Rules() , AllDependencies() + , UsingGCCOnWindows(false) , ComputingUnknownDependencies(false) , PolicyCMP0058(cmPolicies::WARN) { +#ifdef _WIN32 + cm->GetState()->SetWindowsShell(true); +#endif // // Ninja is not ported to non-Unix OS yet. // this->ForceUnixPaths = true; this->FindMakeProgramFile = "CMakeNinjaFindMake.cmake"; @@ -497,11 +528,10 @@ cmGlobalNinjaGenerator::cmGlobalNinjaGenerator() // Virtual public methods. cmLocalGenerator* -cmGlobalNinjaGenerator::CreateLocalGenerator(cmLocalGenerator* parent) +cmGlobalNinjaGenerator::CreateLocalGenerator(cmLocalGenerator* parent, + cmState::Snapshot snapshot) { - cmLocalGenerator* lg = new cmLocalNinjaGenerator(parent); - lg->SetGlobalGenerator(this); - return lg; + return new cmLocalNinjaGenerator(this, parent, snapshot); } void cmGlobalNinjaGenerator @@ -544,24 +574,16 @@ void cmGlobalNinjaGenerator::Generate() this->CloseBuildFileStream(); } -// Implemented in all cmGlobaleGenerator sub-classes. -// Used in: -// Source/cmMakefile.cxx: void cmGlobalNinjaGenerator ::EnableLanguage(std::vector<std::string>const& langs, - cmMakefile* makefile, + cmMakefile* mf, bool optional) { - if (makefile->IsOn("CMAKE_COMPILER_IS_MINGW")) - { - UsingMinGW = true; - this->EnableMinGWLanguage(makefile); - } if (std::find(langs.begin(), langs.end(), "Fortran") != langs.end()) { cmSystemTools::Error("The Ninja generator does not support Fortran yet."); } - this->cmGlobalGenerator::EnableLanguage(langs, makefile, optional); + this->cmGlobalGenerator::EnableLanguage(langs, mf, optional); for(std::vector<std::string>::const_iterator l = langs.begin(); l != langs.end(); ++l) { @@ -569,12 +591,20 @@ void cmGlobalNinjaGenerator { continue; } - this->ResolveLanguageCompiler(*l, makefile, optional); + this->ResolveLanguageCompiler(*l, mf, optional); } +#ifdef _WIN32 + if (mf->IsOn("CMAKE_COMPILER_IS_MINGW") || + strcmp(mf->GetSafeDefinition("CMAKE_C_COMPILER_ID"), "GNU") == 0 || + strcmp(mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID"), "GNU") == 0 || + strcmp(mf->GetSafeDefinition("CMAKE_C_SIMULATE_ID"), "GNU") == 0 || + strcmp(mf->GetSafeDefinition("CMAKE_CXX_SIMULATE_ID"), "GNU") == 0) + { + this->UsingGCCOnWindows = true; + } +#endif } -bool cmGlobalNinjaGenerator::UsingMinGW = false; - // Implemented by: // cmGlobalUnixMakefileGenerator3 // cmGlobalGhsMultiGenerator @@ -1103,9 +1133,7 @@ void cmGlobalNinjaGenerator::WriteUnknownExplicitDependencies(std::ostream& os) if (!warnExplicitDepends.empty()) { std::ostringstream w; - w << - (this->GetCMakeInstance()->GetPolicies()-> - GetPolicyWarning(cmPolicies::CMP0058)) << "\n" + w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0058) << "\n" "This project specifies custom command DEPENDS on files " "in the build tree that are not specified as the OUTPUT or " "BYPRODUCTS of any add_custom_command or add_custom_target:\n" @@ -1155,9 +1183,8 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os) cmMakefile* mfRoot = lg->GetMakefile(); std::ostringstream cmd; - cmd << lg->ConvertToOutputFormat( - mfRoot->GetRequiredDefinition("CMAKE_COMMAND"), - cmLocalGenerator::SHELL) + cmd << lg->ConvertToOutputFormat(cmSystemTools::GetCMakeCommand(), + cmLocalGenerator::SHELL) << " -H" << lg->ConvertToOutputFormat(mfRoot->GetHomeDirectory(), cmLocalGenerator::SHELL) diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index d7b3add..ffd1cdc 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -61,9 +61,10 @@ public: /// Write a divider in the given output stream @a os. static void WriteDivider(std::ostream& os); + static std::string EncodeRuleName(std::string const& name); static std::string EncodeIdent(const std::string &ident, std::ostream &vars); static std::string EncodeLiteral(const std::string &lit); - static std::string EncodePath(const std::string &path); + std::string EncodePath(const std::string &path); static std::string EncodeDepfileSpace(const std::string &path); /** @@ -87,7 +88,8 @@ public: const cmNinjaDeps& orderOnlyDeps, const cmNinjaVars& variables, const std::string& rspfile = std::string(), - int cmdLineLimit = -1); + int cmdLineLimit = -1, + bool* usedResponseFile = 0); /** * Helper to write a build statement with the special 'phony' rule. @@ -155,13 +157,10 @@ public: const cmNinjaDeps& targets, const std::string& comment = ""); - - static bool IsMinGW() { return UsingMinGW; } - + bool IsGCCOnWindows() const { return UsingGCCOnWindows; } public: - /// Default constructor. - cmGlobalNinjaGenerator(); + cmGlobalNinjaGenerator(cmake* cm); /// Convenience method for creating an instance of this class. static cmGlobalGeneratorFactory* NewFactory() { @@ -171,7 +170,8 @@ public: virtual ~cmGlobalNinjaGenerator() { } /// Overloaded methods. @see cmGlobalGenerator::CreateLocalGenerator() - virtual cmLocalGenerator* CreateLocalGenerator(cmLocalGenerator* parent = 0); + virtual cmLocalGenerator* CreateLocalGenerator(cmLocalGenerator* parent, + cmState::Snapshot snapshot); /// Overloaded methods. @see cmGlobalGenerator::GetName(). virtual std::string GetName() const { @@ -362,6 +362,8 @@ private: /// The set of dependencies to add to the "all" target. cmNinjaDeps AllDependencies; + bool UsingGCCOnWindows; + /// The set of custom commands we have seen. std::set<cmCustomCommand const*> CustomCommands; @@ -385,9 +387,6 @@ private: typedef std::map<std::string, cmTarget*> TargetAliasMap; TargetAliasMap TargetAliases; - - static bool UsingMinGW; - }; #endif // ! cmGlobalNinjaGenerator_h diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index 95998ae..4fe52dd 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -20,7 +20,8 @@ #include "cmGeneratorTarget.h" #include "cmAlgorithms.h" -cmGlobalUnixMakefileGenerator3::cmGlobalUnixMakefileGenerator3() +cmGlobalUnixMakefileGenerator3::cmGlobalUnixMakefileGenerator3(cmake* cm) + : cmGlobalGenerator(cm) { // This type of makefile always requires unix style paths this->ForceUnixPaths = true; @@ -33,6 +34,11 @@ cmGlobalUnixMakefileGenerator3::cmGlobalUnixMakefileGenerator3() this->UseLinkScript = true; #endif this->CommandDatabase = NULL; + + this->IncludeDirective = "include"; + this->DefineWindowsNULL = false; + this->PassMakeflags = false; + this->UnixCD = true; } void cmGlobalUnixMakefileGenerator3 @@ -54,11 +60,10 @@ void cmGlobalUnixMakefileGenerator3 ///! Create a local generator appropriate to this Global Generator cmLocalGenerator * -cmGlobalUnixMakefileGenerator3::CreateLocalGenerator(cmLocalGenerator* parent) +cmGlobalUnixMakefileGenerator3::CreateLocalGenerator(cmLocalGenerator* parent, + cmState::Snapshot snapshot) { - cmLocalGenerator* lg = new cmLocalUnixMakefileGenerator3(parent); - lg->SetGlobalGenerator(this); - return lg; + return new cmLocalUnixMakefileGenerator3(this, parent, snapshot); } //---------------------------------------------------------------------------- @@ -524,7 +529,7 @@ cmGlobalUnixMakefileGenerator3 cmLocalUnixMakefileGenerator3* lg) { // Only subdirectories need these rules. - if(!lg->GetParent()) + if(lg->IsRootMakefile()) { return; } @@ -582,7 +587,7 @@ void cmGlobalUnixMakefileGenerator3 else { lg = static_cast<cmLocalUnixMakefileGenerator3 *> - (this->CreateLocalGenerator()); + (this->MakeLocalGenerator()); // set the Start directories lg->GetMakefile()->SetCurrentSourceDirectory (this->CMakeInstance->GetHomeDirectory()); @@ -1029,7 +1034,7 @@ void cmGlobalUnixMakefileGenerator3::WriteHelpRule static_cast<cmLocalUnixMakefileGenerator3 *>(this->LocalGenerators[i]); // for the passed in makefile or if this is the top Makefile wripte out // the targets - if (lg2 == lg || !lg->GetParent()) + if (lg2 == lg || lg->IsRootMakefile()) { // for each target Generate the rule files for each target. cmTargets& targets = lg2->GetMakefile()->GetTargets(); diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h index 165a3c8..a639ff0 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.h +++ b/Source/cmGlobalUnixMakefileGenerator3.h @@ -54,7 +54,7 @@ class cmLocalUnixMakefileGenerator3; class cmGlobalUnixMakefileGenerator3 : public cmGlobalGenerator { public: - cmGlobalUnixMakefileGenerator3(); + cmGlobalUnixMakefileGenerator3(cmake* cm); static cmGlobalGeneratorFactory* NewFactory() { return new cmGlobalGeneratorSimpleFactory <cmGlobalUnixMakefileGenerator3>(); } @@ -68,7 +68,8 @@ public: static void GetDocumentation(cmDocumentationEntry& entry); ///! Create a local generator appropriate to this Global Generator3 - virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent = 0); + virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent, + cmState::Snapshot snapshot); /** * Try to determine system information such as shared library @@ -132,6 +133,11 @@ public: virtual bool AllowDeleteOnError() const { return true; } virtual void ComputeTargetObjectDirectory(cmGeneratorTarget* gt) const; + + std::string IncludeDirective; + bool DefineWindowsNULL; + bool PassMakeflags; + bool UnixCD; protected: void WriteMainMakefile2(); void WriteMainCMakefile(); diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 6481ec2..4e8ada4 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -42,8 +42,8 @@ class cmGlobalVisualStudio10Generator::Factory : public cmGlobalGeneratorFactory { public: - virtual cmGlobalGenerator* CreateGlobalGenerator( - const std::string& name) const + virtual cmGlobalGenerator* + CreateGlobalGenerator(const std::string& name, cmake* cm) const { std::string genName; const char* p = cmVS10GenName(name, genName); @@ -51,20 +51,17 @@ public: { return 0; } if(!*p) { - return new cmGlobalVisualStudio10Generator( - genName, ""); + return new cmGlobalVisualStudio10Generator(cm, genName, ""); } if(*p++ != ' ') { return 0; } if(strcmp(p, "Win64") == 0) { - return new cmGlobalVisualStudio10Generator( - genName, "x64"); + return new cmGlobalVisualStudio10Generator(cm, genName, "x64"); } if(strcmp(p, "IA64") == 0) { - return new cmGlobalVisualStudio10Generator( - genName, "Itanium"); + return new cmGlobalVisualStudio10Generator(cm, genName, "Itanium"); } return 0; } @@ -93,9 +90,9 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio10Generator::NewFactory() } //---------------------------------------------------------------------------- -cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator( +cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator(cmake* cm, const std::string& name, const std::string& platformName) - : cmGlobalVisualStudio8Generator(name, platformName) + : cmGlobalVisualStudio8Generator(cm, name, platformName) { std::string vc10Express; this->ExpressEdition = cmSystemTools::ReadRegistryValue( @@ -105,6 +102,7 @@ cmGlobalVisualStudio10Generator::cmGlobalVisualStudio10Generator( this->SystemIsWindowsPhone = false; this->SystemIsWindowsStore = false; this->MSBuildCommandInitialized = false; + this->Version = VS10; } //---------------------------------------------------------------------------- @@ -309,13 +307,10 @@ void cmGlobalVisualStudio10Generator::WriteSLNHeader(std::ostream& fout) ///! Create a local generator appropriate to this Global Generator cmLocalGenerator * -cmGlobalVisualStudio10Generator::CreateLocalGenerator(cmLocalGenerator* parent) +cmGlobalVisualStudio10Generator::CreateLocalGenerator(cmLocalGenerator* parent, + cmState::Snapshot snapshot) { - cmLocalVisualStudio10Generator* lg = - new cmLocalVisualStudio10Generator(cmLocalVisualStudioGenerator::VS10, - parent); - lg->SetGlobalGenerator(this); - return lg; + return new cmLocalVisualStudio10Generator(this, parent, snapshot); } //---------------------------------------------------------------------------- diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index 8cb2588..74d5022 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -24,7 +24,7 @@ class cmGlobalVisualStudio10Generator : public cmGlobalVisualStudio8Generator { public: - cmGlobalVisualStudio10Generator(const std::string& name, + cmGlobalVisualStudio10Generator(cmake* cm, const std::string& name, const std::string& platformName); static cmGlobalGeneratorFactory* NewFactory(); @@ -46,7 +46,8 @@ public: ); ///! create the correct local generator - virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent = 0); + virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent, + cmState::Snapshot snapshot); /** * Try to determine system information such as shared library diff --git a/Source/cmGlobalVisualStudio11Generator.cxx b/Source/cmGlobalVisualStudio11Generator.cxx index 45d6d95..419bf8a 100644 --- a/Source/cmGlobalVisualStudio11Generator.cxx +++ b/Source/cmGlobalVisualStudio11Generator.cxx @@ -37,8 +37,8 @@ class cmGlobalVisualStudio11Generator::Factory : public cmGlobalGeneratorFactory { public: - virtual cmGlobalGenerator* CreateGlobalGenerator( - const std::string& name) const + virtual cmGlobalGenerator* + CreateGlobalGenerator(const std::string& name, cmake* cm) const { std::string genName; const char* p = cmVS11GenName(name, genName); @@ -46,20 +46,17 @@ public: { return 0; } if(!*p) { - return new cmGlobalVisualStudio11Generator( - genName, ""); + return new cmGlobalVisualStudio11Generator(cm, genName, ""); } if(*p++ != ' ') { return 0; } if(strcmp(p, "Win64") == 0) { - return new cmGlobalVisualStudio11Generator( - genName, "x64"); + return new cmGlobalVisualStudio11Generator(cm, genName, "x64"); } if(strcmp(p, "ARM") == 0) { - return new cmGlobalVisualStudio11Generator( - genName, "ARM"); + return new cmGlobalVisualStudio11Generator(cm, genName, "ARM"); } std::set<std::string> installedSDKs = @@ -71,7 +68,7 @@ public: } cmGlobalVisualStudio11Generator* ret = - new cmGlobalVisualStudio11Generator(name, p); + new cmGlobalVisualStudio11Generator(cm, name, p); ret->WindowsCEVersion = "8.00"; return ret; } @@ -108,15 +105,16 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio11Generator::NewFactory() } //---------------------------------------------------------------------------- -cmGlobalVisualStudio11Generator::cmGlobalVisualStudio11Generator( +cmGlobalVisualStudio11Generator::cmGlobalVisualStudio11Generator(cmake* cm, const std::string& name, const std::string& platformName) - : cmGlobalVisualStudio10Generator(name, platformName) + : cmGlobalVisualStudio10Generator(cm, name, platformName) { std::string vc11Express; this->ExpressEdition = cmSystemTools::ReadRegistryValue( "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\11.0\\Setup\\VC;" "ProductDir", vc11Express, cmSystemTools::KeyWOW64_32); this->DefaultPlatformToolset = "v110"; + this->Version = VS11; } //---------------------------------------------------------------------------- @@ -237,17 +235,6 @@ void cmGlobalVisualStudio11Generator::WriteSLNHeader(std::ostream& fout) } //---------------------------------------------------------------------------- -cmLocalGenerator * -cmGlobalVisualStudio11Generator::CreateLocalGenerator(cmLocalGenerator* parent) -{ - cmLocalVisualStudio10Generator* lg = - new cmLocalVisualStudio10Generator(cmLocalVisualStudioGenerator::VS11, - parent); - lg->SetGlobalGenerator(this); - return lg; -} - -//---------------------------------------------------------------------------- bool cmGlobalVisualStudio11Generator::UseFolderProperty() { // Intentionally skip over the parent class implementation and call the diff --git a/Source/cmGlobalVisualStudio11Generator.h b/Source/cmGlobalVisualStudio11Generator.h index ae4b888..b50f4c9 100644 --- a/Source/cmGlobalVisualStudio11Generator.h +++ b/Source/cmGlobalVisualStudio11Generator.h @@ -20,7 +20,7 @@ class cmGlobalVisualStudio11Generator: public cmGlobalVisualStudio10Generator { public: - cmGlobalVisualStudio11Generator(const std::string& name, + cmGlobalVisualStudio11Generator(cmake* cm, const std::string& name, const std::string& platformName); static cmGlobalGeneratorFactory* NewFactory(); @@ -28,9 +28,6 @@ public: virtual void WriteSLNHeader(std::ostream& fout); - ///! create the correct local generator - virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent = 0); - protected: virtual bool InitializeWindowsPhone(cmMakefile* mf); virtual bool InitializeWindowsStore(cmMakefile* mf); diff --git a/Source/cmGlobalVisualStudio12Generator.cxx b/Source/cmGlobalVisualStudio12Generator.cxx index e298b06..efa1133 100644 --- a/Source/cmGlobalVisualStudio12Generator.cxx +++ b/Source/cmGlobalVisualStudio12Generator.cxx @@ -37,8 +37,8 @@ class cmGlobalVisualStudio12Generator::Factory : public cmGlobalGeneratorFactory { public: - virtual cmGlobalGenerator* CreateGlobalGenerator( - const std::string& name) const + virtual cmGlobalGenerator* + CreateGlobalGenerator(const std::string& name, cmake* cm) const { std::string genName; const char* p = cmVS12GenName(name, genName); @@ -46,20 +46,17 @@ public: { return 0; } if(!*p) { - return new cmGlobalVisualStudio12Generator( - genName, ""); + return new cmGlobalVisualStudio12Generator(cm, genName, ""); } if(*p++ != ' ') { return 0; } if(strcmp(p, "Win64") == 0) { - return new cmGlobalVisualStudio12Generator( - genName, "x64"); + return new cmGlobalVisualStudio12Generator(cm, genName, "x64"); } if(strcmp(p, "ARM") == 0) { - return new cmGlobalVisualStudio12Generator( - genName, "ARM"); + return new cmGlobalVisualStudio12Generator(cm, genName, "ARM"); } return 0; } @@ -88,15 +85,16 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio12Generator::NewFactory() } //---------------------------------------------------------------------------- -cmGlobalVisualStudio12Generator::cmGlobalVisualStudio12Generator( +cmGlobalVisualStudio12Generator::cmGlobalVisualStudio12Generator(cmake* cm, const std::string& name, const std::string& platformName) - : cmGlobalVisualStudio11Generator(name, platformName) + : cmGlobalVisualStudio11Generator(cm, name, platformName) { std::string vc12Express; this->ExpressEdition = cmSystemTools::ReadRegistryValue( "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\12.0\\Setup\\VC;" "ProductDir", vc12Express, cmSystemTools::KeyWOW64_32); this->DefaultPlatformToolset = "v120"; + this->Version = VS12; } //---------------------------------------------------------------------------- @@ -217,17 +215,6 @@ void cmGlobalVisualStudio12Generator::WriteSLNHeader(std::ostream& fout) } //---------------------------------------------------------------------------- -cmLocalGenerator * -cmGlobalVisualStudio12Generator::CreateLocalGenerator(cmLocalGenerator* parent) -{ - cmLocalVisualStudio10Generator* lg = - new cmLocalVisualStudio10Generator(cmLocalVisualStudioGenerator::VS12, - parent); - lg->SetGlobalGenerator(this); - return lg; -} - -//---------------------------------------------------------------------------- bool cmGlobalVisualStudio12Generator::IsWindowsDesktopToolsetInstalled() const { diff --git a/Source/cmGlobalVisualStudio12Generator.h b/Source/cmGlobalVisualStudio12Generator.h index d304bc1..bce9e0c 100644 --- a/Source/cmGlobalVisualStudio12Generator.h +++ b/Source/cmGlobalVisualStudio12Generator.h @@ -20,7 +20,7 @@ class cmGlobalVisualStudio12Generator: public cmGlobalVisualStudio11Generator { public: - cmGlobalVisualStudio12Generator(const std::string& name, + cmGlobalVisualStudio12Generator(cmake* cm, const std::string& name, const std::string& platformName); static cmGlobalGeneratorFactory* NewFactory(); @@ -28,9 +28,6 @@ public: virtual void WriteSLNHeader(std::ostream& fout); - ///! create the correct local generator - virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent = 0); - //in Visual Studio 2013 they detached the MSBuild tools version //from the .Net Framework version and instead made it have it's own //version number diff --git a/Source/cmGlobalVisualStudio14Generator.cxx b/Source/cmGlobalVisualStudio14Generator.cxx index 6642d88..2cf55d4 100644 --- a/Source/cmGlobalVisualStudio14Generator.cxx +++ b/Source/cmGlobalVisualStudio14Generator.cxx @@ -37,8 +37,8 @@ class cmGlobalVisualStudio14Generator::Factory : public cmGlobalGeneratorFactory { public: - virtual cmGlobalGenerator* CreateGlobalGenerator( - const std::string& name) const + virtual cmGlobalGenerator* + CreateGlobalGenerator(const std::string& name, cmake* cm) const { std::string genName; const char* p = cmVS14GenName(name, genName); @@ -46,20 +46,17 @@ public: { return 0; } if(!*p) { - return new cmGlobalVisualStudio14Generator( - genName, ""); + return new cmGlobalVisualStudio14Generator(cm, genName, ""); } if(*p++ != ' ') { return 0; } if(strcmp(p, "Win64") == 0) { - return new cmGlobalVisualStudio14Generator( - genName, "x64"); + return new cmGlobalVisualStudio14Generator(cm, genName, "x64"); } if(strcmp(p, "ARM") == 0) { - return new cmGlobalVisualStudio14Generator( - genName, "ARM"); + return new cmGlobalVisualStudio14Generator(cm, genName, "ARM"); } return 0; } @@ -88,15 +85,16 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio14Generator::NewFactory() } //---------------------------------------------------------------------------- -cmGlobalVisualStudio14Generator::cmGlobalVisualStudio14Generator( +cmGlobalVisualStudio14Generator::cmGlobalVisualStudio14Generator(cmake* cm, const std::string& name, const std::string& platformName) - : cmGlobalVisualStudio12Generator(name, platformName) + : cmGlobalVisualStudio12Generator(cm, name, platformName) { std::string vc14Express; this->ExpressEdition = cmSystemTools::ReadRegistryValue( "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\14.0\\Setup\\VC;" "ProductDir", vc14Express, cmSystemTools::KeyWOW64_32); this->DefaultPlatformToolset = "v140"; + this->Version = VS14; } //---------------------------------------------------------------------------- @@ -126,14 +124,3 @@ void cmGlobalVisualStudio14Generator::WriteSLNHeader(std::ostream& fout) fout << "# Visual Studio 14\n"; } } - -//---------------------------------------------------------------------------- -cmLocalGenerator * -cmGlobalVisualStudio14Generator::CreateLocalGenerator(cmLocalGenerator* parent) -{ - cmLocalVisualStudio10Generator* lg = - new cmLocalVisualStudio10Generator(cmLocalVisualStudioGenerator::VS14, - parent); - lg->SetGlobalGenerator(this); - return lg; -} diff --git a/Source/cmGlobalVisualStudio14Generator.h b/Source/cmGlobalVisualStudio14Generator.h index 59f1e60..aa817be 100644 --- a/Source/cmGlobalVisualStudio14Generator.h +++ b/Source/cmGlobalVisualStudio14Generator.h @@ -20,7 +20,7 @@ class cmGlobalVisualStudio14Generator: public cmGlobalVisualStudio12Generator { public: - cmGlobalVisualStudio14Generator(const std::string& name, + cmGlobalVisualStudio14Generator(cmake* cm, const std::string& name, const std::string& platformName); static cmGlobalGeneratorFactory* NewFactory(); @@ -28,9 +28,6 @@ public: virtual void WriteSLNHeader(std::ostream& fout); - ///! create the correct local generator - virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent = 0); - virtual const char* GetToolsVersion() { return "14.0"; } protected: virtual const char* GetIDEVersion() { return "14.0"; } diff --git a/Source/cmGlobalVisualStudio6Generator.cxx b/Source/cmGlobalVisualStudio6Generator.cxx index 55e70b3..632141a 100644 --- a/Source/cmGlobalVisualStudio6Generator.cxx +++ b/Source/cmGlobalVisualStudio6Generator.cxx @@ -31,9 +31,11 @@ std::string GetVS6TargetName(const std::string& targetName) return name; } -cmGlobalVisualStudio6Generator::cmGlobalVisualStudio6Generator() +cmGlobalVisualStudio6Generator::cmGlobalVisualStudio6Generator(cmake* cm) + : cmGlobalVisualStudioGenerator(cm) { this->MSDevCommandInitialized = false; + this->Version = VS6; } void cmGlobalVisualStudio6Generator @@ -171,11 +173,10 @@ cmGlobalVisualStudio6Generator::GenerateBuildCommand( ///! Create a local generator appropriate to this Global Generator cmLocalGenerator * -cmGlobalVisualStudio6Generator::CreateLocalGenerator(cmLocalGenerator* parent) +cmGlobalVisualStudio6Generator::CreateLocalGenerator(cmLocalGenerator* parent, + cmState::Snapshot snapshot) { - cmLocalGenerator *lg = new cmLocalVisualStudio6Generator(parent); - lg->SetGlobalGenerator(this); - return lg; + return new cmLocalVisualStudio6Generator(this, parent, snapshot); } diff --git a/Source/cmGlobalVisualStudio6Generator.h b/Source/cmGlobalVisualStudio6Generator.h index d748a85..2460158 100644 --- a/Source/cmGlobalVisualStudio6Generator.h +++ b/Source/cmGlobalVisualStudio6Generator.h @@ -25,7 +25,7 @@ class cmTarget; class cmGlobalVisualStudio6Generator : public cmGlobalVisualStudioGenerator { public: - cmGlobalVisualStudio6Generator(); + cmGlobalVisualStudio6Generator(cmake* cm); static cmGlobalGeneratorFactory* NewFactory() { return new cmGlobalGeneratorSimpleFactory <cmGlobalVisualStudio6Generator>(); } @@ -39,7 +39,8 @@ public: static void GetDocumentation(cmDocumentationEntry& entry); ///! Create a local generator appropriate to this Global Generator - virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent = 0); + virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent, + cmState::Snapshot snapshot); /** * Try to determine system information such as shared library diff --git a/Source/cmGlobalVisualStudio71Generator.cxx b/Source/cmGlobalVisualStudio71Generator.cxx index db34d44..1ab4c9c 100644 --- a/Source/cmGlobalVisualStudio71Generator.cxx +++ b/Source/cmGlobalVisualStudio71Generator.cxx @@ -16,24 +16,12 @@ #include "cmake.h" //---------------------------------------------------------------------------- -cmGlobalVisualStudio71Generator::cmGlobalVisualStudio71Generator( +cmGlobalVisualStudio71Generator::cmGlobalVisualStudio71Generator(cmake* cm, const std::string& platformName) - : cmGlobalVisualStudio7Generator(platformName) + : cmGlobalVisualStudio7Generator(cm, platformName) { this->ProjectConfigurationSectionName = "ProjectConfiguration"; -} - -//---------------------------------------------------------------------------- -///! Create a local generator appropriate to this Global Generator -cmLocalGenerator * -cmGlobalVisualStudio71Generator::CreateLocalGenerator(cmLocalGenerator* parent) -{ - cmLocalVisualStudio7Generator *lg = - new cmLocalVisualStudio7Generator(cmLocalVisualStudioGenerator::VS71, - parent); - lg->SetExtraFlagTable(this->GetExtraFlagTableVS7()); - lg->SetGlobalGenerator(this); - return lg; + this->Version = VS71; } //---------------------------------------------------------------------------- @@ -95,6 +83,9 @@ void cmGlobalVisualStudio71Generator cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators) { + std::vector<std::string> configs; + root->GetMakefile()->GetConfigurations(configs); + // Write out the header for a SLN file this->WriteSLNHeader(fout); @@ -116,11 +107,11 @@ void cmGlobalVisualStudio71Generator // Write out the configurations information for the solution fout << "Global\n"; // Write out the configurations for the solution - this->WriteSolutionConfigurations(fout); + this->WriteSolutionConfigurations(fout, configs); fout << "\tGlobalSection(" << this->ProjectConfigurationSectionName << ") = postSolution\n"; // Write out the configurations for all the targets in the project - this->WriteTargetConfigurations(fout, orderedProjectTargets); + this->WriteTargetConfigurations(fout, configs, orderedProjectTargets); fout << "\tEndGlobalSection\n"; if (useFolderProperty) @@ -141,11 +132,12 @@ void cmGlobalVisualStudio71Generator //---------------------------------------------------------------------------- void cmGlobalVisualStudio71Generator -::WriteSolutionConfigurations(std::ostream& fout) +::WriteSolutionConfigurations(std::ostream& fout, + std::vector<std::string> const& configs) { fout << "\tGlobalSection(SolutionConfiguration) = preSolution\n"; - for(std::vector<std::string>::iterator i = this->Configurations.begin(); - i != this->Configurations.end(); ++i) + for(std::vector<std::string>::const_iterator i = configs.begin(); + i != configs.end(); ++i) { fout << "\t\t" << *i << " = " << *i << "\n"; } @@ -281,14 +273,15 @@ void cmGlobalVisualStudio71Generator void cmGlobalVisualStudio71Generator ::WriteProjectConfigurations( std::ostream& fout, const std::string& name, cmTarget::TargetType, + std::vector<std::string> const& configs, const std::set<std::string>& configsPartOfDefaultBuild, std::string const& platformMapping) { const std::string& platformName = !platformMapping.empty() ? platformMapping : this->GetPlatformName(); std::string guid = this->GetGUID(name); - for(std::vector<std::string>::iterator i = this->Configurations.begin(); - i != this->Configurations.end(); ++i) + for(std::vector<std::string>::const_iterator i = configs.begin(); + i != configs.end(); ++i) { fout << "\t\t{" << guid << "}." << *i << ".ActiveCfg = " << *i << "|" << platformName << std::endl; diff --git a/Source/cmGlobalVisualStudio71Generator.h b/Source/cmGlobalVisualStudio71Generator.h index ad6c153..fbb9ecc 100644 --- a/Source/cmGlobalVisualStudio71Generator.h +++ b/Source/cmGlobalVisualStudio71Generator.h @@ -23,7 +23,8 @@ class cmGlobalVisualStudio71Generator : public cmGlobalVisualStudio7Generator { public: - cmGlobalVisualStudio71Generator(const std::string& platformName = ""); + cmGlobalVisualStudio71Generator(cmake* cm, + const std::string& platformName = ""); static cmGlobalGeneratorFactory* NewFactory() { return new cmGlobalGeneratorSimpleFactory <cmGlobalVisualStudio71Generator>(); } @@ -36,9 +37,6 @@ public: /** Get the documentation entry for this generator. */ static void GetDocumentation(cmDocumentationEntry& entry); - ///! Create a local generator appropriate to this Global Generator - virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent = 0); - /** * Where does this version of Visual Studio look for macros for the * current user? Returns the empty string if this version of Visual @@ -57,7 +55,8 @@ protected: virtual void WriteSLNFile(std::ostream& fout, cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators); - virtual void WriteSolutionConfigurations(std::ostream& fout); + virtual void WriteSolutionConfigurations( + std::ostream& fout, std::vector<std::string> const& configs); virtual void WriteProject(std::ostream& fout, const std::string& name, const char* path, cmTarget const& t); @@ -66,6 +65,7 @@ protected: cmTarget const& t); virtual void WriteProjectConfigurations( std::ostream& fout, const std::string& name, cmTarget::TargetType type, + std::vector<std::string> const& configs, const std::set<std::string>& configsPartOfDefaultBuild, const std::string& platformMapping = ""); virtual void WriteExternalProject(std::ostream& fout, diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index de90f7e..4dd54d0 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -18,8 +18,35 @@ #include "cmake.h" #include <cmsys/Encoding.hxx> -cmGlobalVisualStudio7Generator::cmGlobalVisualStudio7Generator( +//---------------------------------------------------------------------------- +static cmVS7FlagTable cmVS7ExtraFlagTable[] = +{ + // Precompiled header and related options. Note that the + // UsePrecompiledHeader entries are marked as "Continue" so that the + // corresponding PrecompiledHeaderThrough entry can be found. + {"UsePrecompiledHeader", "YX", "Automatically Generate", "2", + cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue}, + {"PrecompiledHeaderThrough", "YX", "Precompiled Header Name", "", + cmVS7FlagTable::UserValueRequired}, + {"UsePrecompiledHeader", "Yu", "Use Precompiled Header", "3", + cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue}, + {"PrecompiledHeaderThrough", "Yu", "Precompiled Header Name", "", + cmVS7FlagTable::UserValueRequired}, + {"WholeProgramOptimization", "LTCG", "WholeProgramOptimization", "true", 0}, + + // Exception handling mode. If no entries match, it will be FALSE. + {"ExceptionHandling", "GX", "enable c++ exceptions", "true", 0}, + {"ExceptionHandling", "EHsc", "enable c++ exceptions", "true", 0}, + // The EHa option does not have an IDE setting. Let it go to false, + // and have EHa passed on the command line by leaving out the table + // entry. + + {0,0,0,0,0} +}; + +cmGlobalVisualStudio7Generator::cmGlobalVisualStudio7Generator(cmake *cm, const std::string& platformName) + : cmGlobalVisualStudioGenerator(cm) { this->IntelProjectVersion = 0; this->DevEnvCommandInitialized = false; @@ -33,6 +60,8 @@ cmGlobalVisualStudio7Generator::cmGlobalVisualStudio7Generator( { this->DefaultPlatformName = platformName; } + this->ExtraFlagTable = cmVS7ExtraFlagTable; + this->Version = VS7; } cmGlobalVisualStudio7Generator::~cmGlobalVisualStudio7Generator() @@ -94,7 +123,6 @@ void cmGlobalVisualStudio7Generator // Create list of configurations requested by user's cache, if any. this->cmGlobalGenerator::EnableLanguage(lang, mf, optional); - this->GenerateConfigurations(mf); // if this environment variable is set, then copy it to // a static cache entry. It will be used by @@ -251,13 +279,11 @@ void cmGlobalVisualStudio7Generator::GenerateBuildCommand( ///! Create a local generator appropriate to this Global Generator cmLocalGenerator * -cmGlobalVisualStudio7Generator::CreateLocalGenerator(cmLocalGenerator* parent) +cmGlobalVisualStudio7Generator::CreateLocalGenerator(cmLocalGenerator* parent, + cmState::Snapshot snapshot) { cmLocalVisualStudio7Generator *lg = - new cmLocalVisualStudio7Generator(cmLocalVisualStudioGenerator::VS7, - parent); - lg->SetExtraFlagTable(this->GetExtraFlagTableVS7()); - lg->SetGlobalGenerator(this); + new cmLocalVisualStudio7Generator(this, parent, snapshot); return lg; } @@ -296,50 +322,6 @@ bool cmGlobalVisualStudio7Generator::SetGeneratorPlatform(std::string const& p, return this->cmGlobalVisualStudioGenerator::SetGeneratorPlatform(p, mf); } -void cmGlobalVisualStudio7Generator::GenerateConfigurations(cmMakefile* mf) -{ - // process the configurations - const char* ct - = this->CMakeInstance->GetCacheDefinition("CMAKE_CONFIGURATION_TYPES"); - if ( ct ) - { - std::vector<std::string> argsOut; - cmSystemTools::ExpandListArgument(ct, argsOut); - for(std::vector<std::string>::iterator i = argsOut.begin(); - i != argsOut.end(); ++i) - { - if(std::find(this->Configurations.begin(), - this->Configurations.end(), - *i) == this->Configurations.end()) - { - this->Configurations.push_back(*i); - } - } - } - // default to at least Debug and Release - if(this->Configurations.size() == 0) - { - this->Configurations.push_back("Debug"); - this->Configurations.push_back("Release"); - } - - // Reset the entry to have a semi-colon separated list. - std::string configs = this->Configurations[0]; - for(unsigned int i=1; i < this->Configurations.size(); ++i) - { - configs += ";"; - configs += this->Configurations[i]; - } - - mf->AddCacheDefinition( - "CMAKE_CONFIGURATION_TYPES", - configs.c_str(), - "Semicolon separated list of supported configuration types, " - "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, " - "anything else will be ignored.", - cmState::STRING); -} - void cmGlobalVisualStudio7Generator::Generate() { // first do the superclass method @@ -411,6 +393,7 @@ void cmGlobalVisualStudio7Generator::OutputSLNFile() void cmGlobalVisualStudio7Generator::WriteTargetConfigurations( std::ostream& fout, + std::vector<std::string> const& configs, OrderedTargetDependSet const& projectTargets) { // loop over again and write out configurations for each target @@ -426,23 +409,22 @@ void cmGlobalVisualStudio7Generator::WriteTargetConfigurations( const char* expath = target->GetProperty("EXTERNAL_MSPROJECT"); if(expath) { - std::set<std::string> allConfigurations(this->Configurations.begin(), - this->Configurations.end()); + std::set<std::string> allConfigurations(configs.begin(), configs.end()); const char* mapping = target->GetProperty("VS_PLATFORM_MAPPING"); this->WriteProjectConfigurations( fout, target->GetName().c_str(), target->GetType(), - allConfigurations, mapping ? mapping : ""); + configs, allConfigurations, mapping ? mapping : ""); } else { const std::set<std::string>& configsPartOfDefaultBuild = - this->IsPartOfDefaultBuild(projectTargets, target); + this->IsPartOfDefaultBuild(configs, projectTargets, target); const char *vcprojName = target->GetProperty("GENERATOR_FILE_NAME"); if (vcprojName) { this->WriteProjectConfigurations(fout, vcprojName, target->GetType(), - configsPartOfDefaultBuild); + configs, configsPartOfDefaultBuild); } } } @@ -577,6 +559,9 @@ void cmGlobalVisualStudio7Generator cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators) { + std::vector<std::string> configs; + root->GetMakefile()->GetConfigurations(configs); + // Write out the header for a SLN file this->WriteSLNHeader(fout); @@ -600,8 +585,8 @@ void cmGlobalVisualStudio7Generator << "\tGlobalSection(SolutionConfiguration) = preSolution\n"; int c = 0; - for(std::vector<std::string>::iterator i = this->Configurations.begin(); - i != this->Configurations.end(); ++i) + for(std::vector<std::string>::iterator i = configs.begin(); + i != configs.end(); ++i) { fout << "\t\tConfigName." << c << " = " << *i << "\n"; c++; @@ -622,7 +607,7 @@ void cmGlobalVisualStudio7Generator // Write out the configurations for all the targets in the project fout << "\tGlobalSection(ProjectConfiguration) = postSolution\n"; - this->WriteTargetConfigurations(fout, orderedProjectTargets); + this->WriteTargetConfigurations(fout, configs, orderedProjectTargets); fout << "\tEndGlobalSection\n"; // Write out global sections @@ -778,14 +763,15 @@ cmGlobalVisualStudio7Generator void cmGlobalVisualStudio7Generator ::WriteProjectConfigurations( std::ostream& fout, const std::string& name, cmTarget::TargetType, + std::vector<std::string> const& configs, const std::set<std::string>& configsPartOfDefaultBuild, const std::string& platformMapping) { const std::string& platformName = !platformMapping.empty() ? platformMapping : this->GetPlatformName(); std::string guid = this->GetGUID(name); - for(std::vector<std::string>::iterator i = this->Configurations.begin(); - i != this->Configurations.end(); ++i) + for(std::vector<std::string>::const_iterator i = configs.begin(); + i != configs.end(); ++i) { fout << "\t\t{" << guid << "}." << *i << ".ActiveCfg = " << *i << "|" << platformName << "\n"; @@ -903,6 +889,8 @@ void cmGlobalVisualStudio7Generator::WriteSLNHeader(std::ostream& fout) std::string cmGlobalVisualStudio7Generator::WriteUtilityDepend(cmTarget const* target) { + std::vector<std::string> configs; + target->GetMakefile()->GetConfigurations(configs); std::string pname = target->GetName(); pname += "_UTILITY"; std::string fname = target->GetMakefile()->GetCurrentBinaryDirectory(); @@ -926,8 +914,8 @@ cmGlobalVisualStudio7Generator::WriteUtilityDepend(cmTarget const* target) "\t<Platforms><Platform Name=\"Win32\"/></Platforms>\n" "\t<Configurations>\n" ; - for(std::vector<std::string>::iterator i = this->Configurations.begin(); - i != this->Configurations.end(); ++i) + for(std::vector<std::string>::iterator i = configs.begin(); + i != configs.end(); ++i) { fout << "\t\t<Configuration\n" @@ -992,11 +980,6 @@ void cmGlobalVisualStudio7Generator::CreateGUID(const std::string& name) cmState::INTERNAL); } -std::vector<std::string> *cmGlobalVisualStudio7Generator::GetConfigurations() -{ - return &this->Configurations; -}; - //---------------------------------------------------------------------------- void cmGlobalVisualStudio7Generator ::GetDocumentation(cmDocumentationEntry& entry) @@ -1023,6 +1006,7 @@ cmGlobalVisualStudio7Generator std::set<std::string> cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild( + std::vector<std::string> const& configs, OrderedTargetDependSet const& projectTargets, cmTarget const* target) { std::set<std::string> activeConfigs; @@ -1031,6 +1015,24 @@ cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild( int type = target->GetType(); if (type == cmTarget::GLOBAL_TARGET) { + // check if INSTALL target is part of default build + if(target->GetName() == "INSTALL") + { + // inspect CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD properties + for(std::vector<std::string>::const_iterator i = configs.begin(); + i != configs.end(); ++i) + { + const char* propertyValue = target->GetMakefile() + ->GetDefinition("CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD"); + cmGeneratorExpression ge; + cmsys::auto_ptr<cmCompiledGeneratorExpression> + cge = ge.Parse(propertyValue); + if(cmSystemTools::IsOn(cge->Evaluate(target->GetMakefile(), *i))) + { + activeConfigs.insert(*i); + } + } + } return activeConfigs; } if(type == cmTarget::UTILITY && !this->IsDependedOn(projectTargets, target)) @@ -1038,8 +1040,8 @@ cmGlobalVisualStudio7Generator::IsPartOfDefaultBuild( return activeConfigs; } // inspect EXCLUDE_FROM_DEFAULT_BUILD[_<CONFIG>] properties - for(std::vector<std::string>::iterator i = this->Configurations.begin(); - i != this->Configurations.end(); ++i) + for(std::vector<std::string>::const_iterator i = configs.begin(); + i != configs.end(); ++i) { const char* propertyValue = target->GetFeature("EXCLUDE_FROM_DEFAULT_BUILD", i->c_str()); @@ -1069,36 +1071,6 @@ cmGlobalVisualStudio7Generator return false; } -//---------------------------------------------------------------------------- -static cmVS7FlagTable cmVS7ExtraFlagTable[] = -{ - // Precompiled header and related options. Note that the - // UsePrecompiledHeader entries are marked as "Continue" so that the - // corresponding PrecompiledHeaderThrough entry can be found. - {"UsePrecompiledHeader", "YX", "Automatically Generate", "2", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue}, - {"PrecompiledHeaderThrough", "YX", "Precompiled Header Name", "", - cmVS7FlagTable::UserValueRequired}, - {"UsePrecompiledHeader", "Yu", "Use Precompiled Header", "3", - cmVS7FlagTable::UserValueIgnored | cmVS7FlagTable::Continue}, - {"PrecompiledHeaderThrough", "Yu", "Precompiled Header Name", "", - cmVS7FlagTable::UserValueRequired}, - {"WholeProgramOptimization", "LTCG", "WholeProgramOptimization", "true", 0}, - - // Exception handling mode. If no entries match, it will be FALSE. - {"ExceptionHandling", "GX", "enable c++ exceptions", "true", 0}, - {"ExceptionHandling", "EHsc", "enable c++ exceptions", "true", 0}, - // The EHa option does not have an IDE setting. Let it go to false, - // and have EHa passed on the command line by leaving out the table - // entry. - - {0,0,0,0,0} -}; -cmIDEFlagTable const* cmGlobalVisualStudio7Generator::GetExtraFlagTableVS7() -{ - return cmVS7ExtraFlagTable; -} - std::string cmGlobalVisualStudio7Generator::Encoding() { std::ostringstream encoding; diff --git a/Source/cmGlobalVisualStudio7Generator.h b/Source/cmGlobalVisualStudio7Generator.h index 92c5f1a..c98d269 100644 --- a/Source/cmGlobalVisualStudio7Generator.h +++ b/Source/cmGlobalVisualStudio7Generator.h @@ -26,7 +26,8 @@ struct cmIDEFlagTable; class cmGlobalVisualStudio7Generator : public cmGlobalVisualStudioGenerator { public: - cmGlobalVisualStudio7Generator(const std::string& platformName = ""); + cmGlobalVisualStudio7Generator(cmake* cm, + const std::string& platformName = ""); ~cmGlobalVisualStudio7Generator(); static cmGlobalGeneratorFactory* NewFactory() { @@ -42,7 +43,8 @@ public: std::string const& GetPlatformName() const; ///! Create a local generator appropriate to this Global Generator - virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent = 0); + virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent, + cmState::Snapshot snapshot); virtual bool SetSystemName(std::string const& s, cmMakefile* mf); @@ -78,11 +80,6 @@ public: */ virtual void OutputSLNFile(); - /** - * Get the list of configurations - */ - std::vector<std::string> *GetConfigurations(); - ///! Create a GUID or get an existing one. void CreateGUID(const std::string& name); std::string GetGUID(const std::string& name); @@ -111,6 +108,8 @@ public: // Encoding for Visual Studio files virtual std::string Encoding(); + cmIDEFlagTable const* ExtraFlagTable; + protected: virtual void Generate(); virtual const char* GetIDEVersion() { return "7.0"; } @@ -120,7 +119,6 @@ protected: static const char* ExternalProjectType(const char* location); - static cmIDEFlagTable const* GetExtraFlagTableVS7(); virtual void OutputSLNFile(cmLocalGenerator* root, std::vector<cmLocalGenerator*>& generators); virtual void WriteSLNFile(std::ostream& fout, cmLocalGenerator* root, @@ -133,6 +131,7 @@ protected: cmTarget const&t); virtual void WriteProjectConfigurations( std::ostream& fout, const std::string& name, cmTarget::TargetType type, + std::vector<std::string> const& configs, const std::set<std::string>& configsPartOfDefaultBuild, const std::string& platformMapping = ""); virtual void WriteSLNGlobalSections(std::ostream& fout, @@ -150,10 +149,9 @@ protected: OrderedTargetDependSet const& projectTargets); virtual void WriteTargetConfigurations( std::ostream& fout, + std::vector<std::string> const& configs, OrderedTargetDependSet const& projectTargets); - void GenerateConfigurations(cmMakefile* mf); - virtual void WriteExternalProject(std::ostream& fout, const std::string& name, const char* path, @@ -164,11 +162,11 @@ protected: std::string ConvertToSolutionPath(const char* path); std::set<std::string> - IsPartOfDefaultBuild(OrderedTargetDependSet const& projectTargets, + IsPartOfDefaultBuild(std::vector<std::string> const& configs, + OrderedTargetDependSet const& projectTargets, cmTarget const* target); bool IsDependedOn(OrderedTargetDependSet const& projectTargets, cmTarget const* target); - std::vector<std::string> Configurations; std::map<std::string, std::string> GUIDMap; virtual void WriteFolders(std::ostream& fout); diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index 7174f21..a3ebc61 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -24,8 +24,8 @@ class cmGlobalVisualStudio8Generator::Factory : public cmGlobalGeneratorFactory { public: - virtual cmGlobalGenerator* CreateGlobalGenerator( - const std::string& name) const { + virtual cmGlobalGenerator* + CreateGlobalGenerator(const std::string& name, cmake* cm) const { if(strncmp(name.c_str(), vs8generatorName, sizeof(vs8generatorName) - 1) != 0) { @@ -35,8 +35,7 @@ public: const char* p = name.c_str() + sizeof(vs8generatorName) - 1; if(p[0] == '\0') { - return new cmGlobalVisualStudio8Generator( - name, ""); + return new cmGlobalVisualStudio8Generator(cm, name, ""); } if(p[0] != ' ') @@ -48,8 +47,7 @@ public: if(!strcmp(p, "Win64")) { - return new cmGlobalVisualStudio8Generator( - name, "x64"); + return new cmGlobalVisualStudio8Generator(cm, name, "x64"); } cmVisualStudioWCEPlatformParser parser(p); @@ -59,8 +57,8 @@ public: return 0; } - cmGlobalVisualStudio8Generator* ret = new cmGlobalVisualStudio8Generator( - name, p); + cmGlobalVisualStudio8Generator* ret = + new cmGlobalVisualStudio8Generator(cm, name, p); ret->WindowsCEVersion = parser.GetOSVersion(); return ret; } @@ -95,12 +93,14 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio8Generator::NewFactory() } //---------------------------------------------------------------------------- -cmGlobalVisualStudio8Generator::cmGlobalVisualStudio8Generator( +cmGlobalVisualStudio8Generator::cmGlobalVisualStudio8Generator(cmake* cm, const std::string& name, const std::string& platformName) - : cmGlobalVisualStudio71Generator(platformName) + : cmGlobalVisualStudio71Generator(cm, platformName) { this->ProjectConfigurationSectionName = "ProjectConfigurationPlatforms"; this->Name = name; + this->ExtraFlagTable = this->GetExtraFlagTableVS8(); + this->Version = VS8; } //---------------------------------------------------------------------------- @@ -124,19 +124,6 @@ std::string cmGlobalVisualStudio8Generator::FindDevEnvCommand() } //---------------------------------------------------------------------------- -///! Create a local generator appropriate to this Global Generator -cmLocalGenerator * -cmGlobalVisualStudio8Generator::CreateLocalGenerator(cmLocalGenerator* parent) -{ - cmLocalVisualStudio7Generator *lg = - new cmLocalVisualStudio7Generator(cmLocalVisualStudioGenerator::VS8, - parent); - lg->SetExtraFlagTable(this->GetExtraFlagTableVS8()); - lg->SetGlobalGenerator(this); - return lg; -} - -//---------------------------------------------------------------------------- void cmGlobalVisualStudio8Generator ::EnableLanguage(std::vector<std::string>const & lang, cmMakefile *mf, bool optional) @@ -263,7 +250,6 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() return false; } - std::string cmake_command = mf->GetRequiredDefinition("CMAKE_COMMAND"); cmCustomCommandLines noCommandLines; cmTarget* tgt = mf->AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, false, @@ -321,9 +307,8 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() // Create a rule to re-run CMake. std::string stampName = cmake::GetCMakeFilesDirectoryPostSlash(); stampName += "generate.stamp"; - const char* dsprule = mf->GetRequiredDefinition("CMAKE_COMMAND"); cmCustomCommandLine commandLine; - commandLine.push_back(dsprule); + commandLine.push_back(cmSystemTools::GetCMakeCommand()); std::string argH = "-H"; argH += lg->Convert(mf->GetHomeDirectory(), cmLocalGenerator::START_OUTPUT, @@ -388,11 +373,12 @@ void cmGlobalVisualStudio8Generator::Generate() //---------------------------------------------------------------------------- void cmGlobalVisualStudio8Generator -::WriteSolutionConfigurations(std::ostream& fout) +::WriteSolutionConfigurations(std::ostream& fout, + std::vector<std::string> const& configs) { fout << "\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\n"; - for(std::vector<std::string>::iterator i = this->Configurations.begin(); - i != this->Configurations.end(); ++i) + for(std::vector<std::string>::const_iterator i = configs.begin(); + i != configs.end(); ++i) { fout << "\t\t" << *i << "|" << this->GetPlatformName() << " = " << *i << "|" << this->GetPlatformName() << "\n"; @@ -405,12 +391,13 @@ void cmGlobalVisualStudio8Generator ::WriteProjectConfigurations( std::ostream& fout, const std::string& name, cmTarget::TargetType type, + std::vector<std::string> const& configs, const std::set<std::string>& configsPartOfDefaultBuild, std::string const& platformMapping) { std::string guid = this->GetGUID(name); - for(std::vector<std::string>::iterator i = this->Configurations.begin(); - i != this->Configurations.end(); ++i) + for(std::vector<std::string>::const_iterator i = configs.begin(); + i != configs.end(); ++i) { fout << "\t\t{" << guid << "}." << *i << "|" << this->GetPlatformName() << ".ActiveCfg = " << *i << "|" diff --git a/Source/cmGlobalVisualStudio8Generator.h b/Source/cmGlobalVisualStudio8Generator.h index ee5ba9f..cc02b78 100644 --- a/Source/cmGlobalVisualStudio8Generator.h +++ b/Source/cmGlobalVisualStudio8Generator.h @@ -23,7 +23,7 @@ class cmGlobalVisualStudio8Generator : public cmGlobalVisualStudio71Generator { public: - cmGlobalVisualStudio8Generator(const std::string& name, + cmGlobalVisualStudio8Generator(cmake* cm, const std::string& name, const std::string& platformName); static cmGlobalGeneratorFactory* NewFactory(); @@ -33,9 +33,6 @@ public: /** Get the documentation entry for this generator. */ static void GetDocumentation(cmDocumentationEntry& entry); - ///! Create a local generator appropriate to this Global Generator - virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent = 0); - virtual void EnableLanguage(std::vector<std::string>const& languages, cmMakefile *, bool optional); virtual void AddPlatformDefinitions(cmMakefile* mf); @@ -84,9 +81,11 @@ protected: static cmIDEFlagTable const* GetExtraFlagTableVS8(); virtual void WriteSLNHeader(std::ostream& fout); - virtual void WriteSolutionConfigurations(std::ostream& fout); + virtual void WriteSolutionConfigurations( + std::ostream& fout, std::vector<std::string> const& configs); virtual void WriteProjectConfigurations( std::ostream& fout, const std::string& name, cmTarget::TargetType type, + std::vector<std::string> const& configs, const std::set<std::string>& configsPartOfDefaultBuild, const std::string& platformMapping = ""); virtual bool ComputeTargetDepends(); diff --git a/Source/cmGlobalVisualStudio9Generator.cxx b/Source/cmGlobalVisualStudio9Generator.cxx index 0303c27..d98793a 100644 --- a/Source/cmGlobalVisualStudio9Generator.cxx +++ b/Source/cmGlobalVisualStudio9Generator.cxx @@ -22,8 +22,8 @@ class cmGlobalVisualStudio9Generator::Factory : public cmGlobalGeneratorFactory { public: - virtual cmGlobalGenerator* CreateGlobalGenerator( - const std::string& name) const { + virtual cmGlobalGenerator* + CreateGlobalGenerator(const std::string& name, cmake* cm) const { if(strncmp(name.c_str(), vs9generatorName, sizeof(vs9generatorName) - 1) != 0) { @@ -33,8 +33,7 @@ public: const char* p = name.c_str() + sizeof(vs9generatorName) - 1; if(p[0] == '\0') { - return new cmGlobalVisualStudio9Generator( - name, ""); + return new cmGlobalVisualStudio9Generator(cm, name, ""); } if(p[0] != ' ') @@ -46,14 +45,12 @@ public: if(!strcmp(p, "IA64")) { - return new cmGlobalVisualStudio9Generator( - name, "Itanium"); + return new cmGlobalVisualStudio9Generator(cm, name, "Itanium"); } if(!strcmp(p, "Win64")) { - return new cmGlobalVisualStudio9Generator( - name, "x64"); + return new cmGlobalVisualStudio9Generator(cm, name, "x64"); } cmVisualStudioWCEPlatformParser parser(p); @@ -63,8 +60,8 @@ public: return 0; } - cmGlobalVisualStudio9Generator* ret = new cmGlobalVisualStudio9Generator( - name, p); + cmGlobalVisualStudio9Generator* ret = + new cmGlobalVisualStudio9Generator(cm, name, p); ret->WindowsCEVersion = parser.GetOSVersion(); return ret; } @@ -100,10 +97,11 @@ cmGlobalGeneratorFactory* cmGlobalVisualStudio9Generator::NewFactory() } //---------------------------------------------------------------------------- -cmGlobalVisualStudio9Generator::cmGlobalVisualStudio9Generator( +cmGlobalVisualStudio9Generator::cmGlobalVisualStudio9Generator(cmake* cm, const std::string& name, const std::string& platformName) - : cmGlobalVisualStudio8Generator(name, platformName) + : cmGlobalVisualStudio8Generator(cm, name, platformName) { + this->Version = VS9; } //---------------------------------------------------------------------------- @@ -113,18 +111,6 @@ void cmGlobalVisualStudio9Generator::WriteSLNHeader(std::ostream& fout) fout << "# Visual Studio 2008\n"; } -///! Create a local generator appropriate to this Global Generator -cmLocalGenerator * -cmGlobalVisualStudio9Generator::CreateLocalGenerator(cmLocalGenerator* parent) -{ - cmLocalVisualStudio7Generator *lg - = new cmLocalVisualStudio7Generator(cmLocalVisualStudioGenerator::VS9, - parent); - lg->SetExtraFlagTable(this->GetExtraFlagTableVS8()); - lg->SetGlobalGenerator(this); - return lg; -} - //---------------------------------------------------------------------------- std::string cmGlobalVisualStudio9Generator::GetUserMacrosDirectory() { diff --git a/Source/cmGlobalVisualStudio9Generator.h b/Source/cmGlobalVisualStudio9Generator.h index 97b7804..e25a4be 100644 --- a/Source/cmGlobalVisualStudio9Generator.h +++ b/Source/cmGlobalVisualStudio9Generator.h @@ -24,13 +24,10 @@ class cmGlobalVisualStudio9Generator : public cmGlobalVisualStudio8Generator { public: - cmGlobalVisualStudio9Generator(const std::string& name, + cmGlobalVisualStudio9Generator(cmake* cm, const std::string& name, const std::string& platformName); static cmGlobalGeneratorFactory* NewFactory(); - ///! create the correct local generator - virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent = 0); - /** * Try to determine system information such as shared library * extension, pthreads, byte order etc. diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index 60d545b..585d19a 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -21,8 +21,11 @@ #include <cmsys/Encoding.hxx> //---------------------------------------------------------------------------- -cmGlobalVisualStudioGenerator::cmGlobalVisualStudioGenerator() +cmGlobalVisualStudioGenerator::cmGlobalVisualStudioGenerator(cmake* cm) + : cmGlobalGenerator(cm) { + cm->GetState()->SetWindowsShell(true); + cm->GetState()->SetWindowsVSIDE(true); } //---------------------------------------------------------------------------- @@ -31,6 +34,19 @@ cmGlobalVisualStudioGenerator::~cmGlobalVisualStudioGenerator() } //---------------------------------------------------------------------------- +cmGlobalVisualStudioGenerator::VSVersion +cmGlobalVisualStudioGenerator::GetVersion() const +{ + return this->Version; +} + +//---------------------------------------------------------------------------- +void cmGlobalVisualStudioGenerator::SetVersion(VSVersion v) +{ + this->Version = v; +} + +//---------------------------------------------------------------------------- std::string cmGlobalVisualStudioGenerator::GetRegistryBase() { return cmGlobalVisualStudioGenerator::GetRegistryBase( diff --git a/Source/cmGlobalVisualStudioGenerator.h b/Source/cmGlobalVisualStudioGenerator.h index cb54132..69b4564 100644 --- a/Source/cmGlobalVisualStudioGenerator.h +++ b/Source/cmGlobalVisualStudioGenerator.h @@ -23,9 +23,27 @@ class cmGlobalVisualStudioGenerator : public cmGlobalGenerator { public: - cmGlobalVisualStudioGenerator(); + /** Known versions of Visual Studio. */ + enum VSVersion + { + VS6 = 60, + VS7 = 70, + VS71 = 71, + VS8 = 80, + VS9 = 90, + VS10 = 100, + VS11 = 110, + VS12 = 120, + /* VS13 = 130 was skipped */ + VS14 = 140 + }; + + cmGlobalVisualStudioGenerator(cmake* cm); virtual ~cmGlobalVisualStudioGenerator(); + VSVersion GetVersion() const; + void SetVersion(VSVersion v); + /** * Configure CMake's Visual Studio macros file into the user's Visual * Studio macros directory. @@ -107,6 +125,9 @@ protected: typedef std::map<cmTarget const*, std::string> UtilityDependsMap; UtilityDependsMap UtilityDepends; +protected: + VSVersion Version; + private: virtual std::string GetVSMakeProgram() = 0; void PrintCompilerAdvice(std::ostream&, std::string const&, diff --git a/Source/cmGlobalWatcomWMakeGenerator.cxx b/Source/cmGlobalWatcomWMakeGenerator.cxx index 77c6474..153773f 100644 --- a/Source/cmGlobalWatcomWMakeGenerator.cxx +++ b/Source/cmGlobalWatcomWMakeGenerator.cxx @@ -13,7 +13,8 @@ #include "cmLocalUnixMakefileGenerator3.h" #include "cmMakefile.h" -cmGlobalWatcomWMakeGenerator::cmGlobalWatcomWMakeGenerator() +cmGlobalWatcomWMakeGenerator::cmGlobalWatcomWMakeGenerator(cmake* cm) + : cmGlobalUnixMakefileGenerator3(cm) { this->FindMakeProgramFile = "CMakeFindWMake.cmake"; #ifdef _WIN32 @@ -22,6 +23,14 @@ cmGlobalWatcomWMakeGenerator::cmGlobalWatcomWMakeGenerator() this->ToolSupportsColor = true; this->NeedSymbolicMark = true; this->EmptyRuleHackCommand = "@cd ."; +#ifdef _WIN32 + cm->GetState()->SetWindowsShell(true); +#endif + cm->GetState()->SetWatcomWMake(true); + this->IncludeDirective = "!include"; + this->DefineWindowsNULL = true; + this->UnixCD = false; + this->MakeSilentFlag = "-h"; } void cmGlobalWatcomWMakeGenerator @@ -40,26 +49,6 @@ void cmGlobalWatcomWMakeGenerator this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional); } -///! Create a local generator appropriate to this Global Generator -cmLocalGenerator * -cmGlobalWatcomWMakeGenerator::CreateLocalGenerator(cmLocalGenerator* parent) -{ - cmLocalUnixMakefileGenerator3* lg - = new cmLocalUnixMakefileGenerator3(parent); - lg->SetDefineWindowsNULL(true); -#ifdef _WIN32 - lg->SetWindowsShell(true); -#endif - lg->SetWatcomWMake(true); - lg->SetMakeSilentFlag("-h"); - lg->SetGlobalGenerator(this); - lg->SetIgnoreLibPrefix(true); - lg->SetPassMakeflags(false); - lg->SetUnixCD(false); - lg->SetIncludeDirective("!include"); - return lg; -} - //---------------------------------------------------------------------------- void cmGlobalWatcomWMakeGenerator ::GetDocumentation(cmDocumentationEntry& entry) diff --git a/Source/cmGlobalWatcomWMakeGenerator.h b/Source/cmGlobalWatcomWMakeGenerator.h index 3af2f9d..4bfcf06 100644 --- a/Source/cmGlobalWatcomWMakeGenerator.h +++ b/Source/cmGlobalWatcomWMakeGenerator.h @@ -22,7 +22,7 @@ class cmGlobalWatcomWMakeGenerator : public cmGlobalUnixMakefileGenerator3 { public: - cmGlobalWatcomWMakeGenerator(); + cmGlobalWatcomWMakeGenerator(cmake* cm); static cmGlobalGeneratorFactory* NewFactory() { return new cmGlobalGeneratorSimpleFactory <cmGlobalWatcomWMakeGenerator>(); } @@ -34,9 +34,6 @@ public: /** Get the documentation entry for this generator. */ static void GetDocumentation(cmDocumentationEntry& entry); - ///! Create a local generator appropriate to this Global Generator - virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent = 0); - /** * Try to determine system information such as shared library * extension, pthreads, byte order etc. diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 742750c..7464e90 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -117,8 +117,8 @@ public: class cmGlobalXCodeGenerator::Factory : public cmGlobalGeneratorFactory { public: - virtual cmGlobalGenerator* CreateGlobalGenerator( - const std::string& name) const; + virtual cmGlobalGenerator* + CreateGlobalGenerator(const std::string& name, cmake* cm) const; virtual void GetDocumentation(cmDocumentationEntry& entry) const { cmGlobalXCodeGenerator::GetDocumentation(entry); } @@ -128,7 +128,9 @@ public: }; //---------------------------------------------------------------------------- -cmGlobalXCodeGenerator::cmGlobalXCodeGenerator(std::string const& version) +cmGlobalXCodeGenerator::cmGlobalXCodeGenerator(cmake* cm, + std::string const& version) + : cmGlobalGenerator(cm) { this->VersionString = version; @@ -154,7 +156,7 @@ cmGlobalGeneratorFactory* cmGlobalXCodeGenerator::NewFactory() //---------------------------------------------------------------------------- cmGlobalGenerator* cmGlobalXCodeGenerator::Factory -::CreateGlobalGenerator(const std::string& name) const +::CreateGlobalGenerator(const std::string& name, cmake* cm) const { if (name != GetActualName()) return 0; @@ -187,7 +189,7 @@ cmGlobalGenerator* cmGlobalXCodeGenerator::Factory ("/Developer/Applications/Xcode.app/Contents/version.plist"); } cmsys::auto_ptr<cmGlobalXCodeGenerator> - gg(new cmGlobalXCodeGenerator(parser.Version)); + gg(new cmGlobalXCodeGenerator(cm, parser.Version)); if (gg->XcodeVersion == 20) { cmSystemTools::Message("Xcode 2.0 not really supported by cmake, " @@ -198,7 +200,7 @@ cmGlobalGenerator* cmGlobalXCodeGenerator::Factory #else std::cerr << "CMake should be built with cmake to use Xcode, " "default to Xcode 1.5\n"; - return new cmGlobalXCodeGenerator; + return new cmGlobalXCodeGenerator(cm); #endif } @@ -369,11 +371,10 @@ cmGlobalXCodeGenerator::GenerateBuildCommand( //---------------------------------------------------------------------------- ///! Create a local generator appropriate to this Global Generator cmLocalGenerator * -cmGlobalXCodeGenerator::CreateLocalGenerator(cmLocalGenerator* parent) +cmGlobalXCodeGenerator::CreateLocalGenerator(cmLocalGenerator* parent, + cmState::Snapshot snapshot) { - cmLocalGenerator *lg = new cmLocalXCodeGenerator(parent); - lg->SetGlobalGenerator(this); - return lg; + return new cmLocalXCodeGenerator(this, parent, snapshot); } //---------------------------------------------------------------------------- @@ -584,8 +585,8 @@ void cmGlobalXCodeGenerator::CreateReRunCMakeFile( { makefileStream << "\\\n" << this->ConvertToRelativeForMake(i->c_str()); } - std::string cmake = mf->GetRequiredDefinition("CMAKE_COMMAND"); - makefileStream << "\n\t" << this->ConvertToRelativeForMake(cmake.c_str()) + makefileStream << "\n\t" << + this->ConvertToRelativeForMake(cmSystemTools::GetCMakeCommand().c_str()) << " -H" << this->ConvertToRelativeForMake( mf->GetHomeDirectory()) << " -B" << this->ConvertToRelativeForMake( @@ -1449,7 +1450,7 @@ void cmGlobalXCodeGenerator::CreateCustomCommands(cmXCodeObject* buildPhases, { cmCustomCommandLines cmd; cmd.resize(1); - cmd[0].push_back(this->CurrentMakefile->GetDefinition("CMAKE_COMMAND")); + cmd[0].push_back(cmSystemTools::GetCMakeCommand()); cmd[0].push_back("-E"); cmd[0].push_back("cmake_symlink_library"); std::string str_file = "$<TARGET_FILE:"; diff --git a/Source/cmGlobalXCodeGenerator.h b/Source/cmGlobalXCodeGenerator.h index 6c911a4..c36e4af 100644 --- a/Source/cmGlobalXCodeGenerator.h +++ b/Source/cmGlobalXCodeGenerator.h @@ -29,7 +29,7 @@ class cmSourceGroup; class cmGlobalXCodeGenerator : public cmGlobalGenerator { public: - cmGlobalXCodeGenerator(std::string const& version); + cmGlobalXCodeGenerator(cmake* cm, std::string const& version); static cmGlobalGeneratorFactory* NewFactory(); ///! Get the name for the generator. @@ -41,7 +41,8 @@ public: static void GetDocumentation(cmDocumentationEntry& entry); ///! Create a local generator appropriate to this Global Generator - virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent = 0); + virtual cmLocalGenerator *CreateLocalGenerator(cmLocalGenerator* parent, + cmState::Snapshot snapshot); /** * Try to determine system information such as shared library diff --git a/Source/cmGraphVizWriter.cxx b/Source/cmGraphVizWriter.cxx index 99542a9..7f4c4c9 100644 --- a/Source/cmGraphVizWriter.cxx +++ b/Source/cmGraphVizWriter.cxx @@ -65,9 +65,10 @@ void cmGraphVizWriter::ReadSettings(const char* settingsFileName, const char* fallbackSettingsFileName) { cmake cm; - cmGlobalGenerator ggi; - ggi.SetCMakeInstance(&cm); - cmsys::auto_ptr<cmLocalGenerator> lg(ggi.CreateLocalGenerator()); + cm.SetHomeDirectory(""); + cm.SetHomeOutputDirectory(""); + cmGlobalGenerator ggi(&cm); + cmsys::auto_ptr<cmLocalGenerator> lg(ggi.MakeLocalGenerator()); cmMakefile *mf = lg->GetMakefile(); const char* inFileName = settingsFileName; diff --git a/Source/cmIfCommand.cxx b/Source/cmIfCommand.cxx index 6dea5c1..3551f83 100644 --- a/Source/cmIfCommand.cxx +++ b/Source/cmIfCommand.cxx @@ -20,15 +20,14 @@ static std::string cmIfCommandError( - cmMakefile* mf, std::vector<cmExpandedCommandArgument> const& args) + std::vector<cmExpandedCommandArgument> const& args) { - cmLocalGenerator* lg = mf->GetLocalGenerator(); std::string err = "given arguments:\n "; for(std::vector<cmExpandedCommandArgument>::const_iterator i = args.begin(); i != args.end(); ++i) { err += " "; - err += lg->EscapeForCMake(i->GetValue()); + err += cmLocalGenerator::EscapeForCMake(i->GetValue()); } err += "\n"; return err; @@ -118,7 +117,7 @@ IsFunctionBlocked(const cmListFileFunction& lff, if (!errorString.empty()) { - std::string err = cmIfCommandError(&mf, expandedArguments); + std::string err = cmIfCommandError(expandedArguments); err += errorString; mf.IssueMessage(messType, err); if (messType == cmake::FATAL_ERROR) @@ -206,7 +205,7 @@ bool cmIfCommand if (!errorString.empty()) { - std::string err = cmIfCommandError(this->Makefile, expandedArguments); + std::string err = cmIfCommandError(expandedArguments); err += errorString; if (status == cmake::FATAL_ERROR) { diff --git a/Source/cmIncludeCommand.cxx b/Source/cmIncludeCommand.cxx index 71dabaf..b94ad25 100644 --- a/Source/cmIncludeCommand.cxx +++ b/Source/cmIncludeCommand.cxx @@ -93,8 +93,7 @@ bool cmIncludeCommand cmSystemTools::CollapseFullPath(fname, this->Makefile->GetCurrentSourceDirectory()); - cmGlobalGenerator *gg = this->Makefile->GetLocalGenerator() - ->GetGlobalGenerator(); + cmGlobalGenerator *gg = this->Makefile->GetGlobalGenerator(); if (gg->IsExportedTargetsFile(fname_abs)) { const char *modal = 0; @@ -104,8 +103,7 @@ bool cmIncludeCommand switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0024)) { case cmPolicies::WARN: - e << (this->Makefile->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0024)) << "\n"; + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0024) << "\n"; modal = "should"; case cmPolicies::OLD: break; diff --git a/Source/cmInstallCommand.cxx b/Source/cmInstallCommand.cxx index fac9641..899b088 100644 --- a/Source/cmInstallCommand.cxx +++ b/Source/cmInstallCommand.cxx @@ -62,8 +62,7 @@ bool cmInstallCommand::InitialPass(std::vector<std::string> const& args, } // Enable the install target. - this->Makefile->GetLocalGenerator() - ->GetGlobalGenerator()->EnableInstallTarget(); + this->Makefile->GetGlobalGenerator()->EnableInstallTarget(); this->DefaultComponentName = this->Makefile->GetSafeDefinition( "CMAKE_INSTALL_DEFAULT_COMPONENT_NAME"); @@ -198,7 +197,7 @@ bool cmInstallCommand::HandleScriptMode(std::vector<std::string> const& args) } //Tell the global generator about any installation component names specified. - this->Makefile->GetLocalGenerator()->GetGlobalGenerator() + this->Makefile->GetGlobalGenerator() ->AddInstallComponent(component.c_str()); return true; @@ -774,7 +773,7 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) te->HeaderGenerator = publicHeaderGenerator; te->LibraryGenerator = libraryGenerator; te->RuntimeGenerator = runtimeGenerator; - this->Makefile->GetLocalGenerator()->GetGlobalGenerator() + this->Makefile->GetGlobalGenerator() ->GetExportSets()[exports.GetString()]->AddTargetExport(te); te->InterfaceIncludeDirectories = @@ -786,43 +785,42 @@ bool cmInstallCommand::HandleTargetsMode(std::vector<std::string> const& args) // specified if (installsArchive) { - this->Makefile->GetLocalGenerator()-> - GetGlobalGenerator() + this->Makefile->GetGlobalGenerator() ->AddInstallComponent(archiveArgs.GetComponent().c_str()); } if (installsLibrary) { - this->Makefile->GetLocalGenerator()->GetGlobalGenerator() + this->Makefile->GetGlobalGenerator() ->AddInstallComponent(libraryArgs.GetComponent().c_str()); } if (installsRuntime) { - this->Makefile->GetLocalGenerator()->GetGlobalGenerator() + this->Makefile->GetGlobalGenerator() ->AddInstallComponent(runtimeArgs.GetComponent().c_str()); } if (installsFramework) { - this->Makefile->GetLocalGenerator()->GetGlobalGenerator() + this->Makefile->GetGlobalGenerator() ->AddInstallComponent(frameworkArgs.GetComponent().c_str()); } if (installsBundle) { - this->Makefile->GetLocalGenerator()->GetGlobalGenerator() + this->Makefile->GetGlobalGenerator() ->AddInstallComponent(bundleArgs.GetComponent().c_str()); } if (installsPrivateHeader) { - this->Makefile->GetLocalGenerator()->GetGlobalGenerator() + this->Makefile->GetGlobalGenerator() ->AddInstallComponent(privateHeaderArgs.GetComponent().c_str()); } if (installsPublicHeader) { - this->Makefile->GetLocalGenerator()->GetGlobalGenerator() + this->Makefile->GetGlobalGenerator() ->AddInstallComponent(publicHeaderArgs.GetComponent().c_str()); } if (installsResource) { - this->Makefile->GetLocalGenerator()->GetGlobalGenerator() + this->Makefile->GetGlobalGenerator() ->AddInstallComponent(resourceArgs.GetComponent().c_str()); } @@ -850,13 +848,15 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args) return false; } + const std::vector<std::string>& filesVector = files.GetVector(); + // Check if there is something to do. - if(files.GetVector().empty()) + if(filesVector.empty()) { return true; } - if(!ica.GetRename().empty() && files.GetVector().size() > 1) + if(!ica.GetRename().empty() && filesVector.size() > 1) { // The rename option works only with one file. std::ostringstream e; @@ -866,11 +866,52 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args) } std::vector<std::string> absFiles; - if (!this->MakeFilesFullPath(args[0].c_str(), files.GetVector(), absFiles)) + if (!this->MakeFilesFullPath(args[0].c_str(), filesVector, absFiles)) { return false; } + cmPolicies::PolicyStatus status = + this->Makefile->GetPolicyStatus(cmPolicies::CMP0062); + + cmGlobalGenerator *gg = this->Makefile->GetGlobalGenerator(); + for(std::vector<std::string>::const_iterator fileIt = filesVector.begin(); + fileIt != filesVector.end(); ++fileIt) + { + if (gg->IsExportedTargetsFile(*fileIt)) + { + const char *modal = 0; + std::ostringstream e; + cmake::MessageType messageType = cmake::AUTHOR_WARNING; + + switch(status) + { + case cmPolicies::WARN: + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0062) << "\n"; + modal = "should"; + case cmPolicies::OLD: + break; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + modal = "may"; + messageType = cmake::FATAL_ERROR; + } + if (modal) + { + e << "The file\n " << *fileIt << "\nwas generated by the export() " + "command. It " << modal << " not be installed with the " + "install() command. Use the install(EXPORT) mechanism " + "instead. See the cmake-packages(7) manual for more.\n"; + this->Makefile->IssueMessage(messageType, e.str()); + if (messageType == cmake::FATAL_ERROR) + { + return false; + } + } + } + } + if (!ica.Finalize()) { return false; @@ -890,7 +931,7 @@ bool cmInstallCommand::HandleFilesMode(std::vector<std::string> const& args) CreateInstallFilesGenerator(this->Makefile, absFiles, ica, programs)); //Tell the global generator about any installation component names specified. - this->Makefile->GetLocalGenerator()->GetGlobalGenerator() + this->Makefile->GetGlobalGenerator() ->AddInstallComponent(ica.GetComponent().c_str()); return true; @@ -1235,7 +1276,7 @@ cmInstallCommand::HandleDirectoryMode(std::vector<std::string> const& args) // Tell the global generator about any installation component names // specified. - this->Makefile->GetLocalGenerator()->GetGlobalGenerator() + this->Makefile->GetGlobalGenerator() ->AddInstallComponent(component.c_str()); return true; @@ -1322,8 +1363,8 @@ bool cmInstallCommand::HandleExportMode(std::vector<std::string> const& args) } } - cmExportSet *exportSet = this->Makefile->GetLocalGenerator() - ->GetGlobalGenerator()->GetExportSets()[exp.GetString()]; + cmExportSet *exportSet = this->Makefile->GetGlobalGenerator() + ->GetExportSets()[exp.GetString()]; if (exportOld.IsEnabled()) { for(std::vector<cmTargetExport*>::const_iterator @@ -1404,7 +1445,7 @@ bool cmInstallCommand::CheckCMP0006(bool& failure) { this->Makefile->IssueMessage( cmake::AUTHOR_WARNING, - this->Makefile->GetPolicies()->GetPolicyWarning(cmPolicies::CMP0006) + cmPolicies::GetPolicyWarning(cmPolicies::CMP0006) ); } case cmPolicies::OLD: @@ -1418,8 +1459,7 @@ bool cmInstallCommand::CheckCMP0006(bool& failure) failure = true; this->Makefile->IssueMessage( cmake::FATAL_ERROR, - this->Makefile->GetPolicies() - ->GetRequiredPolicyError(cmPolicies::CMP0006) + cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0006) ); break; } diff --git a/Source/cmInstallFilesCommand.cxx b/Source/cmInstallFilesCommand.cxx index 1fe435c..508c373 100644 --- a/Source/cmInstallFilesCommand.cxx +++ b/Source/cmInstallFilesCommand.cxx @@ -24,8 +24,7 @@ bool cmInstallFilesCommand } // Enable the install target. - this->Makefile->GetLocalGenerator() - ->GetGlobalGenerator()->EnableInstallTarget(); + this->Makefile->GetGlobalGenerator()->EnableInstallTarget(); this->Destination = args[0]; @@ -48,7 +47,7 @@ bool cmInstallFilesCommand args.begin() + 1, args.end()); } - this->Makefile->GetLocalGenerator()->GetGlobalGenerator() + this->Makefile->GetGlobalGenerator() ->AddInstallComponent(this->Makefile->GetSafeDefinition( "CMAKE_INSTALL_DEFAULT_COMPONENT_NAME")); diff --git a/Source/cmInstallProgramsCommand.cxx b/Source/cmInstallProgramsCommand.cxx index 4899b95..be8096c 100644 --- a/Source/cmInstallProgramsCommand.cxx +++ b/Source/cmInstallProgramsCommand.cxx @@ -22,14 +22,13 @@ bool cmInstallProgramsCommand } // Enable the install target. - this->Makefile->GetLocalGenerator() - ->GetGlobalGenerator()->EnableInstallTarget(); + this->Makefile->GetGlobalGenerator()->EnableInstallTarget(); this->Destination = args[0]; this->FinalArgs.insert(this->FinalArgs.end(), args.begin() + 1, args.end()); - this->Makefile->GetLocalGenerator()->GetGlobalGenerator() + this->Makefile->GetGlobalGenerator() ->AddInstallComponent(this->Makefile->GetSafeDefinition( "CMAKE_INSTALL_DEFAULT_COMPONENT_NAME")); diff --git a/Source/cmInstallTargetGenerator.cxx b/Source/cmInstallTargetGenerator.cxx index 11125d3..082a78c 100644 --- a/Source/cmInstallTargetGenerator.cxx +++ b/Source/cmInstallTargetGenerator.cxx @@ -728,8 +728,7 @@ cmInstallTargetGenerator i != oldRuntimeDirs.end(); ++i) { std::string runpath = - mf->GetLocalGenerator()-> - GetGlobalGenerator()->ExpandCFGIntDir(*i, config); + mf->GetGlobalGenerator()->ExpandCFGIntDir(*i, config); if(runpaths.find(runpath) == runpaths.end()) { @@ -745,8 +744,7 @@ cmInstallTargetGenerator i != newRuntimeDirs.end(); ++i) { std::string runpath = - mf->GetLocalGenerator()-> - GetGlobalGenerator()->ExpandCFGIntDir(*i, config); + mf->GetGlobalGenerator()->ExpandCFGIntDir(*i, config); if(runpaths.find(runpath) == runpaths.end()) { diff --git a/Source/cmInstallTargetsCommand.cxx b/Source/cmInstallTargetsCommand.cxx index b738844..7e7b848 100644 --- a/Source/cmInstallTargetsCommand.cxx +++ b/Source/cmInstallTargetsCommand.cxx @@ -22,8 +22,7 @@ bool cmInstallTargetsCommand } // Enable the install target. - this->Makefile->GetLocalGenerator() - ->GetGlobalGenerator()->EnableInstallTarget(); + this->Makefile->GetGlobalGenerator()->EnableInstallTarget(); cmTargets &tgts = this->Makefile->GetTargets(); std::vector<std::string>::const_iterator s = args.begin(); @@ -57,7 +56,7 @@ bool cmInstallTargetsCommand } } - this->Makefile->GetLocalGenerator()->GetGlobalGenerator() + this->Makefile->GetGlobalGenerator() ->AddInstallComponent(this->Makefile->GetSafeDefinition( "CMAKE_INSTALL_DEFAULT_COMPONENT_NAME")); diff --git a/Source/cmLinkDirectoriesCommand.cxx b/Source/cmLinkDirectoriesCommand.cxx index a21f517..f486bf7 100644 --- a/Source/cmLinkDirectoriesCommand.cxx +++ b/Source/cmLinkDirectoriesCommand.cxx @@ -40,18 +40,17 @@ void cmLinkDirectoriesCommand::AddLinkDir(std::string const& dir) e << "This command specifies the relative path\n" << " " << unixPath << "\n" << "as a link directory.\n"; - cmPolicies* policies = this->Makefile->GetPolicies(); switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0015)) { case cmPolicies::WARN: - e << policies->GetPolicyWarning(cmPolicies::CMP0015); + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0015); this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str()); case cmPolicies::OLD: // OLD behavior does not convert break; case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: - e << policies->GetRequiredPolicyError(cmPolicies::CMP0015); + e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0015); this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); case cmPolicies::NEW: // NEW behavior converts diff --git a/Source/cmListCommand.cxx b/Source/cmListCommand.cxx index d18269d..f96b4a8 100644 --- a/Source/cmListCommand.cxx +++ b/Source/cmListCommand.cxx @@ -121,8 +121,7 @@ bool cmListCommand::GetList(std::vector<std::string>& list, // empty values list.clear(); cmSystemTools::ExpandListArgument(listString, list); - std::string warn = this->Makefile->GetPolicies()-> - GetPolicyWarning(cmPolicies::CMP0007); + std::string warn = cmPolicies::GetPolicyWarning(cmPolicies::CMP0007); warn += " List has value = ["; warn += listString; warn += "]."; @@ -143,8 +142,7 @@ bool cmListCommand::GetList(std::vector<std::string>& list, case cmPolicies::REQUIRED_ALWAYS: this->Makefile->IssueMessage( cmake::FATAL_ERROR, - this->Makefile->GetPolicies() - ->GetRequiredPolicyError(cmPolicies::CMP0007) + cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0007) ); return false; } diff --git a/Source/cmListFileCache.cxx b/Source/cmListFileCache.cxx index ddcea9b..2756cd2 100644 --- a/Source/cmListFileCache.cxx +++ b/Source/cmListFileCache.cxx @@ -400,6 +400,11 @@ bool cmListFileParser::AddArgument(cmListFileLexer_Token* token, } } +void cmListFileBacktrace::Append(cmListFileContext const& context) +{ + this->push_back(context); +} + //---------------------------------------------------------------------------- void cmListFileBacktrace::MakeRelative() { @@ -416,6 +421,31 @@ void cmListFileBacktrace::MakeRelative() this->Relative = true; } +void cmListFileBacktrace::PrintTitle(std::ostream& out) +{ + if (this->empty()) + { + return; + } + out << (this->front().Line ? " at " : " in ") << this->front(); +} + +void cmListFileBacktrace::PrintCallStack(std::ostream& out) +{ + if (size() <= 1) + { + return; + } + + const_iterator i = this->begin() + 1; + out << "Call Stack (most recent call first):\n"; + while(i != this->end()) + { + cmListFileContext const& lfc = *i; + out << " " << lfc << "\n"; + ++i; + } +} //---------------------------------------------------------------------------- std::ostream& operator<<(std::ostream& os, cmListFileContext const& lfc) @@ -431,3 +461,22 @@ std::ostream& operator<<(std::ostream& os, cmListFileContext const& lfc) } return os; } + +bool operator<(const cmListFileContext& lhs, const cmListFileContext& rhs) +{ + if(lhs.Line != rhs.Line) + { + return lhs.Line < rhs.Line; + } + return lhs.FilePath < rhs.FilePath; +} + +bool operator==(const cmListFileContext& lhs, const cmListFileContext& rhs) +{ + return lhs.Line == rhs.Line && lhs.FilePath == rhs.FilePath; +} + +bool operator!=(const cmListFileContext& lhs, const cmListFileContext& rhs) +{ + return !(lhs == rhs); +} diff --git a/Source/cmListFileCache.h b/Source/cmListFileCache.h index 544ff1b..4a1d181 100644 --- a/Source/cmListFileCache.h +++ b/Source/cmListFileCache.h @@ -62,13 +62,16 @@ struct cmListFileContext }; std::ostream& operator<<(std::ostream&, cmListFileContext const&); +bool operator<(const cmListFileContext& lhs, const cmListFileContext& rhs); +bool operator==(cmListFileContext const& lhs, cmListFileContext const& rhs); +bool operator!=(cmListFileContext const& lhs, cmListFileContext const& rhs); struct cmListFileFunction: public cmListFileContext { std::vector<cmListFileArgument> Arguments; }; -class cmListFileBacktrace: public std::vector<cmListFileContext> +class cmListFileBacktrace: private std::vector<cmListFileContext> { public: cmListFileBacktrace(cmLocalGenerator* localGen) @@ -77,7 +80,12 @@ class cmListFileBacktrace: public std::vector<cmListFileContext> { } + void Append(cmListFileContext const& context); + void MakeRelative(); + + void PrintTitle(std::ostream& out); + void PrintCallStack(std::ostream& out); private: cmLocalGenerator* LocalGenerator; bool Relative; diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 6b705e8..eb6b871 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -43,27 +43,25 @@ #include <StorageDefs.h> #endif -cmLocalGenerator::cmLocalGenerator(cmLocalGenerator* parent) +cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, + cmLocalGenerator* parent, + cmState::Snapshot snapshot) + : StateSnapshot(snapshot) { - this->Makefile = 0; // moved to after set on global + assert(snapshot.IsValid()); + this->GlobalGenerator = gg; this->Parent = parent; if (parent) { parent->AddChild(this); } - this->WindowsShell = false; - this->WindowsVSIDE = false; - this->WatcomWMake = false; - this->MinGWMake = false; - this->NMake = false; - this->MSYSShell = false; + + this->Makefile = new cmMakefile(this); + this->LinkScriptShell = false; - this->IgnoreLibPrefix = false; this->UseRelativePaths = false; this->Configured = false; this->EmitUniversalBinaryFlags = true; - this->RelativePathsConfigured = false; - this->PathConversionsSetup = false; this->BackwardsCompatibility = 0; this->BackwardsCompatibilityFinal = false; } @@ -73,16 +71,24 @@ cmLocalGenerator::~cmLocalGenerator() delete this->Makefile; } +bool cmLocalGenerator::IsRootMakefile() const +{ + return !this->StateSnapshot.GetParent().IsValid(); +} + //---------------------------------------------------------------------------- class cmLocalGeneratorCurrent { cmGlobalGenerator* GG; cmLocalGenerator* LG; + cmState::Snapshot Snapshot; public: cmLocalGeneratorCurrent(cmLocalGenerator* lg) { this->GG = lg->GetGlobalGenerator(); this->LG = this->GG->GetCurrentLocalGenerator(); + this->Snapshot = this->GG->GetCMakeInstance()->GetCurrentSnapshot(); + this->GG->GetCMakeInstance()->SetCurrentSnapshot(lg->GetStateSnapshot()); this->GG->SetCurrentLocalGenerator(lg); #if defined(CMAKE_BUILD_WITH_CMAKE) this->GG->GetFileLockPool().PushFileScope(); @@ -94,6 +100,7 @@ public: this->GG->GetFileLockPool().PopFileScope(); #endif this->GG->SetCurrentLocalGenerator(this->LG); + this->GG->GetCMakeInstance()->SetCurrentSnapshot(this->Snapshot); } }; @@ -105,12 +112,14 @@ void cmLocalGenerator::Configure() static_cast<void>(clg); // make sure the CMakeFiles dir is there - std::string filesDir = this->Makefile->GetCurrentBinaryDirectory(); + std::string filesDir = this->StateSnapshot.GetCurrentBinaryDirectory(); filesDir += cmake::GetCMakeFilesDirectory(); cmSystemTools::MakeDirectory(filesDir.c_str()); - // find & read the list file - this->ReadInputFile(); + std::string currentStart = this->StateSnapshot.GetCurrentSourceDirectory(); + currentStart += "/CMakeLists.txt"; + assert(cmSystemTools::FileExists(currentStart.c_str(), true)); + this->Makefile->ProcessBuildsystemFile(currentStart.c_str()); // at the end of the ReadListFile handle any old style subdirs // first get all the subdirectories @@ -177,85 +186,6 @@ void cmLocalGenerator::ComputeObjectMaxPath() this->ObjectMaxPathViolations.clear(); } -//---------------------------------------------------------------------------- -void cmLocalGenerator::ReadInputFile() -{ - // Look for the CMakeLists.txt file. - std::string currentStart = this->Makefile->GetCurrentSourceDirectory(); - currentStart += "/CMakeLists.txt"; - if(cmSystemTools::FileExists(currentStart.c_str(), true)) - { - this->Makefile->ProcessBuildsystemFile(currentStart.c_str()); - return; - } - - if(!this->Parent) - { - return; - } - - // The file is missing. Check policy CMP0014. - cmMakefile* mf = this->Parent->GetMakefile(); - std::ostringstream e; - e << "The source directory\n" - << " " << this->Makefile->GetCurrentSourceDirectory() << "\n" - << "does not contain a CMakeLists.txt file."; - switch (mf->GetPolicyStatus(cmPolicies::CMP0014)) - { - case cmPolicies::WARN: - // Print the warning. - e << "\n" - << "CMake does not support this case but it used " - << "to work accidentally and is being allowed for " - << "compatibility." - << "\n" - << mf->GetPolicies()->GetPolicyWarning(cmPolicies::CMP0014); - mf->IssueMessage(cmake::AUTHOR_WARNING, e.str()); - case cmPolicies::OLD: - // OLD behavior does not warn. - return; - case cmPolicies::REQUIRED_IF_USED: - case cmPolicies::REQUIRED_ALWAYS: - e << "\n" - << mf->GetPolicies()->GetRequiredPolicyError(cmPolicies::CMP0014); - case cmPolicies::NEW: - // NEW behavior prints the error. - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); - break; - } -} - -void cmLocalGenerator::SetupPathConversions() -{ - // Setup the current output directory components for use by - // Convert - std::string outdir; - outdir = - cmSystemTools::CollapseFullPath(this->Makefile->GetHomeDirectory()); - cmSystemTools::SplitPath(outdir, this->HomeDirectoryComponents); - outdir = - cmSystemTools::CollapseFullPath( - this->Makefile->GetCurrentSourceDirectory()); - cmSystemTools::SplitPath(outdir, this->StartDirectoryComponents); - - outdir = cmSystemTools::CollapseFullPath - (this->Makefile->GetHomeOutputDirectory()); - cmSystemTools::SplitPath(outdir, - this->HomeOutputDirectoryComponents); - - outdir = cmSystemTools::CollapseFullPath - (this->Makefile->GetCurrentBinaryDirectory()); - cmSystemTools::SplitPath(outdir, - this->StartOutputDirectoryComponents); -} - - -void cmLocalGenerator::SetGlobalGenerator(cmGlobalGenerator *gg) -{ - this->GlobalGenerator = gg; - this->Makefile = new cmMakefile(this); -} - void cmLocalGenerator::ConfigureFinalPass() { this->Makefile->ConfigureFinalPass(); @@ -300,7 +230,7 @@ void cmLocalGenerator::GenerateTestFiles() const std::string& config = this->Makefile->GetConfigurations(configurationTypes, false); - std::string file = this->Makefile->GetCurrentBinaryDirectory(); + std::string file = this->StateSnapshot.GetCurrentBinaryDirectory(); file += "/"; file += "CTestTestfile.cmake"; @@ -309,9 +239,9 @@ void cmLocalGenerator::GenerateTestFiles() fout << "# CMake generated Testfile for " << std::endl << "# Source directory: " - << this->Makefile->GetCurrentSourceDirectory() << std::endl + << this->StateSnapshot.GetCurrentSourceDirectory() << std::endl << "# Build directory: " - << this->Makefile->GetCurrentBinaryDirectory() << std::endl + << this->StateSnapshot.GetCurrentBinaryDirectory() << std::endl << "# " << std::endl << "# This file includes the relevant testing commands " << "required for " << std::endl @@ -425,14 +355,10 @@ void cmLocalGenerator::GenerateInstallRules() } // Create the install script file. - std::string file = this->Makefile->GetCurrentBinaryDirectory(); - std::string homedir = this->Makefile->GetHomeOutputDirectory(); - std::string currdir = this->Makefile->GetCurrentBinaryDirectory(); - cmSystemTools::ConvertToUnixSlashes(file); - cmSystemTools::ConvertToUnixSlashes(homedir); - cmSystemTools::ConvertToUnixSlashes(currdir); + std::string file = this->StateSnapshot.GetCurrentBinaryDirectory(); + std::string homedir = this->GetState()->GetBinaryDirectory(); int toplevel_install = 0; - if ( currdir == homedir ) + if (file == homedir) { toplevel_install = 1; } @@ -442,7 +368,7 @@ void cmLocalGenerator::GenerateInstallRules() // Write the header. fout << "# Install script for directory: " - << this->Makefile->GetCurrentSourceDirectory() + << this->StateSnapshot.GetCurrentSourceDirectory() << std::endl << std::endl; fout << "# Set the install prefix" << std::endl << "if(NOT DEFINED CMAKE_INSTALL_PREFIX)" << std::endl @@ -577,6 +503,16 @@ void cmLocalGenerator::GenerateTargetManifest() } } +cmState* cmLocalGenerator::GetState() const +{ + return this->GlobalGenerator->GetCMakeInstance()->GetState(); +} + +cmState::Snapshot cmLocalGenerator::GetStateSnapshot() const +{ + return this->StateSnapshot; +} + void cmLocalGenerator::AddCustomCommandToCreateObject(const char* ofname, const std::string& lang, cmSourceFile& source, @@ -651,7 +587,7 @@ void cmLocalGenerator::AddCustomCommandToCreateObject(const char* ofname, source.GetFullPath(), commandLines, comment.c_str(), - this->Makefile->GetCurrentBinaryDirectory() + this->StateSnapshot.GetCurrentBinaryDirectory() ); } @@ -673,12 +609,12 @@ void cmLocalGenerator::AddBuildTargetRule(const std::string& llang, !sf->GetPropertyAsBool("EXTERNAL_OBJECT")) { std::string dir_max; - dir_max += this->Makefile->GetCurrentBinaryDirectory(); + dir_max += this->StateSnapshot.GetCurrentBinaryDirectory(); dir_max += "/"; std::string obj = this->GetObjectFileNameWithoutTarget(*sf, dir_max); if(!obj.empty()) { - std::string ofname = this->Makefile->GetCurrentBinaryDirectory(); + std::string ofname = this->StateSnapshot.GetCurrentBinaryDirectory(); ofname += "/"; ofname += obj; objVector.push_back(ofname); @@ -748,7 +684,7 @@ void cmLocalGenerator::AddBuildTargetRule(const std::string& llang, "", commandLines, comment.c_str(), - this->Makefile->GetCurrentBinaryDirectory() + this->StateSnapshot.GetCurrentBinaryDirectory() ); this->Makefile->GetSource(targetFullPath); target.Target->AddSource(targetFullPath); @@ -1058,12 +994,10 @@ cmLocalGenerator::ExpandRuleVariable(std::string const& variable, } if(variable == "CMAKE_COMMAND") { - const char* cmcommand = - this->GetMakefile()->GetDefinition("CMAKE_COMMAND"); - return this->Convert(cmcommand, FULL, SHELL); + return this->Convert(cmSystemTools::GetCMakeCommand(), FULL, SHELL); } - std::vector<std::string> enabledLanguages; - this->GlobalGenerator->GetEnabledLanguages(enabledLanguages); + std::vector<std::string> enabledLanguages = + this->GetState()->GetEnabledLanguages(); // loop over language specific replace variables int pos = 0; while(ruleReplaceVars[pos]) @@ -1242,7 +1176,7 @@ cmLocalGenerator::ConvertToOutputForExistingCommon(const std::string& remote, // If this is a windows shell, the result has a space, and the path // already exists, we can use a short-path to reference it without a // space. - if(this->WindowsShell && result.find(' ') != result.npos && + if(this->GetState()->UseWindowsShell() && result.find(' ') != result.npos && cmSystemTools::FileExists(remote.c_str())) { std::string tmp; @@ -1552,19 +1486,19 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs, if(includeBinaryDir) { if(emitted.find( - this->Makefile->GetCurrentBinaryDirectory()) == emitted.end()) + this->StateSnapshot.GetCurrentBinaryDirectory()) == emitted.end()) { - dirs.push_back(this->Makefile->GetCurrentBinaryDirectory()); - emitted.insert(this->Makefile->GetCurrentBinaryDirectory()); + dirs.push_back(this->StateSnapshot.GetCurrentBinaryDirectory()); + emitted.insert(this->StateSnapshot.GetCurrentBinaryDirectory()); } } if(includeSourceDir) { if(emitted.find( - this->Makefile->GetCurrentSourceDirectory()) == emitted.end()) + this->StateSnapshot.GetCurrentSourceDirectory()) == emitted.end()) { - dirs.push_back(this->Makefile->GetCurrentSourceDirectory()); - emitted.insert(this->Makefile->GetCurrentSourceDirectory()); + dirs.push_back(this->StateSnapshot.GetCurrentSourceDirectory()); + emitted.insert(this->StateSnapshot.GetCurrentSourceDirectory()); } } @@ -1606,8 +1540,8 @@ void cmLocalGenerator::GetIncludeDirectories(std::vector<std::string>& dirs, // it is requested by the project. if(this->Makefile->IsOn("CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE")) { - const char* topSourceDir = this->Makefile->GetHomeDirectory(); - const char* topBinaryDir = this->Makefile->GetHomeOutputDirectory(); + const char* topSourceDir = this->GetState()->GetSourceDirectory(); + const char* topBinaryDir = this->GetState()->GetBinaryDirectory(); for(std::vector<std::string>::const_iterator i = includes.begin(); i != includes.end(); ++i) { @@ -1905,7 +1839,7 @@ void cmLocalGenerator::OutputLinkLibraries(std::string& linkLibraries, fdi != fwDirs.end(); ++fdi) { frameworkPath += fwSearchFlag; - frameworkPath += this->Convert(*fdi, NONE, shellFormat, false); + frameworkPath += this->Convert(*fdi, NONE, shellFormat); frameworkPath += " "; } } @@ -1959,7 +1893,7 @@ void cmLocalGenerator::OutputLinkLibraries(std::string& linkLibraries, ri != runtimeDirs.end(); ++ri) { rpath += cli.GetRuntimeFlag(); - rpath += this->Convert(*ri, NONE, shellFormat, false); + rpath += this->Convert(*ri, NONE, shellFormat); rpath += " "; } fout << rpath; @@ -2165,7 +2099,7 @@ bool cmLocalGenerator::GetRealDependency(const std::string& inName, // Treat the name as relative to the source directory in which it // was given. - dep = this->Makefile->GetCurrentSourceDirectory(); + dep = this->StateSnapshot.GetCurrentSourceDirectory(); dep += "/"; dep += inName; return true; @@ -2315,7 +2249,8 @@ AddCompilerRequirementFlag(std::string &flags, cmTarget const* target, static void AddVisibilityCompileOption(std::string &flags, cmTarget const* target, cmLocalGenerator *lg, - const std::string& lang) + const std::string& lang, + std::string* warnCMP0063) { std::string l(lang); std::string compileOption = "CMAKE_" + l + "_COMPILE_OPTIONS_VISIBILITY"; @@ -2331,6 +2266,11 @@ static void AddVisibilityCompileOption(std::string &flags, { return; } + if (warnCMP0063) + { + *warnCMP0063 += " " + flagDefine + "\n"; + return; + } if (strcmp(prop, "hidden") != 0 && strcmp(prop, "default") != 0 && strcmp(prop, "protected") != 0 @@ -2348,7 +2288,8 @@ static void AddVisibilityCompileOption(std::string &flags, static void AddInlineVisibilityCompileOption(std::string &flags, cmTarget const* target, - cmLocalGenerator *lg) + cmLocalGenerator *lg, + std::string* warnCMP0063) { std::string compileOption = "CMAKE_CXX_COMPILE_OPTIONS_VISIBILITY_INLINES_HIDDEN"; @@ -2363,6 +2304,11 @@ static void AddInlineVisibilityCompileOption(std::string &flags, { return; } + if (warnCMP0063) + { + *warnCMP0063 += " VISIBILITY_INLINES_HIDDEN\n"; + return; + } lg->AppendFlags(flags, opt); } @@ -2371,25 +2317,49 @@ void cmLocalGenerator ::AddVisibilityPresetFlags(std::string &flags, cmTarget const* target, const std::string& lang) { - int targetType = target->GetType(); - bool suitableTarget = ((targetType == cmTarget::SHARED_LIBRARY) - || (targetType == cmTarget::MODULE_LIBRARY) - || (target->IsExecutableWithExports())); - - if (!suitableTarget) + if (lang.empty()) { return; } - if (lang.empty()) + std::string warnCMP0063; + std::string *pWarnCMP0063 = 0; + if (target->GetType() != cmTarget::SHARED_LIBRARY && + target->GetType() != cmTarget::MODULE_LIBRARY && + !target->IsExecutableWithExports()) { - return; + switch (target->GetPolicyStatusCMP0063()) + { + case cmPolicies::OLD: + return; + case cmPolicies::WARN: + pWarnCMP0063 = &warnCMP0063; + break; + default: + break; + } } - AddVisibilityCompileOption(flags, target, this, lang); + + AddVisibilityCompileOption(flags, target, this, lang, pWarnCMP0063); if(lang == "CXX") { - AddInlineVisibilityCompileOption(flags, target, this); + AddInlineVisibilityCompileOption(flags, target, this, pWarnCMP0063); + } + + if (!warnCMP0063.empty() && + this->WarnCMP0063.insert(target).second) + { + std::ostringstream w; + w << + cmPolicies::GetPolicyWarning(cmPolicies::CMP0063) << "\n" + "Target \"" << target->GetName() << "\" of " + "type \"" << cmTarget::GetTargetTypeName(target->GetType()) << "\" " + "has the following visibility properties set for " << lang << ":\n" << + warnCMP0063 << + "For compatibility CMake is not honoring them for this target."; + target->GetMakefile()->GetCMakeInstance() + ->IssueMessage(cmake::AUTHOR_WARNING, w.str(), target->GetBacktrace()); } } @@ -2458,8 +2428,7 @@ bool cmLocalGenerator::GetShouldUseOldFlags(bool shared, "shared libraries and will use the " << flagsVar << " variable " "instead. This may cause errors if the original content of " << flagsVar << " was removed.\n" - << this->Makefile->GetPolicies()->GetPolicyWarning( - cmPolicies::CMP0018); + << cmPolicies::GetPolicyWarning(cmPolicies::CMP0018); this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str()); // fall through to OLD behaviour @@ -2615,7 +2584,7 @@ void cmLocalGenerator::JoinDefines(const std::set<std::string>& defines, { // Append the definition with proper escaping. std::string def = dflag; - if(this->WatcomWMake) + if(this->GetState()->UseWatcomWMake()) { // The Watcom compiler does its own command line parsing instead // of using the windows shell rules. Definitions are one of @@ -2718,10 +2687,10 @@ const char* cmLocalGenerator::GetRelativeRootPath(RelativeRoot relroot) { switch (relroot) { - case HOME: return this->Makefile->GetHomeDirectory(); - case START: return this->Makefile->GetCurrentSourceDirectory(); - case HOME_OUTPUT: return this->Makefile->GetHomeOutputDirectory(); - case START_OUTPUT: return this->Makefile->GetCurrentBinaryDirectory(); + case HOME: return this->GetState()->GetSourceDirectory(); + case START: return this->StateSnapshot.GetCurrentSourceDirectory(); + case HOME_OUTPUT: return this->GetState()->GetBinaryDirectory(); + case START_OUTPUT: return this->StateSnapshot.GetCurrentBinaryDirectory(); default: break; } return 0; @@ -2733,13 +2702,6 @@ std::string cmLocalGenerator::Convert(const std::string& source, OutputFormat output, bool optional) { - // Make sure the relative path conversion components are set. - if(!this->PathConversionsSetup) - { - this->SetupPathConversions(); - this->PathConversionsSetup = true; - } - // Convert the path to a relative path. std::string result = source; @@ -2749,25 +2711,23 @@ std::string cmLocalGenerator::Convert(const std::string& source, { case HOME: //result = cmSystemTools::CollapseFullPath(result.c_str()); - result = this->ConvertToRelativePath(this->HomeDirectoryComponents, - result); + result = this->ConvertToRelativePath( + this->GetState()->GetSourceDirectoryComponents(), result); break; case START: //result = cmSystemTools::CollapseFullPath(result.c_str()); - result = this->ConvertToRelativePath(this->StartDirectoryComponents, - result); + result = this->ConvertToRelativePath( + this->StateSnapshot.GetCurrentSourceDirectoryComponents(), result); break; case HOME_OUTPUT: //result = cmSystemTools::CollapseFullPath(result.c_str()); - result = - this->ConvertToRelativePath(this->HomeOutputDirectoryComponents, - result); + result = this->ConvertToRelativePath( + this->GetState()->GetBinaryDirectoryComponents(), result); break; case START_OUTPUT: //result = cmSystemTools::CollapseFullPath(result.c_str()); - result = - this->ConvertToRelativePath(this->StartOutputDirectoryComponents, - result); + result = this->ConvertToRelativePath( + this->StateSnapshot.GetCurrentBinaryDirectoryComponents(), result); break; case FULL: result = cmSystemTools::CollapseFullPath(result); @@ -2794,7 +2754,7 @@ std::string cmLocalGenerator::ConvertToOutputFormat(const std::string& source, // For the MSYS shell convert drive letters to posix paths, so // that c:/some/path becomes /c/some/path. This is needed to // avoid problems with the shell path translation. - if(this->MSYSShell && !this->LinkScriptShell) + if(this->GetState()->UseMSYSShell() && !this->LinkScriptShell) { if(result.size() > 2 && result[1] == ':') { @@ -2802,7 +2762,7 @@ std::string cmLocalGenerator::ConvertToOutputFormat(const std::string& source, result[0] = '/'; } } - if(this->WindowsShell) + if(this->GetState()->UseWindowsShell()) { std::replace(result.begin(), result.end(), '/', '\\'); } @@ -2840,69 +2800,6 @@ std::string cmLocalGenerator::Convert(RelativeRoot remote, } //---------------------------------------------------------------------------- -std::string cmLocalGenerator::FindRelativePathTopSource() -{ - // Relative path conversion within a single tree managed by CMake is - // safe. We can use our parent relative path top if and only if - // this is a subdirectory of that top. - if(cmLocalGenerator* parent = this->GetParent()) - { - std::string parentTop = parent->FindRelativePathTopSource(); - if(cmSystemTools::IsSubDirectory( - this->Makefile->GetCurrentSourceDirectory(), parentTop)) - { - return parentTop; - } - } - - // Otherwise this directory itself is the new top. - return this->Makefile->GetCurrentSourceDirectory(); -} - -//---------------------------------------------------------------------------- -std::string cmLocalGenerator::FindRelativePathTopBinary() -{ - // Relative path conversion within a single tree managed by CMake is - // safe. We can use our parent relative path top if and only if - // this is a subdirectory of that top. - if(cmLocalGenerator* parent = this->GetParent()) - { - std::string parentTop = parent->FindRelativePathTopBinary(); - if(cmSystemTools::IsSubDirectory( - this->Makefile->GetCurrentBinaryDirectory(), parentTop)) - { - return parentTop; - } - } - - // Otherwise this directory itself is the new top. - return this->Makefile->GetCurrentBinaryDirectory(); -} - -//---------------------------------------------------------------------------- -void cmLocalGenerator::ConfigureRelativePaths() -{ - // Relative path conversion inside the source tree is not used to - // construct relative paths passed to build tools so it is safe to - // even when the source is a network path. - std::string source = this->FindRelativePathTopSource(); - this->RelativePathTopSource = source; - - // The current working directory on Windows cannot be a network - // path. Therefore relative paths cannot work when the binary tree - // is a network path. - std::string binary = this->FindRelativePathTopBinary(); - if(binary.size() < 2 || binary.substr(0, 2) != "//") - { - this->RelativePathTopBinary = binary; - } - else - { - this->RelativePathTopBinary = ""; - } -} - -//---------------------------------------------------------------------------- static bool cmLocalGeneratorNotAbove(const char* a, const char* b) { return (cmSystemTools::ComparePath(a, b) || @@ -2927,26 +2824,19 @@ cmLocalGenerator::ConvertToRelativePath(const std::vector<std::string>& local, return in_remote; } - // Make sure relative path conversion is configured. - if(!this->RelativePathsConfigured) - { - this->ConfigureRelativePaths(); - this->RelativePathsConfigured = true; - } - if(!force) { // Skip conversion if the path and local are not both in the source // or both in the binary tree. std::string local_path = cmSystemTools::JoinPath(local); if(!((cmLocalGeneratorNotAbove(local_path.c_str(), - this->RelativePathTopBinary.c_str()) && + this->StateSnapshot.GetRelativePathTopBinary()) && cmLocalGeneratorNotAbove(in_remote.c_str(), - this->RelativePathTopBinary.c_str())) || + this->StateSnapshot.GetRelativePathTopBinary())) || (cmLocalGeneratorNotAbove(local_path.c_str(), - this->RelativePathTopSource.c_str()) && + this->StateSnapshot.GetRelativePathTopSource()) && cmLocalGeneratorNotAbove(in_remote.c_str(), - this->RelativePathTopSource.c_str())))) + this->StateSnapshot.GetRelativePathTopSource())))) { return in_remote; } @@ -3285,6 +3175,31 @@ void cmLocalGenerator::ComputeObjectFilenames( } +bool cmLocalGenerator::IsWindowsShell() const +{ + return this->GetState()->UseWindowsShell(); +} + +bool cmLocalGenerator::IsWatcomWMake() const +{ + return this->GetState()->UseWatcomWMake(); +} + +bool cmLocalGenerator::IsMinGWMake() const +{ + return this->GetState()->UseMinGWMake(); +} + +bool cmLocalGenerator::IsNMake() const +{ + return this->GetState()->UseNMake(); +} + +void cmLocalGenerator::SetConfiguredCMP0014(bool configured) +{ + this->Configured = configured; +} + //---------------------------------------------------------------------------- std::string cmLocalGenerator @@ -3393,35 +3308,6 @@ cmLocalGenerator } //---------------------------------------------------------------------------- -std::string cmLocalGenerator::EscapeForShellOldStyle(const std::string& str) -{ - std::string result; -#if defined(_WIN32) && !defined(__CYGWIN__) - // if there are spaces - std::string temp = str; - if (temp.find(" ") != std::string::npos && - temp.find("\"")==std::string::npos) - { - result = "\""; - result += str; - result += "\""; - return result; - } - return str; -#else - for(const char* ch = str.c_str(); *ch != '\0'; ++ch) - { - if(*ch == ' ') - { - result += '\\'; - } - result += *ch; - } - return result; -#endif -} - -//---------------------------------------------------------------------------- static bool cmLocalGeneratorIsShellOperator(const std::string& str) { static std::set<std::string> shellOperators; @@ -3457,7 +3343,7 @@ std::string cmLocalGenerator::EscapeForShell(const std::string& str, // Compute the flags for the target shell environment. int flags = 0; - if(this->WindowsVSIDE) + if(this->GetState()->UseWindowsVSIDE()) { flags |= cmsysSystem_Shell_Flag_VSIDE; } @@ -3477,27 +3363,27 @@ std::string cmLocalGenerator::EscapeForShell(const std::string& str, { flags |= cmsysSystem_Shell_Flag_WatcomQuote; } - if(this->WatcomWMake) + if(this->GetState()->UseWatcomWMake()) { flags |= cmsysSystem_Shell_Flag_WatcomWMake; } - if(this->MinGWMake) + if(this->GetState()->UseMinGWMake()) { flags |= cmsysSystem_Shell_Flag_MinGWMake; } - if(this->NMake) + if(this->GetState()->UseNMake()) { flags |= cmsysSystem_Shell_Flag_NMake; } // Compute the buffer size needed. - int size = (this->WindowsShell ? + int size = (this->GetState()->UseWindowsShell() ? cmsysSystem_Shell_GetArgumentSizeForWindows(str.c_str(), flags) : cmsysSystem_Shell_GetArgumentSizeForUnix(str.c_str(), flags)); // Compute the shell argument itself. std::vector<char> arg(size); - if(this->WindowsShell) + if(this->GetState()->UseWindowsShell()) { cmsysSystem_Shell_GetArgumentForWindows(str.c_str(), &arg[0], flags); } diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index befddbf..32b17f5 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -13,6 +13,7 @@ #define cmLocalGenerator_h #include "cmStandardIncludes.h" +#include "cmState.h" class cmMakefile; class cmGlobalGenerator; @@ -33,9 +34,13 @@ class cmCustomCommandGenerator; class cmLocalGenerator { public: - cmLocalGenerator(cmLocalGenerator* parent); + cmLocalGenerator(cmGlobalGenerator* gg, cmLocalGenerator* parent, + cmState::Snapshot snapshot); virtual ~cmLocalGenerator(); + /// @return whether we are processing the top CMakeLists.txt file. + bool IsRootMakefile() const; + /** * Generate the makefile for this directory. */ @@ -88,8 +93,8 @@ public: const cmGlobalGenerator *GetGlobalGenerator() const { return this->GlobalGenerator; } - ///! Set the Global Generator, done on creation by the GlobalGenerator - void SetGlobalGenerator(cmGlobalGenerator *gg); + cmState* GetState() const; + cmState::Snapshot GetStateSnapshot() const; /** * Convert something to something else. This is a centralized conversion @@ -298,9 +303,6 @@ public: bool forEcho = false, bool useWatcomQuote = false); - /** Backwards-compatibility version of EscapeForShell. */ - std::string EscapeForShellOldStyle(const std::string& str); - /** Escape the given string as an argument in a CMake script. */ static std::string EscapeForCMake(const std::string& str); @@ -385,9 +387,16 @@ public: std::map<cmSourceFile const*, std::string>& mapping, cmGeneratorTarget const* gt = 0); + bool IsWindowsShell() const; + bool IsWatcomWMake() const; + bool IsMinGWMake() const; + bool IsNMake() const; + + void SetConfiguredCMP0014(bool configured); + protected: ///! put all the libraries for a target on into the given stream - virtual void OutputLinkLibraries(std::string& linkLibraries, + void OutputLinkLibraries(std::string& linkLibraries, std::string& frameworkPath, std::string& linkPath, cmGeneratorTarget &, @@ -432,11 +441,6 @@ protected: std::string const& dir_max); void ComputeObjectMaxPath(); - void ConfigureRelativePaths(); - std::string FindRelativePathTopSource(); - std::string FindRelativePathTopBinary(); - void SetupPathConversions(); - virtual std::string ConvertToLinkReference(std::string const& lib, OutputFormat format = SHELL); @@ -444,49 +448,26 @@ protected: definition. Issues a warning. */ virtual bool CheckDefinition(std::string const& define) const; - /** Read the input CMakeLists.txt file. */ - void ReadInputFile(); - cmMakefile *Makefile; + cmState::Snapshot StateSnapshot; cmGlobalGenerator *GlobalGenerator; - // members used for relative path function ConvertToMakefilePath - std::string RelativePathToSourceDir; - std::string RelativePathToBinaryDir; - std::vector<std::string> HomeDirectoryComponents; - std::vector<std::string> StartDirectoryComponents; - std::vector<std::string> HomeOutputDirectoryComponents; - std::vector<std::string> StartOutputDirectoryComponents; cmLocalGenerator* Parent; std::vector<cmLocalGenerator*> Children; std::map<std::string, std::string> UniqueObjectNamesMap; std::string::size_type ObjectPathMax; std::set<std::string> ObjectMaxPathViolations; - bool WindowsShell; - bool WindowsVSIDE; - bool WatcomWMake; - bool MinGWMake; - bool NMake; - bool ForceUnixPath; - bool MSYSShell; + + std::set<cmTarget const*> WarnCMP0063; + bool LinkScriptShell; bool UseRelativePaths; - bool IgnoreLibPrefix; bool Configured; bool EmitUniversalBinaryFlags; + // Hack for ExpandRuleVariable until object-oriented version is // committed. std::string TargetImplib; - // The top-most directories for relative path conversion. Both the - // source and destination location of a relative path conversion - // must be underneath one of these directories (both under source or - // both under binary) in order for the relative path to be evaluated - // safely by the build tools. - std::string RelativePathTopSource; - std::string RelativePathTopBinary; - bool RelativePathsConfigured; - bool PathConversionsSetup; - cmIML_INT_uint64_t BackwardsCompatibility; bool BackwardsCompatibilityFinal; private: diff --git a/Source/cmLocalGhsMultiGenerator.cxx b/Source/cmLocalGhsMultiGenerator.cxx index fa2a1a5..870b9b9 100644 --- a/Source/cmLocalGhsMultiGenerator.cxx +++ b/Source/cmLocalGhsMultiGenerator.cxx @@ -16,8 +16,10 @@ #include "cmGhsMultiTargetGenerator.h" #include "cmGeneratedFileStream.h" -cmLocalGhsMultiGenerator::cmLocalGhsMultiGenerator(cmLocalGenerator* parent) - : cmLocalGenerator(parent) +cmLocalGhsMultiGenerator::cmLocalGhsMultiGenerator(cmGlobalGenerator* gg, + cmLocalGenerator* parent, + cmState::Snapshot snapshot) + : cmLocalGenerator(gg, parent, snapshot) { } @@ -26,31 +28,16 @@ cmLocalGhsMultiGenerator::~cmLocalGhsMultiGenerator() {} void cmLocalGhsMultiGenerator::Generate() { cmGeneratorTargetsType tgts = this->GetMakefile()->GetGeneratorTargets(); - if (!tgts.empty()) + + for (cmGeneratorTargetsType::iterator l = tgts.begin(); l != tgts.end(); + ++l) { - for (cmGeneratorTargetsType::iterator l = tgts.begin(); l != tgts.end(); - ++l) + if (l->second->Target->GetType() == cmTarget::INTERFACE_LIBRARY + || l->second->Target->IsImported()) { - cmGhsMultiTargetGenerator tg(l->second->Target); - tg.Generate(); + continue; } + cmGhsMultiTargetGenerator tg(l->second->Target); + tg.Generate(); } } - -// Implemented in: -// cmLocalGenerator. -// Used in: -// Source/cmMakefile.cxx -// Source/cmGlobalGenerator.cxx -void cmLocalGhsMultiGenerator::Configure() -{ - // Compute the path to use when referencing the current output - // directory from the top output directory. - this->HomeRelativeOutputPath = - this->Convert(this->Makefile->GetCurrentBinaryDirectory(), HOME_OUTPUT); - if (this->HomeRelativeOutputPath == ".") - { - this->HomeRelativeOutputPath = ""; - } - this->cmLocalGenerator::Configure(); -} diff --git a/Source/cmLocalGhsMultiGenerator.h b/Source/cmLocalGhsMultiGenerator.h index 7afef56..f52ef39 100644 --- a/Source/cmLocalGhsMultiGenerator.h +++ b/Source/cmLocalGhsMultiGenerator.h @@ -25,32 +25,15 @@ class cmGeneratedFileStream; class cmLocalGhsMultiGenerator : public cmLocalGenerator { public: - cmLocalGhsMultiGenerator(cmLocalGenerator* parent); + cmLocalGhsMultiGenerator(cmGlobalGenerator* gg, cmLocalGenerator* parent, + cmState::Snapshot snapshot); virtual ~cmLocalGhsMultiGenerator(); - /// @returns the relative path between the HomeOutputDirectory and this - /// local generators StartOutputDirectory. - std::string GetHomeRelativeOutputPath() const - { - return this->HomeRelativeOutputPath; - } - /** * Generate the makefile for this directory. */ virtual void Generate(); - - /// Overloaded methods. @see cmLocalGenerator::Configure() - virtual void Configure(); - const char *GetBuildFileName() { return this->BuildFileName.c_str(); } - -protected: - virtual bool CustomCommandUseLocal() const { return true; } - -private: - std::string BuildFileName; - std::string HomeRelativeOutputPath; }; #endif diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index 4e817a0..c08c91f 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -22,14 +22,13 @@ #include <assert.h> -cmLocalNinjaGenerator::cmLocalNinjaGenerator(cmLocalGenerator* parent) - : cmLocalGenerator(parent) +cmLocalNinjaGenerator::cmLocalNinjaGenerator(cmGlobalGenerator* gg, + cmLocalGenerator* parent, + cmState::Snapshot snapshot) + : cmLocalGenerator(gg, parent, snapshot) , ConfigName("") , HomeRelativeOutputPath("") { -#ifdef _WIN32 - this->WindowsShell = true; -#endif this->TargetImplib = "$TARGET_IMPLIB"; } @@ -50,7 +49,7 @@ void cmLocalNinjaGenerator::Generate() #endif // We do that only once for the top CMakeLists.txt file. - if(this->isRootMakefile()) + if(this->IsRootMakefile()) { this->WriteBuildFileTop(); @@ -181,11 +180,6 @@ cmake* cmLocalNinjaGenerator::GetCMakeInstance() return this->GetGlobalGenerator()->GetCMakeInstance(); } -bool cmLocalNinjaGenerator::isRootMakefile() const -{ - return !this->GetParent(); -} - void cmLocalNinjaGenerator::WriteBuildFileTop() { // For the build file. @@ -312,9 +306,9 @@ void cmLocalNinjaGenerator::WriteProcessedMakefile(std::ostream& os) cmGlobalNinjaGenerator::WriteDivider(os); os << "# Write statements declared in CMakeLists.txt:" << std::endl - << "# " << this->Makefile->GetCurrentListFile() << std::endl - ; - if(this->isRootMakefile()) + << "# " + << this->Makefile->GetDefinition("CMAKE_CURRENT_LIST_FILE") << std::endl; + if(this->IsRootMakefile()) os << "# Which is the root file." << std::endl; cmGlobalNinjaGenerator::WriteDivider(os); os << std::endl; diff --git a/Source/cmLocalNinjaGenerator.h b/Source/cmLocalNinjaGenerator.h index d72677b..7ae97de 100644 --- a/Source/cmLocalNinjaGenerator.h +++ b/Source/cmLocalNinjaGenerator.h @@ -31,37 +31,26 @@ class cmake; class cmLocalNinjaGenerator : public cmLocalGenerator { public: - /// Default constructor. - cmLocalNinjaGenerator(cmLocalGenerator* parent); + cmLocalNinjaGenerator(cmGlobalGenerator* gg, cmLocalGenerator* parent, + cmState::Snapshot snapshot); - /// Destructor. virtual ~cmLocalNinjaGenerator(); - /// Overloaded methods. @see cmLocalGenerator::Generate() virtual void Generate(); - /// Overloaded methods. @see cmLocalGenerator::Configure() virtual void Configure(); - /// Overloaded methods. @see cmLocalGenerator::GetTargetDirectory() virtual std::string GetTargetDirectory(cmTarget const& target) const; const cmGlobalNinjaGenerator* GetGlobalNinjaGenerator() const; cmGlobalNinjaGenerator* GetGlobalNinjaGenerator(); - /** - * Shortcut to get the cmake instance throw the global generator. - * @return an instance of the cmake object. - */ const cmake* GetCMakeInstance() const; cmake* GetCMakeInstance(); std::string const& GetConfigName() const { return this->ConfigName; } - /// @return whether we are processing the top CMakeLists.txt file. - bool isRootMakefile() const; - /// @returns the relative path between the HomeOutputDirectory and this /// local generators StartOutputDirectory. std::string GetHomeRelativeOutputPath() const diff --git a/Source/cmLocalUnixMakefileGenerator3.cxx b/Source/cmLocalUnixMakefileGenerator3.cxx index bf6fb61..3eea59b 100644 --- a/Source/cmLocalUnixMakefileGenerator3.cxx +++ b/Source/cmLocalUnixMakefileGenerator3.cxx @@ -80,16 +80,11 @@ static std::string cmSplitExtension(std::string const& in, std::string& base) //---------------------------------------------------------------------------- cmLocalUnixMakefileGenerator3:: -cmLocalUnixMakefileGenerator3(cmLocalGenerator* parent) - : cmLocalGenerator(parent) +cmLocalUnixMakefileGenerator3(cmGlobalGenerator* gg, cmLocalGenerator* parent, + cmState::Snapshot snapshot) + : cmLocalGenerator(gg, parent, snapshot) { - this->WindowsShell = false; - this->IncludeDirective = "include"; this->MakefileVariableSize = 0; - this->IgnoreLibPrefix = false; - this->PassMakeflags = false; - this->DefineWindowsNULL = false; - this->UnixCD = true; this->ColorMakefile = false; this->SkipPreprocessedSourceRules = false; this->SkipAssemblySourceRules = false; @@ -546,9 +541,11 @@ void cmLocalUnixMakefileGenerator3::WriteDirectoryInformationFile() // Setup relative path conversion tops. infoFileStream << "# Relative path conversion top directories.\n" - << "set(CMAKE_RELATIVE_PATH_TOP_SOURCE \"" << this->RelativePathTopSource + << "set(CMAKE_RELATIVE_PATH_TOP_SOURCE \"" + << this->StateSnapshot.GetRelativePathTopSource() << "\")\n" - << "set(CMAKE_RELATIVE_PATH_TOP_BINARY \"" << this->RelativePathTopBinary + << "set(CMAKE_RELATIVE_PATH_TOP_BINARY \"" + << this->StateSnapshot.GetRelativePathTopBinary() << "\")\n" << "\n"; @@ -679,7 +676,7 @@ cmLocalUnixMakefileGenerator3 // Write the list of commands. os << cmWrap("\t", commands, "", "\n") << "\n"; - if(symbolic && !this->WatcomWMake) + if(symbolic && !this->IsWatcomWMake()) { os << ".PHONY : " << cmMakeSafe(tgt) << "\n"; } @@ -696,7 +693,7 @@ std::string cmLocalUnixMakefileGenerator3 ::ConvertShellCommand(std::string const& cmd, RelativeRoot root) { - if(this->WatcomWMake && + if(this->IsWatcomWMake() && cmSystemTools::FileIsFullPath(cmd.c_str()) && cmd.find_first_of("( )") != cmd.npos) { @@ -721,7 +718,9 @@ cmLocalUnixMakefileGenerator3 makefileStream << "# Set environment variables for the build.\n" << "\n"; - if(this->DefineWindowsNULL) + cmGlobalUnixMakefileGenerator3* gg = + static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator); + if(gg->DefineWindowsNULL) { makefileStream << "!IF \"$(OS)\" == \"Windows_NT\"\n" @@ -730,7 +729,7 @@ cmLocalUnixMakefileGenerator3 << "NULL=nul\n" << "!ENDIF\n"; } - if(this->WindowsShell) + if(this->IsWindowsShell()) { makefileStream << "SHELL = cmd.exe\n" @@ -746,18 +745,16 @@ cmLocalUnixMakefileGenerator3 #endif } - std::string cmakecommand = - this->Makefile->GetRequiredDefinition("CMAKE_COMMAND"); makefileStream << "# The CMake executable.\n" << "CMAKE_COMMAND = " - << this->ConvertShellCommand(cmakecommand, FULL) + << this->ConvertShellCommand(cmSystemTools::GetCMakeCommand(), FULL) << "\n" << "\n"; makefileStream << "# The command to remove a file.\n" << "RM = " - << this->ConvertShellCommand(cmakecommand, FULL) + << this->ConvertShellCommand(cmSystemTools::GetCMakeCommand(), FULL) << " -E remove -f\n" << "\n"; makefileStream @@ -798,7 +795,8 @@ cmLocalUnixMakefileGenerator3 makefileStream, "Disable implicit rules so canonical targets will work.", ".SUFFIXES", no_depends, no_commands, false); - if(!this->NMake && !this->WatcomWMake && !this->BorlandMakeCurlyHack) + if(!this->IsNMake() + && !this->IsWatcomWMake() && !this->BorlandMakeCurlyHack) { // turn off RCS and SCCS automatic stuff from gmake makefileStream @@ -810,7 +808,7 @@ cmLocalUnixMakefileGenerator3 depends.push_back(".hpux_make_needs_suffix_list"); this->WriteMakeRule(makefileStream, 0, ".SUFFIXES", depends, no_commands, false); - if(this->WatcomWMake) + if(this->IsWatcomWMake()) { // Switch on WMake feature, if an error or interrupt occurs during // makefile processing, the current target being made may be deleted @@ -828,7 +826,7 @@ cmLocalUnixMakefileGenerator3 << "VERBOSE = 1\n" << "\n"; } - if(this->WatcomWMake) + if(this->IsWatcomWMake()) { makefileStream << "!ifndef VERBOSE\n" @@ -962,7 +960,7 @@ cmLocalUnixMakefileGenerator3 void cmLocalUnixMakefileGenerator3::AppendFlags(std::string& flags, const std::string& newFlags) { - if(this->WatcomWMake && !newFlags.empty()) + if(this->IsWatcomWMake() && !newFlags.empty()) { std::string newf = newFlags; if(newf.find("\\\"") != newf.npos) @@ -1112,7 +1110,7 @@ cmLocalUnixMakefileGenerator3 // bool useCall = false; - if (this->WindowsShell) + if (this->IsWindowsShell()) { std::string suffix; if (cmd.size() > 4) @@ -1179,7 +1177,7 @@ cmLocalUnixMakefileGenerator3 { cmd = "call " + cmd; } - else if (this->NMake && cmd[0]=='"') + else if (this->IsNMake() && cmd[0]=='"') { cmd = "echo >nul && " + cmd; } @@ -1261,7 +1259,7 @@ cmLocalUnixMakefileGenerator3 f != files.end(); ++f) { std::string fc = this->Convert(*f,START_OUTPUT,UNCHANGED); - fout << " " << this->EscapeForCMake(fc) << "\n"; + fout << " " << cmLocalGenerator::EscapeForCMake(fc) << "\n"; } fout << ")\n"; } @@ -1613,16 +1611,15 @@ cmLocalUnixMakefileGenerator3 } // Setup relative path top directories. - this->RelativePathsConfigured = true; if(const char* relativePathTopSource = mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_SOURCE")) { - this->RelativePathTopSource = relativePathTopSource; + this->StateSnapshot.SetRelativePathTopSource(relativePathTopSource); } if(const char* relativePathTopBinary = mf->GetDefinition("CMAKE_RELATIVE_PATH_TOP_BINARY")) { - this->RelativePathTopBinary = relativePathTopBinary; + this->StateSnapshot.SetRelativePathTopBinary(relativePathTopBinary); } } else @@ -2060,7 +2057,7 @@ void cmLocalUnixMakefileGenerator3 di != defines.end(); ++di) { cmakefileStream - << " " << this->EscapeForCMake(*di) << "\n"; + << " " << cmLocalGenerator::EscapeForCMake(*di) << "\n"; } cmakefileStream << " )\n"; @@ -2113,7 +2110,8 @@ void cmLocalUnixMakefileGenerator3 for(std::vector<std::string>::const_iterator tri = transformRules.begin(); tri != transformRules.end(); ++tri) { - cmakefileStream << " " << this->EscapeForCMake(*tri) << "\n"; + cmakefileStream << " " + << cmLocalGenerator::EscapeForCMake(*tri) << "\n"; } cmakefileStream << " )\n"; @@ -2142,10 +2140,12 @@ cmLocalUnixMakefileGenerator3 cmd += this->Convert(makefile,NONE,SHELL); cmd += " "; + cmGlobalUnixMakefileGenerator3* gg = + static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator); // Pass down verbosity level. - if(!this->GetMakeSilentFlag().empty()) + if(!gg->MakeSilentFlag.empty()) { - cmd += this->GetMakeSilentFlag(); + cmd += gg->MakeSilentFlag; cmd += " "; } @@ -2153,7 +2153,7 @@ cmLocalUnixMakefileGenerator3 // sub-invoked makes via an environment variable. However, some // makes do not support that, so you have to pass the flags // explicitly. - if(this->GetPassMakeflags()) + if(gg->PassMakeflags) { cmd += "-$(MAKEFLAGS) "; } @@ -2343,9 +2343,11 @@ void cmLocalUnixMakefileGenerator3 // used by NMake and Borland make does not support "cd /d" so this // feature simply cannot work with them (Borland make does not even // support changing the drive letter with just "d:"). - const char* cd_cmd = this->MinGWMake? "cd /d " : "cd "; + const char* cd_cmd = this->IsMinGWMake() ? "cd /d " : "cd "; - if(!this->UnixCD) + cmGlobalUnixMakefileGenerator3* gg = + static_cast<cmGlobalUnixMakefileGenerator3*>(this->GlobalGenerator); + if(!gg->UnixCD) { // On Windows we must perform each step separately and then change // back because the shell keeps the working directory between diff --git a/Source/cmLocalUnixMakefileGenerator3.h b/Source/cmLocalUnixMakefileGenerator3.h index 9f83b86..988d660 100644 --- a/Source/cmLocalUnixMakefileGenerator3.h +++ b/Source/cmLocalUnixMakefileGenerator3.h @@ -34,7 +34,9 @@ class cmSourceFile; class cmLocalUnixMakefileGenerator3 : public cmLocalGenerator { public: - cmLocalUnixMakefileGenerator3(cmLocalGenerator* parent); + cmLocalUnixMakefileGenerator3(cmGlobalGenerator* gg, + cmLocalGenerator* parent, + cmState::Snapshot snapshot); virtual ~cmLocalUnixMakefileGenerator3(); /** @@ -66,81 +68,11 @@ public: void WriteMakeVariables(std::ostream& makefileStream); /** - * If true, then explicitly pass MAKEFLAGS on the make all target for makes - * that do not use environment variables. - * - */ - void SetPassMakeflags(bool s){this->PassMakeflags = s;} - bool GetPassMakeflags() { return this->PassMakeflags; } - - /** - * Set the flag used to keep the make program silent. - */ - void SetMakeSilentFlag(const std::string& s) { this->MakeSilentFlag = s; } - std::string &GetMakeSilentFlag() { return this->MakeSilentFlag; } - - /** - * Set to true if the shell being used is the windows shell. - * This controls if statements in the makefile and the SHELL variable. - * The default is false. - */ - void SetWindowsShell(bool v) {this->WindowsShell = v;} - - /** - * Set to true if the make tool being used is Watcom WMake. - */ - void SetWatcomWMake(bool v) {this->WatcomWMake = v;} - - /** - * Set to true if the make tool being used is MinGW Make. - */ - void SetMinGWMake(bool v) {this->MinGWMake = v;} - - /** - * Set to true if the make tool being used is NMake. - */ - void SetNMake(bool v) {this->NMake = v;} - - /** - * Set to true if the shell being used is the MSYS shell. - * This controls if statements in the makefile and the SHELL variable. - * The default is false. - */ - void SetMSYSShell(bool v) {this->MSYSShell = v;} - - /** - * If set to true, then NULL is set to nil for non Windows_NT. - * This uses make syntax used by nmake and borland. - * The default is false. - */ - void SetDefineWindowsNULL(bool v) {this->DefineWindowsNULL = v;} - - /** - * If set to true, cd dir && command is used to - * run commands in a different directory. - */ - void SetUnixCD(bool v) {this->UnixCD = v;} - - /** - * Set the string used to include one makefile into another default - * is include. - */ - void SetIncludeDirective(const std::string& s) - { this->IncludeDirective = s; } - const std::string& GetIncludeDirective() { return this->IncludeDirective; } - - /** * Set max makefile variable size, default is 0 which means unlimited. */ void SetMakefileVariableSize(int s) { this->MakefileVariableSize = s; } /** - * If ignore lib prefix is true, then do not strip lib from the name - * of a library. - */ - void SetIgnoreLibPrefix(bool s) { this->IgnoreLibPrefix = s; } - - /** * Set whether passing a make target on a command line requires an * extra level of escapes. */ @@ -331,12 +263,7 @@ private: //========================================================================== // Configuration settings. int MakefileVariableSize; - std::string IncludeDirective; - std::string MakeSilentFlag; std::string ConfigurationName; - bool DefineWindowsNULL; - bool UnixCD; - bool PassMakeflags; bool MakeCommandEscapeTargetTwice; bool BorlandMakeCurlyHack; //========================================================================== diff --git a/Source/cmLocalVisualStudio10Generator.cxx b/Source/cmLocalVisualStudio10Generator.cxx index 73a4ec8..ad6a020 100644 --- a/Source/cmLocalVisualStudio10Generator.cxx +++ b/Source/cmLocalVisualStudio10Generator.cxx @@ -62,8 +62,10 @@ class cmVS10XMLParser : public cmXMLParser //---------------------------------------------------------------------------- cmLocalVisualStudio10Generator -::cmLocalVisualStudio10Generator(VSVersion v, cmLocalGenerator* parent): - cmLocalVisualStudio7Generator(v, parent) +::cmLocalVisualStudio10Generator(cmGlobalGenerator* gg, + cmLocalGenerator* parent, + cmState::Snapshot snapshot): + cmLocalVisualStudio7Generator(gg, parent, snapshot) { } diff --git a/Source/cmLocalVisualStudio10Generator.h b/Source/cmLocalVisualStudio10Generator.h index f90daa0..c588aaf 100644 --- a/Source/cmLocalVisualStudio10Generator.h +++ b/Source/cmLocalVisualStudio10Generator.h @@ -25,7 +25,9 @@ class cmLocalVisualStudio10Generator : public cmLocalVisualStudio7Generator { public: ///! Set cache only and recurse to false by default. - cmLocalVisualStudio10Generator(VSVersion v, cmLocalGenerator* parent); + cmLocalVisualStudio10Generator(cmGlobalGenerator* gg, + cmLocalGenerator* parent, + cmState::Snapshot snapshot); virtual ~cmLocalVisualStudio10Generator(); diff --git a/Source/cmLocalVisualStudio6Generator.cxx b/Source/cmLocalVisualStudio6Generator.cxx index 6d89b15..ad34857 100644 --- a/Source/cmLocalVisualStudio6Generator.cxx +++ b/Source/cmLocalVisualStudio6Generator.cxx @@ -24,8 +24,10 @@ #include <cmsys/FStream.hxx> cmLocalVisualStudio6Generator -::cmLocalVisualStudio6Generator(cmLocalGenerator* parent): - cmLocalVisualStudioGenerator(VS6, parent) +::cmLocalVisualStudio6Generator(cmGlobalGenerator* gg, + cmLocalGenerator* parent, + cmState::Snapshot snapshot): + cmLocalVisualStudioGenerator(gg, parent, snapshot) { } @@ -220,10 +222,8 @@ void cmLocalVisualStudio6Generator::AddDSPBuildRule(cmTarget& tgt) { std::string dspname = GetVS6TargetName(tgt.GetName()); dspname += ".dsp.cmake"; - const char* dsprule = - this->Makefile->GetRequiredDefinition("CMAKE_COMMAND"); cmCustomCommandLine commandLine; - commandLine.push_back(dsprule); + commandLine.push_back(cmSystemTools::GetCMakeCommand()); std::string makefileIn = this->Makefile->GetCurrentSourceDirectory(); makefileIn += "/"; makefileIn += "CMakeLists.txt"; @@ -816,7 +816,7 @@ cmLocalVisualStudio6Generator::MaybeCreateOutputDir(cmTarget& target, // Add a pre-link event to create the directory. cmCustomCommandLine command; - command.push_back(this->Makefile->GetRequiredDefinition("CMAKE_COMMAND")); + command.push_back(cmSystemTools::GetCMakeCommand()); command.push_back("-E"); command.push_back("make_directory"); command.push_back(outDir); diff --git a/Source/cmLocalVisualStudio6Generator.h b/Source/cmLocalVisualStudio6Generator.h index 1a0a614..8f4d521 100644 --- a/Source/cmLocalVisualStudio6Generator.h +++ b/Source/cmLocalVisualStudio6Generator.h @@ -29,7 +29,9 @@ class cmLocalVisualStudio6Generator : public cmLocalVisualStudioGenerator { public: ///! Set cache only and recurse to false by default. - cmLocalVisualStudio6Generator(cmLocalGenerator* parent); + cmLocalVisualStudio6Generator(cmGlobalGenerator* gg, + cmLocalGenerator* parent, + cmState::Snapshot snapshot); virtual ~cmLocalVisualStudio6Generator(); diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index 2152f77..9c031cf 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -55,10 +55,11 @@ static void cmConvertToWindowsSlash(std::string& s) //---------------------------------------------------------------------------- cmLocalVisualStudio7Generator -::cmLocalVisualStudio7Generator(VSVersion v, cmLocalGenerator* parent): - cmLocalVisualStudioGenerator(v, parent) +::cmLocalVisualStudio7Generator(cmGlobalGenerator* gg, + cmLocalGenerator* parent, + cmState::Snapshot snapshot): + cmLocalVisualStudioGenerator(gg, parent, snapshot) { - this->ExtraFlagTable = 0; this->Internal = new cmLocalVisualStudio7GeneratorInternals(this); } @@ -240,18 +241,17 @@ void cmLocalVisualStudio7Generator::WriteStampFiles() void cmLocalVisualStudio7Generator ::CreateSingleVCProj(const std::string& lname, cmTarget &target) { - this->FortranProject = - static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator) - ->TargetIsFortranOnly(target); - this->WindowsCEProject = - static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator) - ->TargetsWindowsCE(); + cmGlobalVisualStudioGenerator* gg + = static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator); + this->FortranProject = gg->TargetIsFortranOnly(target); + this->WindowsCEProject = gg->TargetsWindowsCE(); // Intel Fortran for VS10 uses VS9 format ".vfproj" files. - VSVersion realVersion = this->Version; - if(this->FortranProject && this->Version >= VS10) + cmGlobalVisualStudioGenerator::VSVersion realVersion = gg->GetVersion(); + if(this->FortranProject + && gg->GetVersion() >= cmGlobalVisualStudioGenerator::VS10) { - this->Version = VS9; + gg->SetVersion(cmGlobalVisualStudioGenerator::VS9); } // add to the list of projects @@ -281,7 +281,7 @@ void cmLocalVisualStudio7Generator this->GlobalGenerator->FileReplacedDuringGenerate(fname); } - this->Version = realVersion; + gg->SetVersion(realVersion); } //---------------------------------------------------------------------------- @@ -291,10 +291,8 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule() stampName += "/"; stampName += cmake::GetCMakeFilesDirectoryPostSlash(); stampName += "generate.stamp"; - const char* dsprule = - this->Makefile->GetRequiredDefinition("CMAKE_COMMAND"); cmCustomCommandLine commandLine; - commandLine.push_back(dsprule); + commandLine.push_back(cmSystemTools::GetCMakeCommand()); std::string makefileIn = this->Makefile->GetCurrentSourceDirectory(); makefileIn += "/"; makefileIn += "CMakeLists.txt"; @@ -342,17 +340,14 @@ cmSourceFile* cmLocalVisualStudio7Generator::CreateVCProjBuildRule() } } -void cmLocalVisualStudio7Generator::WriteConfigurations(std::ostream& fout, - const std::string& libName, - cmTarget &target) +void cmLocalVisualStudio7Generator::WriteConfigurations( + std::ostream& fout, std::vector<std::string> const& configs, + const std::string& libName, cmTarget &target + ) { - std::vector<std::string> *configs = - static_cast<cmGlobalVisualStudio7Generator *> - (this->GlobalGenerator)->GetConfigurations(); - fout << "\t<Configurations>\n"; - for( std::vector<std::string>::iterator i = configs->begin(); - i != configs->end(); ++i) + for (std::vector<std::string>::const_iterator i = configs.begin(); + i != configs.end(); ++i) { this->WriteConfiguration(fout, i->c_str(), libName, target); } @@ -772,7 +767,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, } Options targetOptions(this, t, table, - this->ExtraFlagTable); + gg->ExtraFlagTable); targetOptions.FixExceptionHandlingDefault(); std::string asmLocation = configName + "/"; targetOptions.AddFlag("AssemblerListingLocation", asmLocation.c_str()); @@ -994,7 +989,7 @@ void cmLocalVisualStudio7Generator::WriteConfiguration(std::ostream& fout, // end of <Tool Name=VCMIDLTool // Check if we need the FAT32 workaround. - if(targetBuilds && this->Version >= VS8) + if(targetBuilds && this->GetVersion() >= cmGlobalVisualStudioGenerator::VS8) { // Check the filesystem type where the target will be written. if(cmLVS6G_IsFAT(target.GetDirectory(configName).c_str())) @@ -1129,7 +1124,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, fout << "\t\t\t<Tool\n" << "\t\t\t\tName=\"" << tool << "\"\n"; - if(this->GetVersion() < VS8 || this->FortranProject) + if(this->GetVersion() < cmGlobalVisualStudioGenerator::VS8 + || this->FortranProject) { std::ostringstream libdeps; this->Internal->OutputObjects(libdeps, &target); @@ -1189,7 +1185,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, // libraries which may be set by the user to something bad. fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) " << this->Makefile->GetSafeDefinition(standardLibsVar.c_str()); - if(this->GetVersion() < VS8 || this->FortranProject) + if(this->GetVersion() < cmGlobalVisualStudioGenerator::VS8 + || this->FortranProject) { this->Internal->OutputObjects(fout, &target, " "); } @@ -1217,7 +1214,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, } if(this->WindowsCEProject) { - if(this->GetVersion() < VS9) + if(this->GetVersion() < cmGlobalVisualStudioGenerator::VS9) { fout << "\t\t\t\tSubSystem=\"9\"\n"; } @@ -1287,7 +1284,8 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, // libraries which may be set by the user to something bad. fout << "\t\t\t\tAdditionalDependencies=\"$(NOINHERIT) " << this->Makefile->GetSafeDefinition(standardLibsVar.c_str()); - if(this->GetVersion() < VS8 || this->FortranProject) + if(this->GetVersion() < cmGlobalVisualStudioGenerator::VS8 + || this->FortranProject) { this->Internal->OutputObjects(fout, &target, " "); } @@ -1315,7 +1313,7 @@ void cmLocalVisualStudio7Generator::OutputBuildTool(std::ostream& fout, } if ( this->WindowsCEProject ) { - if(this->GetVersion() < VS9) + if(this->GetVersion() < cmGlobalVisualStudioGenerator::VS9) { fout << "\t\t\t\tSubSystem=\"9\"\n"; } @@ -1468,10 +1466,8 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout, const std::string& libName, cmTarget &target) { - // get the configurations - std::vector<std::string> *configs = - static_cast<cmGlobalVisualStudio7Generator *> - (this->GlobalGenerator)->GetConfigurations(); + std::vector<std::string> configs; + this->Makefile->GetConfigurations(configs); // We may be modifying the source groups temporarily, so make a copy. std::vector<cmSourceGroup> sourceGroups = this->Makefile->GetSourceGroups(); @@ -1504,7 +1500,7 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout, // open the project this->WriteProjectStart(fout, libName, target, sourceGroups); // write the configuration information - this->WriteConfigurations(fout, libName, target); + this->WriteConfigurations(fout, configs, libName, target); fout << "\t<Files>\n"; @@ -1516,7 +1512,8 @@ void cmLocalVisualStudio7Generator::WriteVCProjFile(std::ostream& fout, this->WriteGroup(&sg, target, fout, libName, configs); } - if(this->GetVersion() >= VS8 && !this->FortranProject) + if(this->GetVersion() >= cmGlobalVisualStudioGenerator::VS8 + && !this->FortranProject) { // VS >= 8 support per-config source locations so we // list object library content as external objects. @@ -1560,7 +1557,7 @@ public: cmLocalVisualStudio7GeneratorFCInfo(cmLocalVisualStudio7Generator* lg, cmTarget& target, cmSourceFile const& sf, - std::vector<std::string>* configs); + std::vector<std::string> const& configs); std::map<std::string, cmLVS7GFileConfig> FileConfigMap; }; @@ -1568,7 +1565,7 @@ cmLocalVisualStudio7GeneratorFCInfo ::cmLocalVisualStudio7GeneratorFCInfo(cmLocalVisualStudio7Generator* lg, cmTarget& target, cmSourceFile const& sf, - std::vector<std::string>* configs) + std::vector<std::string> const& configs) { cmGeneratorTarget* gt = lg->GetGlobalGenerator()->GetGeneratorTarget(&target); @@ -1579,8 +1576,8 @@ cmLocalVisualStudio7GeneratorFCInfo } // Compute per-source, per-config information. - for(std::vector<std::string>::iterator i = configs->begin(); - i != configs->end(); ++i) + for(std::vector<std::string>::const_iterator i = configs.begin(); + i != configs.end(); ++i) { std::string configUpper = cmSystemTools::UpperCase(*i); cmLVS7GFileConfig fc; @@ -1690,13 +1687,13 @@ std::string cmLocalVisualStudio7Generator ::ComputeLongestObjectDirectory(cmTarget& target) const { - std::vector<std::string> *configs = - static_cast<cmGlobalVisualStudio7Generator *> - (this->GlobalGenerator)->GetConfigurations(); + std::vector<std::string> configs; + target.GetMakefile()->GetConfigurations(configs); + // Compute the maximum length configuration name. std::string config_max; - for(std::vector<std::string>::iterator i = configs->begin(); - i != configs->end(); ++i) + for(std::vector<std::string>::iterator i = configs.begin(); + i != configs.end(); ++i) { if(i->size() > config_max.size()) { @@ -1720,7 +1717,7 @@ cmLocalVisualStudio7Generator bool cmLocalVisualStudio7Generator ::WriteGroup(const cmSourceGroup *sg, cmTarget& target, std::ostream &fout, const std::string& libName, - std::vector<std::string> *configs) + std::vector<std::string> const& configs) { cmGlobalVisualStudio7Generator* gg = static_cast<cmGlobalVisualStudio7Generator *>(this->GlobalGenerator); @@ -1770,7 +1767,8 @@ bool cmLocalVisualStudio7Generator fout << "\t\t\t\tRelativePath=\"" << d << "\">\n"; if(cmCustomCommand const* command = (*sf)->GetCustomCommand()) { - this->WriteCustomRule(fout, source.c_str(), *command, fcinfo); + this->WriteCustomRule(fout, configs, source.c_str(), + *command, fcinfo); } else if(!fcinfo.FileConfigMap.empty()) { @@ -1841,7 +1839,7 @@ bool cmLocalVisualStudio7Generator table = cmLocalVisualStudio7GeneratorFortranFlagTable; } Options fileOptions(this, tool, table, - this->ExtraFlagTable); + gg->ExtraFlagTable); fileOptions.Parse(fc.CompileFlags.c_str()); fileOptions.AddDefines(fc.CompileDefs.c_str()); fileOptions.AddDefines(fc.CompileDefsConfig.c_str()); @@ -1886,6 +1884,7 @@ bool cmLocalVisualStudio7Generator void cmLocalVisualStudio7Generator:: WriteCustomRule(std::ostream& fout, + std::vector<std::string> const& configs, const char* source, const cmCustomCommand& command, FCInfo& fcinfo) @@ -1894,10 +1893,6 @@ WriteCustomRule(std::ostream& fout, static_cast<cmGlobalVisualStudio7Generator *>(this->GlobalGenerator); // Write the rule for each configuration. - std::vector<std::string>::iterator i; - std::vector<std::string> *configs = - static_cast<cmGlobalVisualStudio7Generator *> - (this->GlobalGenerator)->GetConfigurations(); const char* compileTool = "VCCLCompilerTool"; if(this->FortranProject) { @@ -1908,7 +1903,8 @@ WriteCustomRule(std::ostream& fout, { customTool = "VFCustomBuildTool"; } - for(i = configs->begin(); i != configs->end(); ++i) + for (std::vector<std::string>::const_iterator i = configs.begin(); + i != configs.end(); ++i) { cmCustomCommandGenerator ccg(command, *i, this->Makefile); cmLVS7GFileConfig const& fc = fcinfo.FileConfigMap[*i]; @@ -2148,13 +2144,13 @@ cmLocalVisualStudio7Generator::WriteProjectStart(std::ostream& fout, << gg->Encoding() << "\"?>\n" << "<VisualStudioProject\n" << "\tProjectType=\"Visual C++\"\n"; - if(this->Version == VS71) + if(gg->GetVersion() == cmGlobalVisualStudioGenerator::VS71) { fout << "\tVersion=\"7.10\"\n"; } else { - fout << "\tVersion=\"" << (this->Version/10) << ".00\"\n"; + fout << "\tVersion=\"" << (gg->GetVersion()/10) << ".00\"\n"; } const char* projLabel = target.GetProperty("PROJECT_LABEL"); if(!projLabel) @@ -2167,7 +2163,7 @@ cmLocalVisualStudio7Generator::WriteProjectStart(std::ostream& fout, keyword = "Win32Proj"; } fout << "\tName=\"" << projLabel << "\"\n"; - if(this->Version >= VS8) + if(gg->GetVersion() >= cmGlobalVisualStudioGenerator::VS8) { fout << "\tProjectGUID=\"{" << gg->GetGUID(libName.c_str()) << "}\"\n"; } diff --git a/Source/cmLocalVisualStudio7Generator.h b/Source/cmLocalVisualStudio7Generator.h index cfbc63c..43f3af9 100644 --- a/Source/cmLocalVisualStudio7Generator.h +++ b/Source/cmLocalVisualStudio7Generator.h @@ -35,7 +35,9 @@ class cmLocalVisualStudio7Generator : public cmLocalVisualStudioGenerator { public: ///! Set cache only and recurse to false by default. - cmLocalVisualStudio7Generator(VSVersion v, cmLocalGenerator* parent); + cmLocalVisualStudio7Generator(cmGlobalGenerator* gg, + cmLocalGenerator* parent, + cmState::Snapshot snapshot); virtual ~cmLocalVisualStudio7Generator(); @@ -53,8 +55,6 @@ public: */ void SetBuildType(BuildType,const std::string& name); - void SetExtraFlagTable(cmVS7FlagTable const* table) - { this->ExtraFlagTable = table; } virtual std::string GetTargetDirectory(cmTarget const&) const; cmSourceFile* CreateVCProjBuildRule(); void WriteStampFiles(); @@ -78,6 +78,7 @@ private: void WriteVCProjFile(std::ostream& fout, const std::string& libName, cmTarget &tgt); void WriteConfigurations(std::ostream& fout, + std::vector<std::string> const& configs, const std::string& libName, cmTarget &tgt); void WriteConfiguration(std::ostream& fout, const std::string& configName, @@ -102,6 +103,7 @@ private: void WriteVCProjEndGroup(std::ostream& fout); void WriteCustomRule(std::ostream& fout, + std::vector<std::string> const& configs, const char* source, const cmCustomCommand& command, FCInfo& fcinfo); @@ -110,7 +112,7 @@ private: bool WriteGroup(const cmSourceGroup *sg, cmTarget& target, std::ostream &fout, const std::string& libName, - std::vector<std::string> *configs); + std::vector<std::string> const& configs); friend class cmLocalVisualStudio7GeneratorFCInfo; friend class cmLocalVisualStudio7GeneratorInternals; @@ -118,7 +120,6 @@ private: class EventWriter; friend class EventWriter; - cmVS7FlagTable const* ExtraFlagTable; std::string ModuleDefinitionFile; bool FortranProject; bool WindowsCEProject; diff --git a/Source/cmLocalVisualStudioGenerator.cxx b/Source/cmLocalVisualStudioGenerator.cxx index 854ad34..ca72939 100644 --- a/Source/cmLocalVisualStudioGenerator.cxx +++ b/Source/cmLocalVisualStudioGenerator.cxx @@ -19,12 +19,11 @@ //---------------------------------------------------------------------------- cmLocalVisualStudioGenerator -::cmLocalVisualStudioGenerator(VSVersion v, cmLocalGenerator* parent) - : cmLocalGenerator(parent) +::cmLocalVisualStudioGenerator(cmGlobalGenerator* gg, + cmLocalGenerator* parent, + cmState::Snapshot snapshot) + : cmLocalGenerator(gg, parent, snapshot) { - this->WindowsShell = true; - this->WindowsVSIDE = true; - this->Version = v; } //---------------------------------------------------------------------------- @@ -33,6 +32,15 @@ cmLocalVisualStudioGenerator::~cmLocalVisualStudioGenerator() } //---------------------------------------------------------------------------- +cmGlobalVisualStudioGenerator::VSVersion +cmLocalVisualStudioGenerator::GetVersion() const +{ + cmGlobalVisualStudioGenerator* gg = + static_cast<cmGlobalVisualStudioGenerator*>(this->GlobalGenerator); + return gg->GetVersion(); +} + +//---------------------------------------------------------------------------- void cmLocalVisualStudioGenerator::ComputeObjectFilenames( std::map<cmSourceFile const*, std::string>& mapping, cmGeneratorTarget const* gt) @@ -92,7 +100,7 @@ cmLocalVisualStudioGenerator::MaybeCreateImplibDir(cmTarget& target, // Add a pre-build event to create the directory. cmCustomCommandLine command; - command.push_back(this->Makefile->GetRequiredDefinition("CMAKE_COMMAND")); + command.push_back(cmSystemTools::GetCMakeCommand()); command.push_back("-E"); command.push_back("make_directory"); command.push_back(impDir); diff --git a/Source/cmLocalVisualStudioGenerator.h b/Source/cmLocalVisualStudioGenerator.h index 562d595..d414651 100644 --- a/Source/cmLocalVisualStudioGenerator.h +++ b/Source/cmLocalVisualStudioGenerator.h @@ -13,6 +13,7 @@ #define cmLocalVisualStudioGenerator_h #include "cmLocalGenerator.h" +#include "cmGlobalVisualStudioGenerator.h" #include <cmsys/auto_ptr.hxx> @@ -30,22 +31,9 @@ class cmCustomCommandGenerator; class cmLocalVisualStudioGenerator : public cmLocalGenerator { public: - /** Known versions of Visual Studio. */ - enum VSVersion - { - VS6 = 60, - VS7 = 70, - VS71 = 71, - VS8 = 80, - VS9 = 90, - VS10 = 100, - VS11 = 110, - VS12 = 120, - /* VS13 = 130 was skipped */ - VS14 = 140 - }; - - cmLocalVisualStudioGenerator(VSVersion v, cmLocalGenerator* parent); + cmLocalVisualStudioGenerator(cmGlobalGenerator* gg, + cmLocalGenerator* parent, + cmState::Snapshot snapshot); virtual ~cmLocalVisualStudioGenerator(); /** Construct a script from the given list of command lines. */ @@ -56,8 +44,7 @@ public: sequence of custom commands. */ const char* GetReportErrorLabel() const; - /** Version of Visual Studio. */ - VSVersion GetVersion() const { return this->Version; } + cmGlobalVisualStudioGenerator::VSVersion GetVersion() const; virtual std::string ComputeLongestObjectDirectory(cmTarget&) const = 0; @@ -75,8 +62,6 @@ protected: cmsys::auto_ptr<cmCustomCommand> MaybeCreateImplibDir(cmTarget& target, const std::string& config, bool isFortran); - - VSVersion Version; }; #endif diff --git a/Source/cmLocalXCodeGenerator.cxx b/Source/cmLocalXCodeGenerator.cxx index 1d3a8cf..804dd7d 100644 --- a/Source/cmLocalXCodeGenerator.cxx +++ b/Source/cmLocalXCodeGenerator.cxx @@ -15,8 +15,10 @@ #include "cmMakefile.h" //---------------------------------------------------------------------------- -cmLocalXCodeGenerator::cmLocalXCodeGenerator(cmLocalGenerator* parent) - : cmLocalGenerator(parent) +cmLocalXCodeGenerator::cmLocalXCodeGenerator(cmGlobalGenerator* gg, + cmLocalGenerator* parent, + cmState::Snapshot snapshot) + : cmLocalGenerator(gg, parent, snapshot) { // the global generator does this, so do not // put these flags into the language flags diff --git a/Source/cmLocalXCodeGenerator.h b/Source/cmLocalXCodeGenerator.h index 1a5760f..26fff9c 100644 --- a/Source/cmLocalXCodeGenerator.h +++ b/Source/cmLocalXCodeGenerator.h @@ -24,7 +24,8 @@ class cmLocalXCodeGenerator : public cmLocalGenerator { public: ///! Set cache only and recurse to false by default. - cmLocalXCodeGenerator(cmLocalGenerator* parent); + cmLocalXCodeGenerator(cmGlobalGenerator* gg, cmLocalGenerator* parent, + cmState::Snapshot snapshot); virtual ~cmLocalXCodeGenerator(); virtual std::string GetTargetDirectory(cmTarget const& target) const; diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 0935383..7c74a0f 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -38,7 +38,6 @@ #include <cmsys/FStream.hxx> #include <cmsys/auto_ptr.hxx> -#include <stack> #include <list> #include <ctype.h> // for isspace #include <assert.h> @@ -46,42 +45,109 @@ class cmMakefile::Internals { public: - std::stack<cmDefinitions, std::list<cmDefinitions> > VarStack; - std::stack<std::set<std::string> > VarInitStack; - std::stack<std::set<std::string> > VarUsageStack; + std::list<cmDefinitions> VarStack; bool IsSourceFileTryCompile; + + void PushDefinitions() + { + this->VarStack.push_back(cmDefinitions()); + } + + void InitializeDefinitions(cmMakefile* parent) + { + this->VarStack.back() = + cmDefinitions::MakeClosure(parent->Internal->VarStack.rbegin(), + parent->Internal->VarStack.rend()); + } + + const char* GetDefinition(std::string const& name) + { + return cmDefinitions::Get(name, this->VarStack.rbegin(), + this->VarStack.rend()); + } + + bool IsInitialized(std::string const& name) + { + return cmDefinitions::HasKey(name, this->VarStack.rbegin(), + this->VarStack.rend()); + } + + void SetDefinition(std::string const& name, std::string const& value) + { + this->VarStack.back().Set(name, value.c_str()); + } + + void RemoveDefinition(std::string const& name) + { + this->VarStack.back().Set(name, 0); + } + + std::vector<std::string> UnusedKeys() const + { + return this->VarStack.back().UnusedKeys(); + } + + std::vector<std::string> ClosureKeys() const + { + return cmDefinitions::ClosureKeys(this->VarStack.rbegin(), + this->VarStack.rend()); + } + + void PopDefinitions() + { + this->VarStack.pop_back(); + } + + bool RaiseScope(std::string const& var, const char* varDef, cmMakefile* mf) + { + std::list<cmDefinitions>::reverse_iterator it = this->VarStack.rbegin(); + assert(it != this->VarStack.rend()); + ++it; + if(it == this->VarStack.rend()) + { + cmLocalGenerator* plg = mf->GetLocalGenerator()->GetParent(); + if(!plg) + { + return false; + } + // Update the definition in the parent directory top scope. This + // directory's scope was initialized by the closure of the parent + // scope, so we do not need to localize the definition first. + cmMakefile* parent = plg->GetMakefile(); + if (varDef) + { + parent->AddDefinition(var, varDef); + } + else + { + parent->RemoveDefinition(var); + } + return true; + } + // First localize the definition in the current scope. + cmDefinitions::Raise(var, this->VarStack.rbegin(), this->VarStack.rend()); + + // Now update the definition in the parent scope. + it->Set(var, varDef); + return true; + } }; // default is not to be building executables cmMakefile::cmMakefile(cmLocalGenerator* localGenerator) : Internal(new Internals), LocalGenerator(localGenerator), - StateSnapshot(localGenerator->GetGlobalGenerator() - ->GetCMakeInstance()->GetState()) -{ - const cmDefinitions& defs = cmDefinitions(); - const std::set<std::string> globalKeys = defs.LocalKeys(); - this->Internal->VarStack.push(defs); - this->Internal->VarInitStack.push(globalKeys); - this->Internal->VarUsageStack.push(globalKeys); + StateSnapshot(localGenerator->GetStateSnapshot()) +{ + this->Internal->PushDefinitions(); this->Internal->IsSourceFileTryCompile = false; - if (this->LocalGenerator->GetParent()) - { - cmMakefile* parentMf = this->LocalGenerator->GetParent()->GetMakefile(); - this->StateSnapshot = - this->GetState()->CreateSnapshot(parentMf->StateSnapshot); - } - else - { - this->StateSnapshot = - this->GetState()->CreateSnapshot(this->StateSnapshot); - } - - // Initialize these first since AddDefaultDefinitions calls AddDefinition - this->WarnUnused = false; - this->CheckSystemVars = false; + this->WarnUnused = this->GetCMakeInstance()->GetWarnUnused(); + this->CheckSystemVars = this->GetCMakeInstance()->GetCheckSystemVars(); + + this->GeneratingBuildSystem = false; + this->SuppressWatches = false; // Setup the default include file regular expression (match everything). this->IncludeFileRegularExpression = "^.*$"; @@ -114,18 +180,9 @@ cmMakefile::cmMakefile(cmLocalGenerator* localGenerator) this->HeaderFileExtensions.push_back( "txx" ); this->DefineFlags = " "; - this->LocalGenerator = localGenerator; this->AddDefaultDefinitions(); - this->Initialize(); - this->GeneratingBuildSystem = false; - - this->SuppressWatches = false; -} -//---------------------------------------------------------------------------- -void cmMakefile::Initialize() -{ this->cmDefineRegex.compile("#cmakedefine[ \t]+([A-Za-z_0-9]*)"); this->cmDefine01Regex.compile("#cmakedefine01[ \t]+([A-Za-z_0-9]*)"); this->cmAtVarRegex.compile("(@[A-Za-z_0-9/.+-]+@)"); @@ -157,24 +214,16 @@ void cmMakefile::Initialize() #endif this->Properties.SetCMakeInstance(this->GetCMakeInstance()); - this->WarnUnused = this->GetCMakeInstance()->GetWarnUnused(); - this->CheckSystemVars = this->GetCMakeInstance()->GetCheckSystemVars(); { const char* dir = this->GetCMakeInstance()->GetHomeDirectory(); this->AddDefinition("CMAKE_SOURCE_DIR", dir); - if ( !this->GetDefinition("CMAKE_CURRENT_SOURCE_DIR") ) - { - this->AddDefinition("CMAKE_CURRENT_SOURCE_DIR", dir); - } + this->AddDefinition("CMAKE_CURRENT_SOURCE_DIR", dir); } { const char* dir = this->GetCMakeInstance()->GetHomeOutputDirectory(); this->AddDefinition("CMAKE_BINARY_DIR", dir); - if ( !this->GetDefinition("CMAKE_CURRENT_BINARY_DIR") ) - { - this->AddDefinition("CMAKE_CURRENT_BINARY_DIR", dir); - } + this->AddDefinition("CMAKE_CURRENT_BINARY_DIR", dir); } } @@ -195,99 +244,34 @@ cmMakefile::~cmMakefile() } } -void cmMakefile::PrintStringVector(const char* s, - const std::vector<std::string>& v) const -{ - std::cout << s << ": ( \n" << cmWrap('"', v, '"', " ") << ")\n"; -} - -void cmMakefile -::PrintStringVector(const char* s, - const std::vector<std::pair<std::string, bool> >& v) const -{ - std::cout << s << ": ( \n"; - for(std::vector<std::pair<std::string, bool> >::const_iterator i - = v.begin(); i != v.end(); ++i) - { - std::cout << i->first << " " << i->second; - } - std::cout << " )\n"; -} - - -// call print on all the classes in the makefile -void cmMakefile::Print() const -{ - // print the class lists - std::cout << "classes:\n"; - - std::cout << " this->Targets: "; - for (cmTargets::iterator l = this->Targets.begin(); - l != this->Targets.end(); l++) - { - std::cout << l->first << std::endl; - } - - std::cout << " this->StartOutputDirectory; " << - this->GetCurrentBinaryDirectory() << std::endl; - std::cout << " this->HomeOutputDirectory; " << - this->GetHomeOutputDirectory() << std::endl; - std::cout << " this->cmStartDirectory; " << - this->GetCurrentSourceDirectory() << std::endl; - std::cout << " this->cmHomeDirectory; " << - this->GetHomeDirectory() << std::endl; - std::cout << " this->ProjectName; " - << this->ProjectName << std::endl; - this->PrintStringVector("this->LinkDirectories", this->LinkDirectories); -#if defined(CMAKE_BUILD_WITH_CMAKE) - for( std::vector<cmSourceGroup>::const_iterator i = - this->SourceGroups.begin(); i != this->SourceGroups.end(); ++i) - { - std::cout << "Source Group: " << i->GetName() << std::endl; - } -#endif -} - //---------------------------------------------------------------------------- void cmMakefile::IssueMessage(cmake::MessageType t, std::string const& text) const { // Collect context information. - cmLocalGenerator* localGen = this->GetLocalGenerator(); - if(this->CallStack.empty() && this->GetCMakeInstance()->GetIsInTryCompile()) - { - localGen = 0; - } - cmListFileBacktrace backtrace(localGen); if(!this->CallStack.empty()) { if((t == cmake::FATAL_ERROR) || (t == cmake::INTERNAL_ERROR)) { this->CallStack.back().Status->SetNestedError(true); } - backtrace = this->GetBacktrace(); + this->GetCMakeInstance()->IssueMessage(t, text, this->GetBacktrace()); } else { cmListFileContext lfc; - if(this->ListFileStack.empty()) - { - // We are not processing the project. Add the directory-level context. - lfc.FilePath = this->GetCurrentSourceDirectory(); - lfc.FilePath += "/CMakeLists.txt"; - } - else + // We are not currently executing a command. Add whatever context + // information we have. + lfc.FilePath = this->ListFileStack.back(); + + if(!this->GetCMakeInstance()->GetIsInTryCompile()) { - // We are processing the project but are not currently executing a - // command. Add whatever context information we have. - lfc.FilePath = this->ListFileStack.back(); + lfc.FilePath = this->LocalGenerator->Convert(lfc.FilePath, + cmLocalGenerator::HOME); } lfc.Line = 0; - backtrace.push_back(lfc); + this->GetCMakeInstance()->IssueMessage(t, text, lfc); } - - // Issue the message. - this->GetCMakeInstance()->IssueMessage(t, text, backtrace); } //---------------------------------------------------------------------------- @@ -297,12 +281,18 @@ cmListFileBacktrace cmMakefile::GetBacktrace() const for(CallStackType::const_reverse_iterator i = this->CallStack.rbegin(); i != this->CallStack.rend(); ++i) { - backtrace.push_back(*i->Context); + backtrace.Append(*i->Context); } return backtrace; } //---------------------------------------------------------------------------- +cmListFileContext cmMakefile::GetExecutionContext() const +{ + return *this->CallStack.back().Context; +} + +//---------------------------------------------------------------------------- void cmMakefile::PrintCommandTrace(const cmListFileFunction& lff) const { std::ostringstream msg; @@ -470,7 +460,7 @@ cmMakefile::IncludeScope::~IncludeScope() // one we pushed above. If the entry is empty, then the included // script did not set any policies that might affect the includer so // we do not need to enforce the policy. - if(this->CheckCMP0011 && this->Makefile->PolicyStack.back().empty()) + if(this->CheckCMP0011 && this->Makefile->PolicyStack.back().IsEmpty()) { this->CheckCMP0011 = false; } @@ -492,14 +482,13 @@ void cmMakefile::IncludeScope::EnforceCMP0011() { // We check the setting of this policy again because the included // script might actually set this policy for its includer. - cmPolicies* policies = this->Makefile->GetPolicies(); switch (this->Makefile->GetPolicyStatus(cmPolicies::CMP0011)) { case cmPolicies::WARN: // Warn because the user did not set this policy. { std::ostringstream w; - w << policies->GetPolicyWarning(cmPolicies::CMP0011) << "\n" + w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0011) << "\n" << "The included script\n " << this->File << "\n" << "affects policy settings. " << "CMake is implying the NO_POLICY_SCOPE option for compatibility, " @@ -511,7 +500,7 @@ void cmMakefile::IncludeScope::EnforceCMP0011() case cmPolicies::REQUIRED_ALWAYS: { std::ostringstream e; - e << policies->GetRequiredPolicyError(cmPolicies::CMP0011) << "\n" + e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0011) << "\n" << "The included script\n " << this->File << "\n" << "affects policy settings, so it requires this policy to be set."; this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); @@ -529,7 +518,6 @@ void cmMakefile::IncludeScope::EnforceCMP0011() bool cmMakefile::ProcessBuildsystemFile(const char* listfile) { this->AddDefinition("CMAKE_PARENT_LIST_FILE", listfile); - this->cmCurrentListFile = listfile; std::string curSrc = this->GetCurrentSourceDirectory(); return this->ReadListFile(listfile, true, curSrc == this->GetHomeDirectory()); @@ -537,17 +525,20 @@ bool cmMakefile::ProcessBuildsystemFile(const char* listfile) bool cmMakefile::ReadDependentFile(const char* listfile, bool noPolicyScope) { - this->AddDefinition("CMAKE_PARENT_LIST_FILE", this->GetCurrentListFile()); - this->cmCurrentListFile = - cmSystemTools::CollapseFullPath(listfile, - this->GetCurrentSourceDirectory()); - return this->ReadListFile(this->cmCurrentListFile.c_str(), - noPolicyScope); + this->AddDefinition("CMAKE_PARENT_LIST_FILE", + this->GetDefinition("CMAKE_CURRENT_LIST_FILE")); + bool result = this->ReadListFile(listfile, noPolicyScope, false); + this->ListFileStack.pop_back(); + return result; +} + +bool cmMakefile::ReadListFile(const char* listfile) +{ + bool result = this->ReadListFile(listfile, true, false); + this->ListFileStack.pop_back(); + return result; } -//---------------------------------------------------------------------------- -// Parse the given CMakeLists.txt file executing all commands -// bool cmMakefile::ReadListFile(const char* listfile, bool noPolicyScope, bool requireProjectCommand) @@ -582,11 +573,8 @@ bool cmMakefile::ReadListFile(const char* listfile, this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_FILE"); this->MarkVariableAsUsed("CMAKE_CURRENT_LIST_DIR"); - this->ListFileStack.pop_back(); - if (res) { - // Check for unused variables this->CheckForUnusedVariables(); } @@ -780,8 +768,7 @@ cmMakefile::AddCustomCommandToTarget(const std::string& target, switch(this->GetPolicyStatus(cmPolicies::CMP0040)) { case cmPolicies::WARN: - e << (this->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0040)) << "\n"; + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0040) << "\n"; issueMessage = true; case cmPolicies::OLD: break; @@ -901,33 +888,6 @@ cmMakefile::AddCustomCommandToOutput(const std::vector<std::string>& outputs, } else { - std::ostringstream e; - cmake::MessageType messageType = cmake::AUTHOR_WARNING; - bool issueMessage = false; - - switch(this->GetPolicyStatus(cmPolicies::CMP0057)) - { - case cmPolicies::WARN: - e << (this->GetPolicies()-> - GetPolicyWarning(cmPolicies::CMP0057)) << "\n"; - issueMessage = true; - case cmPolicies::OLD: - break; - case cmPolicies::NEW: - case cmPolicies::REQUIRED_IF_USED: - case cmPolicies::REQUIRED_ALWAYS: - issueMessage = true; - messageType = cmake::FATAL_ERROR; - break; - } - - if(issueMessage) - { - e << "\"" << main_dependency << "\" can only be specified as a " - "custom command MAIN_DEPENDENCY once."; - IssueMessage(messageType, e.str()); - } - // The existing custom command is different. We need to // generate a rule file for this new command. file = 0; @@ -942,7 +902,7 @@ 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(); + cmGlobalGenerator* gg = this->GetGlobalGenerator(); // Construct a rule file associated with the first output produced. std::string outName = gg->GenerateRuleFile(outputs[0]); @@ -1348,8 +1308,7 @@ bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove) // VS6 IDE does not support definition values with spaces in // combination with '"', '$', or ';'. - if((this->LocalGenerator->GetGlobalGenerator()->GetName() == - "Visual Studio 6") && + if((this->GetGlobalGenerator()->GetName() == "Visual Studio 6") && (def.find(" ") != def.npos && def.find_first_of("\"$;") != def.npos)) { return false; @@ -1366,7 +1325,7 @@ bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove) case cmPolicies::WARN: this->IssueMessage( cmake::AUTHOR_WARNING, - this->GetPolicies()->GetPolicyWarning(cmPolicies::CMP0005) + cmPolicies::GetPolicyWarning(cmPolicies::CMP0005) ); case cmPolicies::OLD: // OLD behavior is to not escape the value. We should not @@ -1376,7 +1335,7 @@ bool cmMakefile::ParseDefineFlag(std::string const& def, bool remove) case cmPolicies::REQUIRED_ALWAYS: this->IssueMessage( cmake::FATAL_ERROR, - this->GetPolicies()->GetRequiredPolicyError(cmPolicies::CMP0005) + cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0005) ); return false; case cmPolicies::NEW: @@ -1433,8 +1392,7 @@ void cmMakefile::AddLinkLibraryForTarget(const std::string& target, cmTargets::iterator i = this->Targets.find(target); if ( i != this->Targets.end()) { - cmTarget* tgt = - this->GetCMakeInstance()->GetGlobalGenerator()->FindTarget(lib); + cmTarget* tgt = this->GetGlobalGenerator()->FindTarget(lib); if(tgt) { // if it is not a static or shared library then you can not link to it @@ -1523,7 +1481,7 @@ void cmMakefile::InitializeFromParent() cmMakefile *parent = this->LocalGenerator->GetParent()->GetMakefile(); // Initialize definitions with the closure of the parent scope. - this->Internal->VarStack.top() = parent->Internal->VarStack.top().Closure(); + this->Internal->InitializeDefinitions(parent); this->AddDefinition("CMAKE_CURRENT_SOURCE_DIR", this->GetCurrentSourceDirectory()); @@ -1598,12 +1556,47 @@ void cmMakefile::InitializeFromParent() void cmMakefile::ConfigureSubDirectory(cmLocalGenerator *lg2) { lg2->GetMakefile()->InitializeFromParent(); + std::string currentStart = lg2->GetMakefile()->GetCurrentSourceDirectory(); if (this->GetCMakeInstance()->GetDebugOutput()) { std::string msg=" Entering "; - msg += lg2->GetMakefile()->GetCurrentSourceDirectory(); + msg += currentStart; cmSystemTools::Message(msg.c_str()); } + + currentStart += "/CMakeLists.txt"; + if(!cmSystemTools::FileExists(currentStart.c_str(), true)) + { + // The file is missing. Check policy CMP0014. + std::ostringstream e; + e << "The source directory\n" + << " " << currentStart << "\n" + << "does not contain a CMakeLists.txt file."; + switch (this->GetPolicyStatus(cmPolicies::CMP0014)) + { + case cmPolicies::WARN: + // Print the warning. + e << "\n" + << "CMake does not support this case but it used " + << "to work accidentally and is being allowed for " + << "compatibility." + << "\n" + << cmPolicies::GetPolicyWarning(cmPolicies::CMP0014); + this->IssueMessage(cmake::AUTHOR_WARNING, e.str()); + case cmPolicies::OLD: + // OLD behavior does not warn. + break; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + e << "\n" + << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0014); + case cmPolicies::NEW: + // NEW behavior prints the error. + this->IssueMessage(cmake::FATAL_ERROR, e.str()); + } + lg2->SetConfiguredCMP0014(true); + return; + } // finally configure the subdir lg2->Configure(); if (this->GetCMakeInstance()->GetDebugOutput()) @@ -1625,11 +1618,13 @@ void cmMakefile::AddSubDirectory(const std::string& srcPath, return; } + cmState::Snapshot newSnapshot = this->GetState() + ->CreateSnapshot(this->StateSnapshot); + // create a new local generator and set its parent - cmLocalGenerator *lg2 = - this->LocalGenerator->GetGlobalGenerator() - ->CreateLocalGenerator(this->LocalGenerator); - this->LocalGenerator->GetGlobalGenerator()->AddLocalGenerator(lg2); + cmLocalGenerator *lg2 = this->GetGlobalGenerator() + ->MakeLocalGenerator(newSnapshot, this->LocalGenerator); + this->GetGlobalGenerator()->AddLocalGenerator(lg2); // set the subdirs start dirs lg2->GetMakefile()->SetCurrentSourceDirectory(srcPath); @@ -1717,14 +1712,11 @@ void cmMakefile::AddDefinition(const std::string& name, const char* value) return; } - this->Internal->VarStack.top().Set(name, value); - if (!this->Internal->VarUsageStack.empty() && - this->VariableInitialized(name)) + if (this->VariableInitialized(name)) { - this->CheckForUnused("changing definition", name); - this->Internal->VarUsageStack.top().erase(name); + this->LogUnused("changing definition", name); } - this->Internal->VarInitStack.top().insert(name); + this->Internal->SetDefinition(name, value); #ifdef CMAKE_BUILD_WITH_CMAKE cmVariableWatch* vv = this->GetVariableWatch(); @@ -1787,20 +1779,17 @@ void cmMakefile::AddCacheDefinition(const std::string& name, const char* value, this->GetState()->AddCacheEntry(name, haveVal ? val.c_str() : 0, doc, type); // if there was a definition then remove it - this->Internal->VarStack.top().Set(name, 0); + this->Internal->RemoveDefinition(name); } void cmMakefile::AddDefinition(const std::string& name, bool value) { - this->Internal->VarStack.top().Set(name, value? "ON" : "OFF"); - if (!this->Internal->VarUsageStack.empty() && - this->VariableInitialized(name)) + if (this->VariableInitialized(name)) { - this->CheckForUnused("changing definition", name); - this->Internal->VarUsageStack.top().erase(name); + this->LogUnused("changing definition", name); } - this->Internal->VarInitStack.top().insert(name); + this->Internal->SetDefinition(name, value ? "ON" : "OFF"); #ifdef CMAKE_BUILD_WITH_CMAKE cmVariableWatch* vv = this->GetVariableWatch(); if ( vv ) @@ -1817,62 +1806,46 @@ void cmMakefile::CheckForUnusedVariables() const { return; } - const cmDefinitions& defs = this->Internal->VarStack.top(); - const std::set<std::string>& locals = defs.LocalKeys(); - std::set<std::string>::const_iterator it = locals.begin(); - for (; it != locals.end(); ++it) + const std::vector<std::string>& unused = this->Internal->UnusedKeys(); + std::vector<std::string>::const_iterator it = unused.begin(); + for (; it != unused.end(); ++it) { - this->CheckForUnused("out of scope", *it); + this->LogUnused("out of scope", *it); } } void cmMakefile::MarkVariableAsUsed(const std::string& var) { - this->Internal->VarUsageStack.top().insert(var); + this->Internal->GetDefinition(var); } bool cmMakefile::VariableInitialized(const std::string& var) const { - if(this->Internal->VarInitStack.top().find(var) != - this->Internal->VarInitStack.top().end()) - { - return true; - } - return false; -} - -bool cmMakefile::VariableUsed(const std::string& var) const -{ - if(this->Internal->VarUsageStack.top().find(var) != - this->Internal->VarUsageStack.top().end()) - { - return true; - } - return false; + return this->Internal->IsInitialized(var); } -void cmMakefile::CheckForUnused(const char* reason, +void cmMakefile::LogUnused(const char* reason, const std::string& name) const { - if (this->WarnUnused && !this->VariableUsed(name)) + if (this->WarnUnused) { std::string path; - cmListFileBacktrace bt(this->GetLocalGenerator()); + cmListFileContext lfc; if (!this->CallStack.empty()) { - const cmListFileContext* file = this->CallStack.back().Context; - bt.push_back(*file); - path = file->FilePath.c_str(); + lfc = this->GetExecutionContext(); + path = lfc.FilePath; } else { path = this->GetCurrentSourceDirectory(); path += "/CMakeLists.txt"; - cmListFileContext lfc; lfc.FilePath = path; lfc.Line = 0; - bt.push_back(lfc); } + lfc.FilePath = this->LocalGenerator->Convert(lfc.FilePath, + cmLocalGenerator::HOME); + if (this->CheckSystemVars || cmSystemTools::IsSubDirectory(path, this->GetHomeDirectory()) || @@ -1885,21 +1858,18 @@ void cmMakefile::CheckForUnused(const char* reason, msg << "unused variable (" << reason << ") \'" << name << "\'"; this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, msg.str(), - bt); + lfc); } } } void cmMakefile::RemoveDefinition(const std::string& name) { - this->Internal->VarStack.top().Set(name, 0); - if (!this->Internal->VarUsageStack.empty() && - this->VariableInitialized(name)) + if (this->VariableInitialized(name)) { - this->CheckForUnused("unsetting", name); - this->Internal->VarUsageStack.top().erase(name); + this->LogUnused("unsetting", name); } - this->Internal->VarInitStack.top().insert(name); + this->Internal->RemoveDefinition(name); #ifdef CMAKE_BUILD_WITH_CMAKE cmVariableWatch* vv = this->GetVariableWatch(); if ( vv ) @@ -1946,7 +1916,7 @@ void cmMakefile::AddGlobalLinkInformation(const std::string& name, void cmMakefile::AddAlias(const std::string& lname, cmTarget *tgt) { this->AliasTargets[lname] = tgt; - this->LocalGenerator->GetGlobalGenerator()->AddAlias(lname, tgt); + this->GetGlobalGenerator()->AddAlias(lname, tgt); } cmTarget* cmMakefile::AddLibrary(const std::string& lname, @@ -2003,7 +1973,7 @@ cmMakefile::AddNewTarget(cmTarget::TargetType type, const std::string& name) cmTarget& target = it->second; target.SetType(type, name); target.SetMakefile(this); - this->LocalGenerator->GetGlobalGenerator()->AddTarget(&it->second); + this->GetGlobalGenerator()->AddTarget(&it->second); return &it->second; } @@ -2147,7 +2117,7 @@ void cmMakefile::AddSourceGroup(const std::vector<std::string>& name, } // build the whole source group path const char* fullname = sg->GetFullName(); - cmGlobalGenerator* gg = this->LocalGenerator->GetGlobalGenerator(); + cmGlobalGenerator* gg = this->GetGlobalGenerator(); if(strlen(fullname)) { std::string guidName = "SG_Filter_"; @@ -2264,7 +2234,7 @@ void cmMakefile::ExpandVariablesCMP0019() if(!w.str().empty()) { std::ostringstream m; - m << this->GetPolicies()->GetPolicyWarning(cmPolicies::CMP0019) + m << cmPolicies::GetPolicyWarning(cmPolicies::CMP0019) << "\n" << "The following variable evaluations were encountered:\n" << w.str(); @@ -2365,8 +2335,7 @@ const char* cmMakefile::GetRequiredDefinition(const std::string& name) const bool cmMakefile::IsDefinitionSet(const std::string& name) const { - const char* def = this->Internal->VarStack.top().Get(name); - this->Internal->VarUsageStack.top().insert(name); + const char* def = this->Internal->GetDefinition(name); if(!def) { def = this->GetState()->GetInitializedCacheValue(name); @@ -2387,11 +2356,7 @@ bool cmMakefile::IsDefinitionSet(const std::string& name) const const char* cmMakefile::GetDefinition(const std::string& name) const { - if (this->WarnUnused) - { - this->Internal->VarUsageStack.top().insert(name); - } - const char* def = this->Internal->VarStack.top().Get(name); + const char* def = this->Internal->GetDefinition(name); if(!def) { def = this->GetState()->GetInitializedCacheValue(name); @@ -2431,9 +2396,7 @@ std::vector<std::string> cmMakefile std::vector<std::string> res; if ( !cacheonly ) { - std::set<std::string> definitions = - this->Internal->VarStack.top().ClosureKeys(); - res.insert(res.end(), definitions.begin(), definitions.end()); + res = this->Internal->ClosureKeys(); } std::vector<std::string> cacheKeys = this->GetState()->GetCacheEntryKeys(); @@ -2524,7 +2487,7 @@ const char *cmMakefile::ExpandVariablesInString(std::string& source, else if(compareResults && (newResult != source || newError != mtype)) { std::string msg = - this->GetPolicies()->GetPolicyWarning(cmPolicies::CMP0053); + cmPolicies::GetPolicyWarning(cmPolicies::CMP0053); msg += "\n"; std::string msg_input = original; @@ -2676,9 +2639,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringOld( switch(this->GetPolicyStatus(cmPolicies::CMP0010)) { case cmPolicies::WARN: - error << "\n" - << (this->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0010)); + error << "\n" << cmPolicies::GetPolicyWarning(cmPolicies::CMP0010); case cmPolicies::OLD: // OLD behavior is to just warn and continue. mtype = cmake::AUTHOR_WARNING; @@ -2686,8 +2647,7 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringOld( case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: error << "\n" - << (this->GetPolicies() - ->GetRequiredPolicyError(cmPolicies::CMP0010)); + << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0010); case cmPolicies::NEW: // NEW behavior is to report the error. break; @@ -2802,14 +2762,13 @@ cmake::MessageType cmMakefile::ExpandVariablesInStringNew( this->GetHomeOutputDirectory())) { std::ostringstream msg; - cmListFileBacktrace bt(this->GetLocalGenerator()); cmListFileContext lfc; - lfc.FilePath = filename; + lfc.FilePath = this->LocalGenerator + ->Convert(filename, cmLocalGenerator::HOME); lfc.Line = line; - bt.push_back(lfc); msg << "uninitialized variable \'" << lookup << "\'"; this->GetCMakeInstance()->IssueMessage(cmake::AUTHOR_WARNING, - msg.str(), bt); + msg.str(), lfc); } } } @@ -3106,7 +3065,7 @@ std::string cmMakefile::GetConfigurations(std::vector<std::string>& configs, bool single) const { - if(this->LocalGenerator->GetGlobalGenerator()->IsMultiConfig()) + if(this->GetGlobalGenerator()->IsMultiConfig()) { if(const char* configTypes = this->GetDefinition("CMAKE_CONFIGURATION_TYPES")) @@ -3204,6 +3163,7 @@ void cmMakefile::PopFunctionBlockerBarrier(bool reportError) this->FunctionBlockerBarriers.back(); while(this->FunctionBlockers.size() > barrier) { + cmMakefile::LoopBlockPop loopBlockPop(this); cmsys::auto_ptr<cmFunctionBlocker> fb(this->FunctionBlockers.back()); this->FunctionBlockers.pop_back(); if(reportError) @@ -3338,7 +3298,7 @@ void cmMakefile::AddFunctionBlocker(cmFunctionBlocker* fb) if(!this->CallStack.empty()) { // Record the context in which the blocker is created. - fb->SetStartingContext(*(this->CallStack.back().Context)); + fb->SetStartingContext(this->GetExecutionContext()); } this->FunctionBlockers.push_back(fb); @@ -3477,10 +3437,8 @@ void cmMakefile::EnableLanguage(std::vector<std::string> const & lang, bool optional) { this->AddDefinition("CMAKE_CFG_INTDIR", - this->LocalGenerator->GetGlobalGenerator() - ->GetCMakeCFGIntDir()); - this->LocalGenerator->GetGlobalGenerator()->EnableLanguage(lang, this, - optional); + this->GetGlobalGenerator()->GetCMakeCFGIntDir()); + this->GetGlobalGenerator()->EnableLanguage(lang, this, optional); } int cmMakefile::TryCompile(const std::string& srcdir, @@ -3506,11 +3464,10 @@ int cmMakefile::TryCompile(const std::string& srcdir, // make sure the same generator is used // use this program as the cmake to be run, it should not // be run that way but the cmake object requires a vailid path - std::string cmakeCommand = this->GetDefinition("CMAKE_COMMAND"); cmake cm; cm.SetIsInTryCompile(true); cmGlobalGenerator *gg = cm.CreateGlobalGenerator - (this->LocalGenerator->GetGlobalGenerator()->GetName()); + (this->GetGlobalGenerator()->GetName()); if (!gg) { cmSystemTools::Error( @@ -3571,8 +3528,7 @@ int cmMakefile::TryCompile(const std::string& srcdir, cm.SetCacheArgs(*cmakeArgs); } // to save time we pass the EnableLanguage info directly - gg->EnableLanguagesFromGenerator - (this->LocalGenerator->GetGlobalGenerator(), this); + gg->EnableLanguagesFromGenerator(this->GetGlobalGenerator(), this); if(this->IsOn("CMAKE_SUPPRESS_DEVELOPER_WARNINGS")) { cm.AddCacheEntry("CMAKE_SUPPRESS_DEVELOPER_WARNINGS", @@ -3604,13 +3560,12 @@ int cmMakefile::TryCompile(const std::string& srcdir, } // finally call the generator to actually build the resulting project - int ret = - this->LocalGenerator->GetGlobalGenerator()->TryCompile(srcdir,bindir, - projectName, - targetName, - fast, - output, - this); + int ret = this->GetGlobalGenerator()->TryCompile(srcdir,bindir, + projectName, + targetName, + fast, + output, + this); cmSystemTools::ChangeDirectory(cwd); this->Internal->IsSourceFileTryCompile = false; @@ -3624,11 +3579,12 @@ bool cmMakefile::GetIsSourceFileTryCompile() const cmake *cmMakefile::GetCMakeInstance() const { - if ( this->LocalGenerator && this->LocalGenerator->GetGlobalGenerator() ) - { - return this->LocalGenerator->GetGlobalGenerator()->GetCMakeInstance(); - } - return 0; + return this->GetGlobalGenerator()->GetCMakeInstance(); +} + +cmGlobalGenerator* cmMakefile::GetGlobalGenerator() const +{ + return this->LocalGenerator->GetGlobalGenerator(); } #ifdef CMAKE_BUILD_WITH_CMAKE @@ -3662,8 +3618,7 @@ cmState *cmMakefile::GetState() const void cmMakefile::DisplayStatus(const char* message, float s) const { - cmake* cm = this->GetLocalGenerator()->GetGlobalGenerator() - ->GetCMakeInstance(); + cmake* cm = this->GetCMakeInstance(); if (cm->GetWorkingMode() == cmake::FIND_PACKAGE_MODE) { // don't output any STATUS message in FIND_PACKAGE_MODE, since they will @@ -3751,7 +3706,7 @@ std::string cmMakefile::GetModulesFile(const char* filename) const << moduleInCMakeModulePath << " (found via CMAKE_MODULE_PATH) which shadows " << moduleInCMakeRoot << ". This may cause errors later on .\n" - << this->GetPolicies()->GetPolicyWarning(cmPolicies::CMP0017); + << cmPolicies::GetPolicyWarning(cmPolicies::CMP0017); this->IssueMessage(cmake::AUTHOR_WARNING, e.str()); // break; // fall through to OLD behaviour @@ -4083,11 +4038,12 @@ const char *cmMakefile::GetProperty(const std::string& prop, output = ""; if (prop == "PARENT_DIRECTORY") { - if(cmLocalGenerator* plg = this->LocalGenerator->GetParent()) + cmState::Snapshot parent = this->StateSnapshot.GetParent(); + if(parent.IsValid()) { - output = plg->GetMakefile()->GetCurrentSourceDirectory(); + return parent.GetCurrentSourceDirectory(); } - return output.c_str(); + return ""; } else if (prop == "INCLUDE_REGULAR_EXPRESSION" ) { @@ -4119,7 +4075,7 @@ const char *cmMakefile::GetProperty(const std::string& prop, switch(this->GetPolicyStatus(cmPolicies::CMP0059)) { case cmPolicies::WARN: - this->IssueMessage(cmake::AUTHOR_WARNING, this->GetPolicies()-> + this->IssueMessage(cmake::AUTHOR_WARNING, cmPolicies:: GetPolicyWarning(cmPolicies::CMP0059)); case cmPolicies::OLD: output += this->DefineFlagsOrig; @@ -4296,13 +4252,13 @@ void cmMakefile::AddCMakeDependFilesFromUser() } } -std::string cmMakefile::GetListFileStack() const +std::string cmMakefile::FormatListFileStack() const { std::ostringstream tmp; size_t depth = this->ListFileStack.size(); if (depth > 0) { - std::deque<std::string>::const_iterator it = this->ListFileStack.end(); + std::vector<std::string>::const_iterator it = this->ListFileStack.end(); do { if (depth != this->ListFileStack.size()) @@ -4324,55 +4280,26 @@ std::string cmMakefile::GetListFileStack() const void cmMakefile::PushScope() { - cmDefinitions* parent = &this->Internal->VarStack.top(); - const std::set<std::string>& init = this->Internal->VarInitStack.top(); - const std::set<std::string>& usage = this->Internal->VarUsageStack.top(); - this->Internal->VarStack.push(cmDefinitions(parent)); - this->Internal->VarInitStack.push(init); - this->Internal->VarUsageStack.push(usage); + this->Internal->PushDefinitions(); this->PushLoopBlockBarrier(); #if defined(CMAKE_BUILD_WITH_CMAKE) - this->GetLocalGenerator()->GetGlobalGenerator()-> - GetFileLockPool().PushFunctionScope(); + this->GetGlobalGenerator()->GetFileLockPool().PushFunctionScope(); #endif } void cmMakefile::PopScope() { #if defined(CMAKE_BUILD_WITH_CMAKE) - this->GetLocalGenerator()->GetGlobalGenerator()-> - GetFileLockPool().PopFunctionScope(); + this->GetGlobalGenerator()->GetFileLockPool().PopFunctionScope(); #endif this->PopLoopBlockBarrier(); - cmDefinitions* current = &this->Internal->VarStack.top(); - std::set<std::string> init = this->Internal->VarInitStack.top(); - std::set<std::string> usage = this->Internal->VarUsageStack.top(); - const std::set<std::string>& locals = current->LocalKeys(); - // Remove initialization and usage information for variables in the local - // scope. - std::set<std::string>::const_iterator it = locals.begin(); - for (; it != locals.end(); ++it) - { - init.erase(*it); - if (!this->VariableUsed(*it)) - { - this->CheckForUnused("out of scope", *it); - } - else - { - usage.erase(*it); - } - } - this->Internal->VarStack.pop(); - this->Internal->VarInitStack.pop(); - this->Internal->VarUsageStack.pop(); - // Push initialization and usage up to the parent scope. - this->Internal->VarInitStack.top().insert(init.begin(), init.end()); - this->Internal->VarUsageStack.top().insert(usage.begin(), usage.end()); + this->CheckForUnusedVariables(); + + this->Internal->PopDefinitions(); } void cmMakefile::RaiseScope(const std::string& var, const char *varDef) @@ -4382,31 +4309,7 @@ void cmMakefile::RaiseScope(const std::string& var, const char *varDef) return; } - cmDefinitions& cur = this->Internal->VarStack.top(); - if(cmDefinitions* up = cur.GetParent()) - { - // First localize the definition in the current scope. - cur.Get(var); - - // Now update the definition in the parent scope. - up->Set(var, varDef); - } - else if(cmLocalGenerator* plg = this->LocalGenerator->GetParent()) - { - // Update the definition in the parent directory top scope. This - // directory's scope was initialized by the closure of the parent - // scope, so we do not need to localize the definition first. - cmMakefile* parent = plg->GetMakefile(); - if (varDef) - { - parent->AddDefinition(var, varDef); - } - else - { - parent->RemoveDefinition(var); - } - } - else + if (!this->Internal->RaiseScope(var, varDef, this)) { std::ostringstream m; m << "Cannot set \"" << var << "\": current scope has no parent."; @@ -4430,7 +4333,7 @@ cmMakefile::AddImportedTarget(const std::string& name, this->ImportedTargets[name] = target.get(); if(global) { - this->LocalGenerator->GetGlobalGenerator()->AddTarget(target.get()); + this->GetGlobalGenerator()->AddTarget(target.get()); } // Transfer ownership to this cmMakefile object. @@ -4458,8 +4361,7 @@ cmTarget* cmMakefile::FindTargetToUse(const std::string& name, } // Look for a target built in this project. - return this->LocalGenerator->GetGlobalGenerator()->FindTarget(name, - excludeAliases); + return this->GetGlobalGenerator()->FindTarget(name, excludeAliases); } //---------------------------------------------------------------------------- @@ -4467,8 +4369,7 @@ bool cmMakefile::IsAlias(const std::string& name) const { if (this->AliasTargets.find(name) != this->AliasTargets.end()) return true; - return this->GetLocalGenerator()->GetGlobalGenerator()->IsAlias( - name); + return this->GetGlobalGenerator()->IsAlias(name); } //---------------------------------------------------------------------------- @@ -4477,7 +4378,7 @@ cmMakefile::FindGeneratorTargetToUse(const std::string& name) const { if (cmTarget *t = this->FindTargetToUse(name)) { - return this->LocalGenerator->GetGlobalGenerator()->GetGeneratorTarget(t); + return this->GetGlobalGenerator()->GetGeneratorTarget(t); } return 0; } @@ -4514,14 +4415,14 @@ bool cmMakefile::EnforceUniqueName(std::string const& name, std::string& msg, switch (this->GetPolicyStatus(cmPolicies::CMP0002)) { case cmPolicies::WARN: - this->IssueMessage(cmake::AUTHOR_WARNING, this->GetPolicies()-> + this->IssueMessage(cmake::AUTHOR_WARNING, cmPolicies:: GetPolicyWarning(cmPolicies::CMP0002)); case cmPolicies::OLD: return true; case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: this->IssueMessage(cmake::FATAL_ERROR, - this->GetPolicies()->GetRequiredPolicyError(cmPolicies::CMP0002) + cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0002) ); return true; case cmPolicies::NEW: @@ -4530,8 +4431,7 @@ bool cmMakefile::EnforceUniqueName(std::string const& name, std::string& msg, // The conflict is with a non-imported target. // Allow this if the user has requested support. - cmake* cm = - this->LocalGenerator->GetGlobalGenerator()->GetCMakeInstance(); + cmake* cm = this->GetCMakeInstance(); if(isCustom && existing->GetType() == cmTarget::UTILITY && this != existing->GetMakefile() && cm->GetState() @@ -4583,7 +4483,7 @@ bool cmMakefile::EnforceUniqueDir(const std::string& srcPath, const std::string& binPath) const { // Make sure the binary directory is unique. - cmGlobalGenerator* gg = this->LocalGenerator->GetGlobalGenerator(); + cmGlobalGenerator* gg = this->GetGlobalGenerator(); if(gg->BinaryDirectoryIsNew(binPath)) { return true; @@ -4593,7 +4493,7 @@ bool cmMakefile::EnforceUniqueDir(const std::string& srcPath, { case cmPolicies::WARN: // Print the warning. - e << this->GetPolicies()->GetPolicyWarning(cmPolicies::CMP0013) + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0013) << "\n" << "The binary directory\n" << " " << binPath << "\n" @@ -4610,7 +4510,7 @@ bool cmMakefile::EnforceUniqueDir(const std::string& srcPath, return true; case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: - e << this->GetPolicies()->GetRequiredPolicyError(cmPolicies::CMP0013) + e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0013) << "\n"; case cmPolicies::NEW: // NEW behavior prints the error. @@ -4713,7 +4613,7 @@ cmMakefile::GetPolicyStatus(cmPolicies::PolicyID id) const { return cur; } - cmPolicies::PolicyStatus def = this->GetPolicies()->GetPolicyStatus(id); + cmPolicies::PolicyStatus def = cmPolicies::GetPolicyStatus(id); if(def == cmPolicies::REQUIRED_ALWAYS || def == cmPolicies::REQUIRED_IF_USED) { @@ -4733,10 +4633,9 @@ cmMakefile::GetPolicyStatusInternal(cmPolicies::PolicyID id) const for(PolicyStackType::const_reverse_iterator psi = this->PolicyStack.rbegin(); psi != this->PolicyStack.rend(); ++psi) { - PolicyStackEntry::const_iterator pse = psi->find(id); - if(pse != psi->end()) + if(psi->IsDefined(id)) { - return pse->second; + return psi->Get(id); } } @@ -4748,7 +4647,7 @@ cmMakefile::GetPolicyStatusInternal(cmPolicies::PolicyID id) const } // The policy is not set. Use the default for this CMake version. - return this->GetPolicies()->GetPolicyStatus(id); + return cmPolicies::GetPolicyStatus(id); } //---------------------------------------------------------------------------- @@ -4771,7 +4670,7 @@ bool cmMakefile::SetPolicy(const char *id, cmPolicies::PolicyStatus status) { cmPolicies::PolicyID pid; - if (!this->GetPolicies()->GetPolicyID(id, /* out */ pid)) + if (!cmPolicies::GetPolicyID(id, /* out */ pid)) { std::ostringstream e; e << "Policy \"" << id << "\" is not known to this version of CMake."; @@ -4787,11 +4686,11 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id, { // A REQUIRED_ALWAYS policy may be set only to NEW. if(status != cmPolicies::NEW && - this->GetPolicies()->GetPolicyStatus(id) == + cmPolicies::GetPolicyStatus(id) == cmPolicies::REQUIRED_ALWAYS) { std::string msg = - this->GetPolicies()->GetRequiredAlwaysPolicyError(id); + cmPolicies::GetRequiredAlwaysPolicyError(id); this->IssueMessage(cmake::FATAL_ERROR, msg); return false; } @@ -4801,7 +4700,7 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id, for(PolicyStackType::reverse_iterator psi = this->PolicyStack.rbegin(); previous_was_weak && psi != this->PolicyStack.rend(); ++psi) { - (*psi)[id] = status; + psi->Set(id, status); previous_was_weak = psi->Weak; } @@ -4893,49 +4792,47 @@ void cmMakefile::PopPolicyBarrier(bool reportError) //---------------------------------------------------------------------------- bool cmMakefile::SetPolicyVersion(const char *version) { - return this->GetCMakeInstance()->GetPolicies()-> - ApplyPolicyVersion(this,version); + return cmPolicies::ApplyPolicyVersion(this,version); } //---------------------------------------------------------------------------- -cmPolicies *cmMakefile::GetPolicies() const +bool cmMakefile::HasCMP0054AlreadyBeenReported() const { - if (!this->GetCMakeInstance()) - { - return 0; - } - return this->GetCMakeInstance()->GetPolicies(); + return !this->CMP0054ReportedIds.insert(this->GetExecutionContext()).second; } //---------------------------------------------------------------------------- -bool cmMakefile::HasCMP0054AlreadyBeenReported( - cmListFileContext context) const +void cmMakefile::RecordPolicies(cmPolicies::PolicyMap& pm) { - cmCMP0054Id id(context); - - bool alreadyReported = - this->CMP0054ReportedIds.find(id) != this->CMP0054ReportedIds.end(); - - if(!alreadyReported) + /* Record the setting of every policy. */ + typedef cmPolicies::PolicyID PolicyID; + for(PolicyID pid = cmPolicies::CMP0000; + pid != cmPolicies::CMPCOUNT; pid = PolicyID(pid+1)) { - this->CMP0054ReportedIds.insert(id); + pm.Set(pid, this->GetPolicyStatus(pid)); } - - return alreadyReported; } //---------------------------------------------------------------------------- -void cmMakefile::RecordPolicies(cmPolicies::PolicyMap& pm) +bool cmMakefile::IgnoreErrorsCMP0061() const { - /* Record the setting of every policy. */ - typedef cmPolicies::PolicyID PolicyID; - for(PolicyID pid = cmPolicies::CMP0000; - pid != cmPolicies::CMPCOUNT; pid = PolicyID(pid+1)) + bool ignoreErrors = true; + switch (this->GetPolicyStatus(cmPolicies::CMP0061)) { - pm[pid] = this->GetPolicyStatus(pid); + case cmPolicies::WARN: + // No warning for this policy! + case cmPolicies::OLD: + break; + case cmPolicies::REQUIRED_IF_USED: + case cmPolicies::REQUIRED_ALWAYS: + case cmPolicies::NEW: + ignoreErrors = false; + break; } + return ignoreErrors; } +//---------------------------------------------------------------------------- #define FEATURE_STRING(F) , #F static const char * const C_FEATURES[] = { 0 diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 8968e81..efd73a1 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -31,11 +31,14 @@ #include <cmsys/auto_ptr.hxx> #include <cmsys/RegularExpression.hxx> #if defined(CMAKE_BUILD_WITH_CMAKE) -# include <cmsys/hash_map.hxx> +# ifdef CMake_HAVE_CXX11_UNORDERED_MAP +# include <unordered_map> +# else +# include <cmsys/hash_map.hxx> +# endif #endif #include <stack> -#include <deque> class cmFunctionBlocker; class cmCommand; @@ -62,14 +65,10 @@ class cmMakefile class Internals; cmsys::auto_ptr<Internals> Internal; public: - /* Check for unused variables in this scope */ - void CheckForUnusedVariables() const; /* Mark a variable as used */ void MarkVariableAsUsed(const std::string& var); /* return true if a variable has been initialized */ bool VariableInitialized(const std::string& ) const; - /* return true if a variable has been used */ - bool VariableUsed(const std::string& ) const; /** * Construct an empty makefile. @@ -81,12 +80,7 @@ public: */ ~cmMakefile(); - /** - * Read and parse a CMakeLists.txt file. - */ - bool ReadListFile(const char* listfile, - bool noPolicyScope = true, - bool requireProjectCommand = false); + bool ReadListFile(const char* listfile); bool ReadDependentFile(const char* listfile, bool noPolicyScope = true); @@ -159,11 +153,6 @@ public: */ void FinalPass(); - /** - * Print the object state to std::cout. - */ - void Print() const; - /** Add a custom command to the build. */ void AddCustomCommandToTarget(const std::string& target, const std::vector<std::string>& byproducts, @@ -387,33 +376,15 @@ public: */ cmPolicies *GetPolicies() const; - struct cmCMP0054Id - { - cmCMP0054Id(cmListFileContext const& context): - Context(context) - { - - } - - bool operator< (cmCMP0054Id const& id) const - { - if(this->Context.FilePath != id.Context.FilePath) - return this->Context.FilePath < id.Context.FilePath; - - return this->Context.Line < id.Context.Line; - } - - cmListFileContext Context; - }; - - mutable std::set<cmCMP0054Id> CMP0054ReportedIds; + mutable std::set<cmListFileContext> CMP0054ReportedIds; /** * Determine if the given context, name pair has already been reported * in context of CMP0054. */ - bool HasCMP0054AlreadyBeenReported( - cmListFileContext context) const; + bool HasCMP0054AlreadyBeenReported() const; + + bool IgnoreErrorsCMP0061() const; const char* GetHomeDirectory() const; const char* GetHomeOutputDirectory() const; @@ -433,14 +404,6 @@ public: void SetCurrentBinaryDirectory(const std::string& dir); const char* GetCurrentBinaryDirectory() const; - /* Get the current CMakeLists.txt file that is being processed. This - * is just used in order to be able to 'branch' from one file to a second - * transparently */ - const char* GetCurrentListFile() const - { - return this->cmCurrentListFile.c_str(); - } - //@} /** @@ -603,12 +566,13 @@ public: { this->ListFiles.push_back(file);} void AddCMakeDependFilesFromUser(); - std::string GetListFileStack() const; + std::string FormatListFileStack() const; /** * Get the current context backtrace. */ cmListFileBacktrace GetBacktrace() const; + cmListFileContext GetExecutionContext() const; /** * Get the vector of files created by this makefile @@ -712,6 +676,7 @@ public: * Get the instance */ cmake *GetCMakeInstance() const; + cmGlobalGenerator* GetGlobalGenerator() const; /** * Get all the source files this makefile knows about @@ -856,16 +821,18 @@ protected: void AddGlobalLinkInformation(const std::string& name, cmTarget& target); // Check for a an unused variable - void CheckForUnused(const char* reason, const std::string& name) const; - - std::string cmCurrentListFile; + void LogUnused(const char* reason, const std::string& name) const; std::string ProjectName; // project name // libraries, classes, and executables mutable cmTargets Targets; #if defined(CMAKE_BUILD_WITH_CMAKE) +#ifdef CMake_HAVE_CXX11_UNORDERED_MAP + typedef std::unordered_map<std::string, cmTarget*> TargetMap; +#else typedef cmsys::hash_map<std::string, cmTarget*> TargetMap; +#endif #else typedef std::map<std::string, cmTarget*> TargetMap; #endif @@ -918,10 +885,13 @@ protected: private: cmMakefile(const cmMakefile& mf); cmMakefile& operator=(const cmMakefile& mf); - void Initialize(); cmState::Snapshot StateSnapshot; + bool ReadListFile(const char* listfile, + bool noPolicyScope, + bool requireProjectCommand); + bool ReadListFileInternal(const char* filenametoread, bool noPolicyScope, bool requireProjectCommand); @@ -933,10 +903,6 @@ private: friend class cmMakeDepend; // make depend needs direct access // to the Sources array - void PrintStringVector(const char* s, const - std::vector<std::pair<std::string, bool> >& v) const; - void PrintStringVector(const char* s, - const std::vector<std::string>& v) const; void AddDefaultDefinitions(); typedef std::vector<cmFunctionBlocker*> FunctionBlockersType; @@ -961,7 +927,7 @@ private: bool CheckSystemVars; // stack of list files being read - std::deque<std::string> ListFileStack; + std::vector<std::string> ListFileStack; // stack of commands being invoked. struct CallStackEntry @@ -969,7 +935,7 @@ private: cmListFileContext const* Context; cmExecutionStatus* Status; }; - typedef std::deque<CallStackEntry> CallStackType; + typedef std::vector<CallStackEntry> CallStackType; CallStackType CallStack; friend class cmMakefileCall; @@ -1039,7 +1005,11 @@ private: // A map for fast output to input look up. #if defined(CMAKE_BUILD_WITH_CMAKE) +#ifdef CMake_HAVE_CXX11_UNORDERED_MAP + typedef std::unordered_map<std::string, cmSourceFile*> OutputToSourceMap; +#else typedef cmsys::hash_map<std::string, cmSourceFile*> OutputToSourceMap; +#endif #else typedef std::map<std::string, cmSourceFile*> OutputToSourceMap; #endif @@ -1068,6 +1038,8 @@ private: bool HaveCxxStandardAvailable(cmTarget const* target, const std::string& feature) const; + void CheckForUnusedVariables() const; + mutable bool SuppressWatches; }; diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index c001622..450f573 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -626,7 +626,7 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules install_name_dir = this->LocalGenerator->Convert(install_name_dir, cmLocalGenerator::NONE, - cmLocalGenerator::SHELL, false); + cmLocalGenerator::SHELL); vars.TargetInstallNameDir = install_name_dir.c_str(); } } diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index d28dde1..7b88bc7 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -24,6 +24,7 @@ #include "cmComputeLinkInformation.h" #include "cmCustomCommandGenerator.h" #include "cmGeneratorExpression.h" +#include "cmAlgorithms.h" #include "cmMakefileExecutableTargetGenerator.h" #include "cmMakefileLibraryTargetGenerator.h" @@ -225,7 +226,7 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() dependFileNameFull += "/depend.make"; *this->BuildFileStream << "# Include any dependencies generated for this target.\n" - << this->LocalGenerator->IncludeDirective << " " << root + << this->GlobalGenerator->IncludeDirective << " " << root << this->Convert(dependFileNameFull, cmLocalGenerator::HOME_OUTPUT, cmLocalGenerator::MAKERULE) @@ -236,7 +237,7 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() // Include the progress variables for the target. *this->BuildFileStream << "# Include the progress variables for this target.\n" - << this->LocalGenerator->IncludeDirective << " " << root + << this->GlobalGenerator->IncludeDirective << " " << root << this->Convert(this->ProgressFileNameFull, cmLocalGenerator::HOME_OUTPUT, cmLocalGenerator::MAKERULE) @@ -269,7 +270,7 @@ void cmMakefileTargetGenerator::WriteCommonCodeRules() // Include the flags for the target. *this->BuildFileStream << "# Include the compile flags for this target's objects.\n" - << this->LocalGenerator->IncludeDirective << " " << root + << this->GlobalGenerator->IncludeDirective << " " << root << this->Convert(this->FlagFileNameFull, cmLocalGenerator::HOME_OUTPUT, cmLocalGenerator::MAKERULE) @@ -681,6 +682,15 @@ cmMakefileTargetGenerator this->Convert(targetFullPathCompilePDB, cmLocalGenerator::START_OUTPUT, cmLocalGenerator::SHELL); + + if (this->LocalGenerator->IsMinGWMake() && + cmHasLiteralSuffix(targetOutPathCompilePDB, "\\")) + { + // mingw32-make incorrectly interprets 'a\ b c' as 'a b' and 'c' + // (but 'a\ b "c"' as 'a\', 'b', and 'c'!). Workaround this by + // avoiding a trailing backslash in the argument. + targetOutPathCompilePDB[targetOutPathCompilePDB.size()-1] = '/'; + } } cmLocalGenerator::RuleVariables vars; vars.RuleLauncher = "RULE_LAUNCH_COMPILE"; @@ -751,6 +761,20 @@ cmMakefileTargetGenerator source.GetFullPath(), workingDirectory, compileCommand); } + // Maybe insert an include-what-you-use runner. + if (!compileCommands.empty() && (lang == "C" || lang == "CXX")) + { + std::string const iwyu_prop = lang + "_INCLUDE_WHAT_YOU_USE"; + const char *iwyu = this->Target->GetProperty(iwyu_prop); + if (iwyu && *iwyu) + { + std::string run_iwyu = "$(CMAKE_COMMAND) -E __run_iwyu --iwyu="; + run_iwyu += this->LocalGenerator->EscapeForShell(iwyu); + run_iwyu += " -- "; + compileCommands.front().insert(0, run_iwyu); + } + } + // Expand placeholders in the commands. for(std::vector<std::string>::iterator i = compileCommands.begin(); i != compileCommands.end(); ++i) @@ -1108,8 +1132,8 @@ void cmMakefileTargetGenerator::WriteTargetDependRules() pi != this->MultipleOutputPairs.end(); ++pi) { *this->InfoFileStream - << " " << this->LocalGenerator->EscapeForCMake(pi->first) - << " " << this->LocalGenerator->EscapeForCMake(pi->second) + << " " << cmLocalGenerator::EscapeForCMake(pi->first) + << " " << cmLocalGenerator::EscapeForCMake(pi->second) << "\n"; } *this->InfoFileStream << " )\n\n"; diff --git a/Source/cmMakefileUtilityTargetGenerator.cxx b/Source/cmMakefileUtilityTargetGenerator.cxx index 617214f..25d929c 100644 --- a/Source/cmMakefileUtilityTargetGenerator.cxx +++ b/Source/cmMakefileUtilityTargetGenerator.cxx @@ -51,7 +51,7 @@ void cmMakefileUtilityTargetGenerator::WriteRuleFiles() // Include the progress variables for the target. *this->BuildFileStream << "# Include the progress variables for this target.\n" - << this->LocalGenerator->IncludeDirective << " " << root + << this->GlobalGenerator->IncludeDirective << " " << root << this->Convert(this->ProgressFileNameFull, cmLocalGenerator::HOME_OUTPUT, cmLocalGenerator::MAKERULE) diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 155a30e..bbf03ff 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -94,8 +94,6 @@ void cmNinjaNormalTargetGenerator::Generate() } else { - this->WriteLinkRule(false); // write rule without rspfile support - this->WriteLinkRule(true); // write rule with rspfile support this->WriteLinkStatement(); } } @@ -160,7 +158,9 @@ cmNinjaNormalTargetGenerator return this->TargetLinkLanguage + "_" + cmTarget::GetTargetTypeName(this->GetTarget()->GetType()) - + "_LINKER"; + + "_LINKER__" + + cmGlobalNinjaGenerator::EncodeRuleName(this->GetTarget()->GetName()) + ; } void @@ -169,8 +169,6 @@ cmNinjaNormalTargetGenerator { cmTarget::TargetType targetType = this->GetTarget()->GetType(); std::string ruleName = this->LanguageLinkerRule(); - if (useResponseFile) - ruleName += "_RSP_FILE"; // Select whether to use a response file for objects. std::string rspfile; @@ -202,7 +200,12 @@ cmNinjaNormalTargetGenerator responseFlag += rspfile; // build response file content - rspcontent = "$in_newline $LINK_PATH $LINK_LIBRARIES"; + if (this->GetGlobalGenerator()->IsGCCOnWindows()) { + rspcontent = "$in"; + } else { + rspcontent = "$in_newline"; + } + rspcontent += " $LINK_PATH $LINK_LIBRARIES"; vars.Objects = responseFlag.c_str(); vars.LinkLibraries = ""; } @@ -279,8 +282,7 @@ cmNinjaNormalTargetGenerator !this->GetTarget()->IsFrameworkOnApple()) { std::string cmakeCommand = this->GetLocalGenerator()->ConvertToOutputFormat( - this->GetMakefile()->GetRequiredDefinition("CMAKE_COMMAND"), - cmLocalGenerator::SHELL); + cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL); if (targetType == cmTarget::EXECUTABLE) this->GetGlobalGenerator()->AddRule("CMAKE_SYMLINK_EXECUTABLE", cmakeCommand + @@ -334,8 +336,7 @@ cmNinjaNormalTargetGenerator { std::string cmakeCommand = this->GetLocalGenerator()->ConvertToOutputFormat( - mf->GetRequiredDefinition("CMAKE_COMMAND"), - cmLocalGenerator::SHELL); + cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL); linkCmds.push_back(cmakeCommand + " -E remove $TARGET_FILE"); } // TODO: Use ARCHIVE_APPEND for archives over a certain size. @@ -524,8 +525,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() { vars["INSTALLNAME_DIR"] = localGen.Convert(install_dir, cmLocalGenerator::NONE, - cmLocalGenerator::SHELL, - false); + cmLocalGenerator::SHELL); } } } @@ -560,7 +560,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() vars["TARGET_PDB"] = base + suffix + dbg_suffix; } - if (mf->IsOn("CMAKE_COMPILER_IS_MINGW")) + if (this->GetGlobalGenerator()->IsGCCOnWindows()) { const std::string objPath = GetTarget()->GetSupportDirectory(); vars["OBJECT_DIR"] = ConvertToNinjaPath(objPath); @@ -656,6 +656,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() } // Write the build statement for this target. + bool usedResponseFile = false; globalGen.WriteBuild(this->GetBuildFileStream(), comment.str(), this->LanguageLinkerRule(), @@ -665,7 +666,9 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement() orderOnlyDeps, vars, rspfile, - commandLineLengthLimit); + commandLineLengthLimit, + &usedResponseFile); + this->WriteLinkRule(usedResponseFile); if (targetOutput != targetOutputReal && !target.IsFrameworkOnApple()) { diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index dfd3c04..879d6b7 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -97,6 +97,13 @@ std::string const& cmNinjaTargetGenerator::GetConfigName() const return this->LocalGenerator->GetConfigName(); } +std::string cmNinjaTargetGenerator::LanguageCompilerRule( + const std::string& lang) const +{ + return lang + "_COMPILER__" + + cmGlobalNinjaGenerator::EncodeRuleName(this->Target->GetName()); +} + // TODO: Picked up from cmMakefileTargetGenerator. Refactor it. const char* cmNinjaTargetGenerator::GetFeature(const std::string& feature) { @@ -175,7 +182,7 @@ cmNinjaTargetGenerator::ComputeFlagsForObject(cmSourceFile const* source, // needed by cmcldeps false, this->GetConfigName()); - if(cmGlobalNinjaGenerator::IsMinGW()) + if (this->GetGlobalGenerator()->IsGCCOnWindows()) cmSystemTools::ReplaceString(includeFlags, "\\", "/"); this->LocalGenerator->AppendFlags(languageFlags, includeFlags); @@ -451,6 +458,23 @@ cmNinjaTargetGenerator std::vector<std::string> compileCmds; cmSystemTools::ExpandListArgument(compileCmd, compileCmds); + // Maybe insert an include-what-you-use runner. + if (!compileCmds.empty() && (lang == "C" || lang == "CXX")) + { + std::string const iwyu_prop = lang + "_INCLUDE_WHAT_YOU_USE"; + const char *iwyu = this->Target->GetProperty(iwyu_prop); + if (iwyu && *iwyu) + { + std::string run_iwyu = + this->GetLocalGenerator()->ConvertToOutputFormat( + cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL); + run_iwyu += " -E __run_iwyu --iwyu="; + run_iwyu += this->GetLocalGenerator()->EscapeForShell(iwyu); + run_iwyu += " -- "; + compileCmds.front().insert(0, run_iwyu); + } + } + if (!compileCmds.empty()) { compileCmds.front().insert(0, cldeps); diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h index 5733fde..4e7d8b3 100644 --- a/Source/cmNinjaTargetGenerator.h +++ b/Source/cmNinjaTargetGenerator.h @@ -67,8 +67,7 @@ protected: std::string const& GetConfigName() const; - std::string LanguageCompilerRule(const std::string& lang) const - { return lang + "_COMPILER"; } + std::string LanguageCompilerRule(const std::string& lang) const; const char* GetFeature(const std::string& feature); bool GetFeatureAsBool(const std::string& feature); diff --git a/Source/cmPolicies.cxx b/Source/cmPolicies.cxx index e7678cb..f8d61db 100644 --- a/Source/cmPolicies.cxx +++ b/Source/cmPolicies.cxx @@ -1,7 +1,6 @@ #include "cmPolicies.h" #include "cmake.h" #include "cmMakefile.h" -#include "cmSourceFile.h" #include "cmVersion.h" #include "cmVersionMacros.h" #include "cmAlgorithms.h" @@ -10,421 +9,171 @@ #include <queue> #include <assert.h> -const char* cmPolicies::PolicyStatusNames[] = { - "OLD", "WARN", "NEW", "REQUIRED_IF_USED", "REQUIRED_ALWAYS" -}; - -class cmPolicy +static bool stringToId(const char* input, cmPolicies::PolicyID& pid) { -public: - cmPolicy(cmPolicies::PolicyID iD, - const char *idString, - const char *shortDescription, - unsigned int majorVersionIntroduced, - unsigned int minorVersionIntroduced, - unsigned int patchVersionIntroduced, - cmPolicies::PolicyStatus status) - { - if (!idString || !shortDescription) - { - cmSystemTools::Error("Attempt to define a policy without " - "all parameters being specified!"); - return; - } - this->ID = iD; - this->IDString = idString; - this->ShortDescription = shortDescription; - this->MajorVersionIntroduced = majorVersionIntroduced; - this->MinorVersionIntroduced = minorVersionIntroduced; - this->PatchVersionIntroduced = patchVersionIntroduced; - this->Status = status; - } - - std::string GetVersionString() - { - std::ostringstream v; - v << this->MajorVersionIntroduced << "." << this->MinorVersionIntroduced; - if(this->PatchVersionIntroduced > 0) - { - v << "." << this->PatchVersionIntroduced; - } - return v.str(); - } - - bool IsPolicyNewerThan(unsigned int majorV, - unsigned int minorV, - unsigned int patchV) - { - if (majorV < this->MajorVersionIntroduced) - { - return true; - } - if (majorV > this->MajorVersionIntroduced) - { - return false; - } - if (minorV < this->MinorVersionIntroduced) - { - return true; - } - if (minorV > this->MinorVersionIntroduced) + assert(input); + if (strlen(input) != 7) + { + return false; + } + if (!cmHasLiteralPrefix(input, "CMP")) + { + return false; + } + if (cmHasLiteralSuffix(input, "0000")) + { + pid = cmPolicies::CMP0000; + return true; + } + for (int i = 3; i < 7; ++i) + { + if (!isdigit(*(input + i))) { return false; } - return (patchV < this->PatchVersionIntroduced); - } - - cmPolicies::PolicyID ID; - std::string IDString; - std::string ShortDescription; - unsigned int MajorVersionIntroduced; - unsigned int MinorVersionIntroduced; - unsigned int PatchVersionIntroduced; - cmPolicies::PolicyStatus Status; -}; - -cmPolicies::cmPolicies() -{ - // define all the policies - this->DefinePolicy( - CMP0000, "CMP0000", - "A minimum required CMake version must be specified.", - 2,6,0, cmPolicies::WARN - ); - - this->DefinePolicy( - CMP0001, "CMP0001", - "CMAKE_BACKWARDS_COMPATIBILITY should no longer be used.", - 2,6,0, cmPolicies::WARN - ); - - this->DefinePolicy( - CMP0002, "CMP0002", - "Logical target names must be globally unique.", - 2,6,0, cmPolicies::WARN - ); - - this->DefinePolicy( - CMP0003, "CMP0003", - "Libraries linked via full path no longer produce linker search paths.", - 2,6,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0004, "CMP0004", - "Libraries linked may not have leading or trailing whitespace.", - 2,6,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0005, "CMP0005", - "Preprocessor definition values are now escaped automatically.", - 2,6,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0006, "CMP0006", - "Installing MACOSX_BUNDLE targets requires a BUNDLE DESTINATION.", - 2,6,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0007, "CMP0007", - "list command no longer ignores empty elements.", - 2,6,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0008, "CMP0008", - "Libraries linked by full-path must have a valid library file name.", - 2,6,1, cmPolicies::WARN); - - this->DefinePolicy( - CMP0009, "CMP0009", - "FILE GLOB_RECURSE calls should not follow symlinks by default.", - 2,6,2, cmPolicies::WARN); - - this->DefinePolicy( - CMP0010, "CMP0010", - "Bad variable reference syntax is an error.", - 2,6,3, cmPolicies::WARN); - - this->DefinePolicy( - CMP0011, "CMP0011", - "Included scripts do automatic cmake_policy PUSH and POP.", - 2,6,3, cmPolicies::WARN); - - this->DefinePolicy( - CMP0012, "CMP0012", - "if() recognizes numbers and boolean constants.", - 2,8,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0013, "CMP0013", - "Duplicate binary directories are not allowed.", - 2,8,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0014, "CMP0014", - "Input directories must have CMakeLists.txt.", - 2,8,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0015, "CMP0015", - "link_directories() treats paths relative to the source dir.", - 2,8,1, cmPolicies::WARN); - - this->DefinePolicy( - CMP0016, "CMP0016", - "target_link_libraries() reports error if its only argument " - "is not a target.", - 2,8,3, cmPolicies::WARN); - - this->DefinePolicy( - CMP0017, "CMP0017", - "Prefer files from the CMake module directory when including from there.", - 2,8,4, cmPolicies::WARN); - - this->DefinePolicy( - CMP0018, "CMP0018", - "Ignore CMAKE_SHARED_LIBRARY_<Lang>_FLAGS variable.", - 2,8,9, cmPolicies::WARN); - - this->DefinePolicy( - CMP0019, "CMP0019", - "Do not re-expand variables in include and link information.", - 2,8,11, cmPolicies::WARN); - - this->DefinePolicy( - CMP0020, "CMP0020", - "Automatically link Qt executables to qtmain target on Windows.", - 2,8,11, cmPolicies::WARN); - - this->DefinePolicy( - CMP0021, "CMP0021", - "Fatal error on relative paths in INCLUDE_DIRECTORIES target property.", - 2,8,12, cmPolicies::WARN); - - this->DefinePolicy( - CMP0022, "CMP0022", - "INTERFACE_LINK_LIBRARIES defines the link interface.", - 2,8,12, cmPolicies::WARN); - - this->DefinePolicy( - CMP0023, "CMP0023", - "Plain and keyword target_link_libraries signatures cannot be mixed.", - 2,8,12, cmPolicies::WARN); - - this->DefinePolicy( - CMP0024, "CMP0024", - "Disallow include export result.", - 3,0,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0025, "CMP0025", - "Compiler id for Apple Clang is now AppleClang.", - 3,0,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0026, "CMP0026", - "Disallow use of the LOCATION target property.", - 3,0,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0027, "CMP0027", - "Conditionally linked imported targets with missing include directories.", - 3,0,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0028, "CMP0028", - "Double colon in target name means ALIAS or IMPORTED target.", - 3,0,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0029, "CMP0029", - "The subdir_depends command should not be called.", - 3,0,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0030, "CMP0030", - "The use_mangled_mesa command should not be called.", - 3,0,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0031, "CMP0031", - "The load_command command should not be called.", - 3,0,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0032, "CMP0032", - "The output_required_files command should not be called.", - 3,0,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0033, "CMP0033", - "The export_library_dependencies command should not be called.", - 3,0,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0034, "CMP0034", - "The utility_source command should not be called.", - 3,0,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0035, "CMP0035", - "The variable_requires command should not be called.", - 3,0,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0036, "CMP0036", - "The build_name command should not be called.", - 3,0,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0037, "CMP0037", - "Target names should not be reserved and should match a validity pattern.", - 3,0,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0038, "CMP0038", - "Targets may not link directly to themselves.", - 3,0,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0039, "CMP0039", - "Utility targets may not have link dependencies.", - 3,0,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0040, "CMP0040", - "The target in the TARGET signature of add_custom_command() must exist.", - 3,0,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0041, "CMP0041", - "Error on relative include with generator expression.", - 3,0,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0042, "CMP0042", - "MACOSX_RPATH is enabled by default.", - 3,0,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0043, "CMP0043", - "Ignore COMPILE_DEFINITIONS_<Config> properties.", - 3,0,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0044, "CMP0044", - "Case sensitive <LANG>_COMPILER_ID generator expressions.", - 3,0,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0045, "CMP0045", - "Error on non-existent target in get_target_property.", - 3,0,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0046, "CMP0046", - "Error on non-existent dependency in add_dependencies.", - 3,0,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0047, "CMP0047", - "Use QCC compiler id for the qcc drivers on QNX.", - 3,0,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0048, "CMP0048", - "project() command manages VERSION variables.", - 3,0,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0049, "CMP0049", - "Do not expand variables in target source entries.", - 3,0,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0050, "CMP0050", - "Disallow add_custom_command SOURCE signatures.", - 3,0,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0051, "CMP0051", - "List TARGET_OBJECTS in SOURCES target property.", - 3,1,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0052, "CMP0052", - "Reject source and build dirs in installed " - "INTERFACE_INCLUDE_DIRECTORIES.", - 3,1,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0053, "CMP0053", - "Simplify variable reference and escape sequence evaluation.", - 3,1,0, cmPolicies::WARN); - - this->DefinePolicy( - CMP0054, "CMP0054", - "Only interpret if() arguments as variables or keywords when unquoted.", - 3,1,0, cmPolicies::WARN); + } + long id; + if (!cmSystemTools::StringToLong(input + 3, &id)) + { + return false; + } + if (id >= cmPolicies::CMPCOUNT) + { + return false; + } + pid = cmPolicies::PolicyID(id); + return true; +} - this->DefinePolicy( - CMP0055, "CMP0055", - "Strict checking for break() command.", - 3,2,0, cmPolicies::WARN); +#define CM_SELECT_ID_VERSION(F, A1, A2, A3, A4, A5, A6) F(A1, A3, A4, A5) +#define CM_FOR_EACH_POLICY_ID_VERSION(POLICY) \ + CM_FOR_EACH_POLICY_TABLE(POLICY, CM_SELECT_ID_VERSION) - this->DefinePolicy( - CMP0056, "CMP0056", - "Honor link flags in try_compile() source-file signature.", - 3,2,0, cmPolicies::WARN); +#define CM_SELECT_ID_DOC(F, A1, A2, A3, A4, A5, A6) F(A1, A2) +#define CM_FOR_EACH_POLICY_ID_DOC(POLICY) \ + CM_FOR_EACH_POLICY_TABLE(POLICY, CM_SELECT_ID_DOC) - this->DefinePolicy( - CMP0057, "CMP0057", - "Disallow multiple MAIN_DEPENDENCY specifications for the same file.", - 3,3,0, cmPolicies::WARN); +static const char* idToString(cmPolicies::PolicyID id) +{ + switch(id) + { +#define POLICY_CASE(ID) \ + case cmPolicies::ID: \ + return #ID; + CM_FOR_EACH_POLICY_ID(POLICY_CASE) +#undef POLICY_CASE + case cmPolicies::CMPCOUNT: + return 0; + } + return 0; +} - this->DefinePolicy( - CMP0058, "CMP0058", - "Ninja requires custom command byproducts to be explicit.", - 3,3,0, cmPolicies::WARN); +static const char* idToVersion(cmPolicies::PolicyID id) +{ + switch(id) + { +#define POLICY_CASE(ID, V_MAJOR, V_MINOR, V_PATCH) \ + case cmPolicies::ID: \ + return #V_MAJOR "." #V_MINOR "." #V_PATCH; + CM_FOR_EACH_POLICY_ID_VERSION(POLICY_CASE) +#undef POLICY_CASE + case cmPolicies::CMPCOUNT: + return 0; + } + return 0; +} - this->DefinePolicy( - CMP0059, "CMP0059", - "Do no treat DEFINITIONS as a built-in directory property.", - 3,3,0, cmPolicies::WARN); +static bool isPolicyNewerThan(cmPolicies::PolicyID id, + unsigned int majorV, + unsigned int minorV, + unsigned int patchV) +{ + switch(id) + { +#define POLICY_CASE(ID, V_MAJOR, V_MINOR, V_PATCH) \ + case cmPolicies::ID: \ + return (majorV < V_MAJOR || \ + (majorV == V_MAJOR && \ + minorV + 1 < V_MINOR + 1) || \ + (majorV == V_MAJOR && \ + minorV == V_MINOR && \ + patchV + 1 < V_PATCH + 1)); + CM_FOR_EACH_POLICY_ID_VERSION(POLICY_CASE) +#undef POLICY_CASE + case cmPolicies::CMPCOUNT: + return false; + } + return false; +} - this->DefinePolicy( - CMP0060, "CMP0060", - "Link libraries by full path even in implicit directories.", - 3,3,0, cmPolicies::WARN); +const char* idToShortDescription(cmPolicies::PolicyID id) +{ + switch(id) + { +#define POLICY_CASE(ID, SHORT_DESCRIPTION) \ + case cmPolicies::ID: \ + return SHORT_DESCRIPTION; + CM_FOR_EACH_POLICY_ID_DOC(POLICY_CASE) +#undef POLICY_CASE + case cmPolicies::CMPCOUNT: + return 0; + } + return 0; } -cmPolicies::~cmPolicies() +//---------------------------------------------------------------------------- +static void DiagnoseAncientPolicies( + std::vector<cmPolicies::PolicyID> const& ancient, + unsigned int majorVer, + unsigned int minorVer, + unsigned int patchVer, + cmMakefile* mf) { - cmDeleteAll(this->Policies); + std::ostringstream e; + e << "The project requests behavior compatible with CMake version \"" + << majorVer << "." << minorVer << "." << patchVer + << "\", which requires the OLD behavior for some policies:\n"; + for(std::vector<cmPolicies::PolicyID>::const_iterator + i = ancient.begin(); i != ancient.end(); ++i) + { + e << " " << idToString(*i) << ": " << idToShortDescription(*i) << "\n"; + } + e << "However, this version of CMake no longer supports the OLD " + << "behavior for these policies. " + << "Please either update your CMakeLists.txt files to conform to " + << "the new behavior or use an older version of CMake that still " + << "supports the old behavior."; + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); } -void cmPolicies::DefinePolicy(cmPolicies::PolicyID iD, - const char *idString, - const char *shortDescription, - unsigned int majorVersionIntroduced, - unsigned int minorVersionIntroduced, - unsigned int patchVersionIntroduced, - cmPolicies::PolicyStatus status) +//---------------------------------------------------------------------------- +static bool GetPolicyDefault(cmMakefile* mf, std::string const& policy, + cmPolicies::PolicyStatus* defaultSetting) { - // a policy must be unique and can only be defined once - if (this->Policies.find(iD) != this->Policies.end()) + std::string defaultVar = "CMAKE_POLICY_DEFAULT_" + policy; + std::string defaultValue = mf->GetSafeDefinition(defaultVar); + if(defaultValue == "NEW") + { + *defaultSetting = cmPolicies::NEW; + } + else if(defaultValue == "OLD") + { + *defaultSetting = cmPolicies::OLD; + } + else if(defaultValue == "") + { + *defaultSetting = cmPolicies::WARN; + } + else { - cmSystemTools::Error("Attempt to redefine a CMake policy for policy " - "ID ", this->GetPolicyIDString(iD).c_str()); - return; + std::ostringstream e; + e << defaultVar << " has value \"" << defaultValue + << "\" but must be \"OLD\", \"NEW\", or \"\" (empty)."; + mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + return false; } - this->Policies[iD] = new cmPolicy(iD, idString, - shortDescription, - majorVersionIntroduced, - minorVersionIntroduced, - patchVersionIntroduced, - status); - this->PolicyStringMap[idString] = iD; + return true; } //---------------------------------------------------------------------------- @@ -489,20 +238,20 @@ bool cmPolicies::ApplyPolicyVersion(cmMakefile *mf, // now loop over all the policies and set them as appropriate std::vector<cmPolicies::PolicyID> ancientPolicies; - for(std::map<cmPolicies::PolicyID,cmPolicy *>::iterator i - = this->Policies.begin(); i != this->Policies.end(); ++i) + for(PolicyID pid = cmPolicies::CMP0000; + pid != cmPolicies::CMPCOUNT; pid = PolicyID(pid+1)) { - if (i->second->IsPolicyNewerThan(majorVer,minorVer,patchVer)) + if (isPolicyNewerThan(pid, majorVer, minorVer, patchVer)) { - if(i->second->Status == cmPolicies::REQUIRED_ALWAYS) + if(cmPolicies::GetPolicyStatus(pid) == cmPolicies::REQUIRED_ALWAYS) { - ancientPolicies.push_back(i->first); + ancientPolicies.push_back(pid); } else { cmPolicies::PolicyStatus status = cmPolicies::WARN; - if(!this->GetPolicyDefault(mf, i->second->IDString, &status) || - !mf->SetPolicy(i->second->ID, status)) + if(!GetPolicyDefault(mf, idToString(pid), &status) || + !mf->SetPolicy(pid, status)) { return false; } @@ -510,7 +259,7 @@ bool cmPolicies::ApplyPolicyVersion(cmMakefile *mf, } else { - if (!mf->SetPolicy(i->second->ID, cmPolicies::NEW)) + if (!mf->SetPolicy(pid, cmPolicies::NEW)) { return false; } @@ -520,8 +269,8 @@ bool cmPolicies::ApplyPolicyVersion(cmMakefile *mf, // Make sure the project does not use any ancient policies. if(!ancientPolicies.empty()) { - this->DiagnoseAncientPolicies(ancientPolicies, - majorVer, minorVer, patchVer, mf); + DiagnoseAncientPolicies(ancientPolicies, + majorVer, minorVer, patchVer, mf); cmSystemTools::SetFatalErrorOccured(); return false; } @@ -529,81 +278,19 @@ bool cmPolicies::ApplyPolicyVersion(cmMakefile *mf, return true; } -//---------------------------------------------------------------------------- -bool cmPolicies::GetPolicyDefault(cmMakefile* mf, std::string const& policy, - cmPolicies::PolicyStatus* defaultSetting) -{ - std::string defaultVar = "CMAKE_POLICY_DEFAULT_" + policy; - std::string defaultValue = mf->GetSafeDefinition(defaultVar); - if(defaultValue == "NEW") - { - *defaultSetting = cmPolicies::NEW; - } - else if(defaultValue == "OLD") - { - *defaultSetting = cmPolicies::OLD; - } - else if(defaultValue == "") - { - *defaultSetting = cmPolicies::WARN; - } - else - { - std::ostringstream e; - e << defaultVar << " has value \"" << defaultValue - << "\" but must be \"OLD\", \"NEW\", or \"\" (empty)."; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); - return false; - } - - return true; -} - bool cmPolicies::GetPolicyID(const char *id, cmPolicies::PolicyID &pid) { - if (!id || strlen(id) < 1) - { - return false; - } - std::map<std::string,cmPolicies::PolicyID>::iterator pos = - this->PolicyStringMap.find(id); - if (pos == this->PolicyStringMap.end()) - { - return false; - } - pid = pos->second; - return true; -} - -std::string cmPolicies::GetPolicyIDString(cmPolicies::PolicyID pid) -{ - std::map<cmPolicies::PolicyID,cmPolicy *>::iterator pos = - this->Policies.find(pid); - if (pos == this->Policies.end()) - { - return ""; - } - return pos->second->IDString; + return stringToId(id, pid); } - ///! return a warning string for a given policy std::string cmPolicies::GetPolicyWarning(cmPolicies::PolicyID id) { - std::map<cmPolicies::PolicyID,cmPolicy *>::iterator pos = - this->Policies.find(id); - if (pos == this->Policies.end()) - { - cmSystemTools::Error( - "Request for warning text for undefined policy!"); - return "Request for warning text for undefined policy!"; - } - std::ostringstream msg; msg << - "Policy " << pos->second->IDString << " is not set: " - "" << pos->second->ShortDescription << " " - "Run \"cmake --help-policy " << pos->second->IDString << "\" for " + "Policy " << idToString(id) << " is not set: " + "" << idToShortDescription(id) << " " + "Run \"cmake --help-policy " << idToString(id) << "\" for " "policy details. " "Use the cmake_policy command to set the policy " "and suppress this warning."; @@ -614,26 +301,17 @@ std::string cmPolicies::GetPolicyWarning(cmPolicies::PolicyID id) ///! return an error string for when a required policy is unspecified std::string cmPolicies::GetRequiredPolicyError(cmPolicies::PolicyID id) { - std::map<cmPolicies::PolicyID,cmPolicy *>::iterator pos = - this->Policies.find(id); - if (pos == this->Policies.end()) - { - cmSystemTools::Error( - "Request for error text for undefined policy!"); - return "Request for error text for undefined policy!"; - } - std::ostringstream error; error << - "Policy " << pos->second->IDString << " is not set to NEW: " - "" << pos->second->ShortDescription << " " - "Run \"cmake --help-policy " << pos->second->IDString << "\" for " + "Policy " << idToString(id) << " is not set to NEW: " + "" << idToShortDescription(id) << " " + "Run \"cmake --help-policy " << idToString(id) << "\" for " "policy details. " "CMake now requires this policy to be set to NEW by the project. " "The policy may be set explicitly using the code\n" - " cmake_policy(SET " << pos->second->IDString << " NEW)\n" + " cmake_policy(SET " << idToString(id) << " NEW)\n" "or by upgrading all policies with the code\n" - " cmake_policy(VERSION " << pos->second->GetVersionString() << + " cmake_policy(VERSION " << idToVersion(id) << ") # or later\n" "Run \"cmake --help-command cmake_policy\" for more information."; return error.str(); @@ -641,30 +319,21 @@ std::string cmPolicies::GetRequiredPolicyError(cmPolicies::PolicyID id) ///! Get the default status for a policy cmPolicies::PolicyStatus -cmPolicies::GetPolicyStatus(cmPolicies::PolicyID id) +cmPolicies::GetPolicyStatus(cmPolicies::PolicyID) { - // if the policy is not know then what? - std::map<cmPolicies::PolicyID,cmPolicy *>::iterator pos = - this->Policies.find(id); - if (pos == this->Policies.end()) - { - // TODO is this right? - return cmPolicies::WARN; - } - - return pos->second->Status; + return cmPolicies::WARN; } //---------------------------------------------------------------------------- std::string cmPolicies::GetRequiredAlwaysPolicyError(cmPolicies::PolicyID id) { - std::string pid = this->GetPolicyIDString(id); + std::string pid = idToString(id); std::ostringstream e; e << "Policy " << pid << " may not be set to OLD behavior because this " << "version of CMake no longer supports it. " << "The policy was introduced in " - << "CMake version " << this->Policies[id]->GetVersionString() + << "CMake version " << idToVersion(id) << ", and use of NEW behavior is now required." << "\n" << "Please either update your CMakeLists.txt files to conform to " @@ -674,28 +343,51 @@ cmPolicies::GetRequiredAlwaysPolicyError(cmPolicies::PolicyID id) return e.str(); } -//---------------------------------------------------------------------------- -void -cmPolicies::DiagnoseAncientPolicies(std::vector<PolicyID> const& ancient, - unsigned int majorVer, - unsigned int minorVer, - unsigned int patchVer, - cmMakefile* mf) +cmPolicies::PolicyMap::PolicyMap() { - std::ostringstream e; - e << "The project requests behavior compatible with CMake version \"" - << majorVer << "." << minorVer << "." << patchVer - << "\", which requires the OLD behavior for some policies:\n"; - for(std::vector<PolicyID>::const_iterator - i = ancient.begin(); i != ancient.end(); ++i) + this->UNDEFINED.set(); +} + +cmPolicies::PolicyStatus +cmPolicies::PolicyMap::Get(cmPolicies::PolicyID id) const +{ + PolicyStatus status = cmPolicies::WARN; + + if (this->OLD[id]) { - cmPolicy const* policy = this->Policies[*i]; - e << " " << policy->IDString << ": " << policy->ShortDescription << "\n"; + status = cmPolicies::OLD; } - e << "However, this version of CMake no longer supports the OLD " - << "behavior for these policies. " - << "Please either update your CMakeLists.txt files to conform to " - << "the new behavior or use an older version of CMake that still " - << "supports the old behavior."; - mf->IssueMessage(cmake::FATAL_ERROR, e.str()); + else if (this->NEW[id]) + { + status = cmPolicies::NEW; + } + else if (this->REQUIRED_ALWAYS[id]) + { + status = cmPolicies::REQUIRED_ALWAYS; + } + else if (this->REQUIRED_IF_USED[id]) + { + status = cmPolicies::REQUIRED_IF_USED; + } + return status; +} + +void cmPolicies::PolicyMap::Set(cmPolicies::PolicyID id, + cmPolicies::PolicyStatus status) +{ + this->UNDEFINED.reset(id); + this->OLD[id] = (status == cmPolicies::OLD); + this->NEW[id] = (status == cmPolicies::NEW); + this->REQUIRED_ALWAYS[id] = (status == cmPolicies::REQUIRED_ALWAYS); + this->REQUIRED_IF_USED[id] = (status == cmPolicies::REQUIRED_IF_USED); +} + +bool cmPolicies::PolicyMap::IsDefined(cmPolicies::PolicyID id) const +{ + return !this->UNDEFINED[id]; +} + +bool cmPolicies::PolicyMap::IsEmpty() const +{ + return !this->UNDEFINED.none(); } diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index 1d108c1..00d857a 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -14,10 +14,216 @@ #include "cmCustomCommand.h" -class cmake; +#include <bitset> + class cmMakefile; class cmPolicy; +#define CM_FOR_EACH_POLICY_TABLE(POLICY, SELECT) \ + SELECT(POLICY, CMP0000, \ + "A minimum required CMake version must be specified.", \ + 2, 6, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0001, \ + "CMAKE_BACKWARDS_COMPATIBILITY should no longer be used.", \ + 2, 6, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0002, \ + "Logical target names must be globally unique.", \ + 2, 6, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0003, \ + "Libraries linked via full path no longer produce linker search paths.", \ + 2, 6, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0004, \ + "Libraries linked may not have leading or trailing whitespace.", \ + 2, 6, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0005, \ + "Preprocessor definition values are now escaped automatically.", \ + 2, 6, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0006, \ + "Installing MACOSX_BUNDLE targets requires a BUNDLE DESTINATION.", \ + 2, 6, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0007, \ + "list command no longer ignores empty elements.", \ + 2, 6, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0008, \ + "Libraries linked by full-path must have a valid library file name.", \ + 2, 6, 1, cmPolicies::WARN) \ + SELECT(POLICY, CMP0009, \ + "FILE GLOB_RECURSE calls should not follow symlinks by default.", \ + 2, 6, 2, cmPolicies::WARN) \ + SELECT(POLICY, CMP0010, \ + "Bad variable reference syntax is an error.", \ + 2, 6, 3, cmPolicies::WARN) \ + SELECT(POLICY, CMP0011, \ + "Included scripts do automatic cmake_policy PUSH and POP.", \ + 2, 6, 3, cmPolicies::WARN) \ + SELECT(POLICY, CMP0012, \ + "if() recognizes numbers and boolean constants.", \ + 2, 8, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0013, \ + "Duplicate binary directories are not allowed.", \ + 2, 8, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0014, \ + "Input directories must have CMakeLists.txt.", \ + 2, 8, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0015, \ + "link_directories() treats paths relative to the source dir.", \ + 2, 8, 1, cmPolicies::WARN) \ + SELECT(POLICY, CMP0016, \ + "target_link_libraries() reports error if its only argument " \ + "is not a target.", \ + 2, 8, 3, cmPolicies::WARN) \ + SELECT(POLICY, CMP0017, \ + "Prefer files from the CMake module directory when including from " \ + "there.", \ + 2, 8, 4, cmPolicies::WARN) \ + SELECT(POLICY, CMP0018, \ + "Ignore CMAKE_SHARED_LIBRARY_<Lang>_FLAGS variable.", \ + 2, 8, 9, cmPolicies::WARN) \ + SELECT(POLICY, CMP0019, \ + "Do not re-expand variables in include and link information.", \ + 2, 8, 11, cmPolicies::WARN) \ + SELECT(POLICY, CMP0020, \ + "Automatically link Qt executables to qtmain target on Windows.", \ + 2, 8, 11, cmPolicies::WARN) \ + SELECT(POLICY, CMP0021, \ + "Fatal error on relative paths in INCLUDE_DIRECTORIES target property.", \ + 2, 8, 12, cmPolicies::WARN) \ + SELECT(POLICY, CMP0022, \ + "INTERFACE_LINK_LIBRARIES defines the link interface.", \ + 2, 8, 12, cmPolicies::WARN) \ + SELECT(POLICY, CMP0023, \ + "Plain and keyword target_link_libraries signatures cannot be mixed.", \ + 2, 8, 12, cmPolicies::WARN) \ + SELECT(POLICY, CMP0024, \ + "Disallow include export result.", \ + 3, 0, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0025, \ + "Compiler id for Apple Clang is now AppleClang.", \ + 3, 0, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0026, \ + "Disallow use of the LOCATION target property.", \ + 3, 0, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0027, \ + "Conditionally linked imported targets with missing include " \ + "directories.", \ + 3, 0, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0028, \ + "Double colon in target name means ALIAS or IMPORTED target.", \ + 3, 0, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0029, \ + "The subdir_depends command should not be called.", \ + 3, 0, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0030, \ + "The use_mangled_mesa command should not be called.", \ + 3, 0, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0031, \ + "The load_command command should not be called.", \ + 3, 0, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0032, \ + "The output_required_files command should not be called.", \ + 3, 0, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0033, \ + "The export_library_dependencies command should not be called.", \ + 3, 0, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0034, \ + "The utility_source command should not be called.", \ + 3, 0, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0035, \ + "The variable_requires command should not be called.", \ + 3, 0, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0036, \ + "The build_name command should not be called.", \ + 3, 0, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0037, \ + "Target names should not be reserved and should match a validity " \ + "pattern.", \ + 3, 0, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0038, \ + "Targets may not link directly to themselves.", \ + 3, 0, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0039, \ + "Utility targets may not have link dependencies.", \ + 3, 0, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0040, \ + "The target in the TARGET signature of add_custom_command() must " \ + "exist.", \ + 3, 0, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0041, \ + "Error on relative include with generator expression.", \ + 3, 0, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0042, \ + "MACOSX_RPATH is enabled by default.", \ + 3, 0, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0043, \ + "Ignore COMPILE_DEFINITIONS_<Config> properties.", \ + 3, 0, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0044, \ + "Case sensitive <LANG>_COMPILER_ID generator expressions.", \ + 3, 0, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0045, \ + "Error on non-existent target in get_target_property.", \ + 3, 0, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0046, \ + "Error on non-existent dependency in add_dependencies.", \ + 3, 0, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0047, \ + "Use QCC compiler id for the qcc drivers on QNX.", \ + 3, 0, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0048, \ + "project() command manages VERSION variables.", \ + 3, 0, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0049, \ + "Do not expand variables in target source entries.", \ + 3, 0, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0050, \ + "Disallow add_custom_command SOURCE signatures.", \ + 3, 0, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0051, \ + "List TARGET_OBJECTS in SOURCES target property.", \ + 3, 1, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0052, \ + "Reject source and build dirs in installed " \ + "INTERFACE_INCLUDE_DIRECTORIES.", \ + 3, 1, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0053, \ + "Simplify variable reference and escape sequence evaluation.", \ + 3, 1, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0054, \ + "Only interpret if() arguments as variables or keywords when unquoted.", \ + 3, 1, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0055, \ + "Strict checking for break() command.", \ + 3, 2, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0056, \ + "Honor link flags in try_compile() source-file signature.", \ + 3, 2, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0057, \ + "Support new IN_LIST if() operator.", \ + 3, 3, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0058, \ + "Ninja requires custom command byproducts to be explicit.", \ + 3, 3, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0059, \ + "Do no treat DEFINITIONS as a built-in directory property.", \ + 3, 3, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0060, \ + "Link libraries by full path even in implicit directories.", \ + 3, 3, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0061, \ + "CTest does not by default tell make to ignore errors (-i).", \ + 3, 3, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0062, \ + "Disallow install() of export() result.", \ + 3, 3, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0063, \ + "Honor visibility properties for all target types.", \ + 3, 3, 0, cmPolicies::WARN) + +#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) +#define CM_FOR_EACH_POLICY_ID(POLICY) \ + CM_FOR_EACH_POLICY_TABLE(POLICY, CM_SELECT_ID) + + /** \class cmPolicies * \brief Handles changes in CMake behavior and policies * @@ -28,9 +234,6 @@ class cmPolicy; class cmPolicies { public: - cmPolicies(); - ~cmPolicies(); - /// Status of a policy enum PolicyStatus { OLD, ///< Use old behavior @@ -41,84 +244,13 @@ public: REQUIRED_IF_USED, REQUIRED_ALWAYS ///< Issue an error unless user sets policy status to NEW. }; - static const char* PolicyStatusNames[]; /// Policy identifiers enum PolicyID { - CMP0000, ///< Policy version specification - CMP0001, ///< Ignore old compatibility variable - CMP0002, ///< Target names must be unique - CMP0003, ///< Linking does not include extra -L paths - CMP0004, ///< Libraries linked may not have leading or trailing whitespace - CMP0005, ///< Definition value escaping - CMP0006, ///< BUNDLE install rules needed for MACOSX_BUNDLE targets - CMP0007, ///< list command handling of empty elements - CMP0008, ///< Full-path libraries must be a valid library file name - CMP0009, ///< GLOB_RECURSE should not follow symlinks by default - CMP0010, ///< Bad variable reference syntax is an error - CMP0011, ///< Strong policy scope for include and find_package - CMP0012, ///< Recognize numbers and boolean constants in if() - CMP0013, ///< Duplicate binary directories not allowed - CMP0014, ///< Input directories must have CMakeLists.txt - CMP0015, ///< link_directories() treats paths relative to source dir - /// target_link_libraries() fails if only argument is not a target - CMP0016, - CMP0017, ///< Prefer files in CMAKE_ROOT when including from CMAKE_ROOT - CMP0018, ///< Ignore language flags for shared libs, and adhere to - /// POSITION_INDEPENDENT_CODE property and *_COMPILE_OPTIONS_PI{E,C} - /// instead. - CMP0019, ///< No variable re-expansion in include and link info - CMP0020, ///< Automatically link Qt executables to qtmain target - CMP0021, ///< Fatal error on relative paths in INCLUDE_DIRECTORIES - /// target property - CMP0022, ///< INTERFACE_LINK_LIBRARIES defines the link interface - CMP0023, ///< Disallow mixing keyword and plain tll signatures - CMP0024, ///< Disallow including export() result. - CMP0025, ///< Compiler id for Apple Clang is now AppleClang - CMP0026, ///< Disallow use of the LOCATION target property. - CMP0027, ///< Conditionally linked imported targets with missing include - /// directories. - CMP0028, ///< Double colon in target name means ALIAS or IMPORTED target. - CMP0029, ///< Disallow command: subdir_depends - CMP0030, ///< Disallow command: use_mangled_mesa - CMP0031, ///< Disallow command: load_command - CMP0032, ///< Disallow command: output_required_files - CMP0033, ///< Disallow command: export_library_dependencies - CMP0034, ///< Disallow command: utility_source - CMP0035, ///< Disallow command: variable_requires - CMP0036, ///< Disallow command: build_name - CMP0037, ///< Target names should not be reserved and - /// should match a validity pattern. - CMP0038, ///< Targets may not link directly to themselves - CMP0039, ///< Utility targets may not have link dependencies - CMP0040, ///< The target in the TARGET signature of - /// add_custom_command() must exist. - CMP0041, ///< Error on relative include with generator expression - CMP0042, ///< Enable MACOSX_RPATH by default - CMP0043, ///< Ignore COMPILE_DEFINITIONS_<Config> properties - CMP0044, ///< Case sensitive <LANG>_COMPILER_ID generator expressions - CMP0045, ///< Error on non-existent target in get_target_property - CMP0046, ///< Error on non-existent dependency in add_dependencies - CMP0047, ///< Use QCC compiler id for the qcc drivers on QNX. - CMP0048, ///< project() command manages VERSION variables - CMP0049, ///< Do not expand variables in target source entries - CMP0050, ///< Disallow add_custom_command SOURCE signatures - CMP0051, ///< List TARGET_OBJECTS in SOURCES target property - CMP0052, ///< Reject source and build dirs in installed - /// INTERFACE_INCLUDE_DIRECTORIES - - CMP0053, ///< Simplify variable reference and escape sequence evaluation - CMP0054, ///< Only interpret if() arguments as variables - /// or keywords when unquoted. - CMP0055, ///< Strict checking for break() command. - CMP0056, ///< Honor link flags in try_compile() source-file signature. - CMP0057, ///< Disallow multiple MAIN_DEPENDENCY specifications - /// for the same file. - CMP0058, ///< Ninja requires custom command byproducts to be explicit - CMP0059, ///< Do not treat ``DEFINITIONS`` as a built-in directory - /// property. - CMP0060, ///< Link libraries by full path even in implicit directories. +#define POLICY_ENUM(POLICY_ID) POLICY_ID, + CM_FOR_EACH_POLICY_ID(POLICY_ENUM) +#undef POLICY_ENUM /** \brief Always the last entry. * @@ -129,48 +261,39 @@ public: }; ///! convert a string policy ID into a number - bool GetPolicyID(const char *id, /* out */ cmPolicies::PolicyID &pid); - std::string GetPolicyIDString(cmPolicies::PolicyID pid); + static bool GetPolicyID(const char *id, /* out */ cmPolicies::PolicyID &pid); ///! Get the default status for a policy - cmPolicies::PolicyStatus GetPolicyStatus(cmPolicies::PolicyID id); - - ///! Define a Policy for CMake - void DefinePolicy(cmPolicies::PolicyID id, - const char *stringID, - const char *shortDescription, - unsigned int majorVersionIntroduced, - unsigned int minorVersionIntroduced, - unsigned int patchVersionIntroduced, - cmPolicies::PolicyStatus status); + static cmPolicies::PolicyStatus GetPolicyStatus(cmPolicies::PolicyID id); ///! Set a policy level for this listfile - bool ApplyPolicyVersion(cmMakefile *mf, const char *version); + static bool ApplyPolicyVersion(cmMakefile *mf, const char *version); ///! return a warning string for a given policy - std::string GetPolicyWarning(cmPolicies::PolicyID id); + static std::string GetPolicyWarning(cmPolicies::PolicyID id); ///! return an error string for when a required policy is unspecified - std::string GetRequiredPolicyError(cmPolicies::PolicyID id); + static std::string GetRequiredPolicyError(cmPolicies::PolicyID id); ///! return an error string for when a required policy is unspecified - std::string GetRequiredAlwaysPolicyError(cmPolicies::PolicyID id); + static std::string GetRequiredAlwaysPolicyError(cmPolicies::PolicyID id); /** Represent a set of policy values. */ - typedef std::map<PolicyID, PolicyStatus> PolicyMap; + struct PolicyMap + { + PolicyMap(); + PolicyStatus Get(PolicyID id) const; + void Set(PolicyID id, PolicyStatus status); + bool IsDefined(PolicyID id) const; + bool IsEmpty() const; private: - // might have to make these internal for VS6 not sure yet - std::map<PolicyID,cmPolicy *> Policies; - std::map<std::string,PolicyID> PolicyStringMap; - - void DiagnoseAncientPolicies(std::vector<PolicyID> const& ancient, - unsigned int majorVer, unsigned int minorVer, - unsigned int patchVer, cmMakefile* mf); - - bool GetPolicyDefault(cmMakefile* mf, std::string const& policy, - cmPolicies::PolicyStatus* defaultStatus); - + std::bitset<cmPolicies::CMPCOUNT> UNDEFINED; + std::bitset<cmPolicies::CMPCOUNT> OLD; + std::bitset<cmPolicies::CMPCOUNT> NEW; + std::bitset<cmPolicies::CMPCOUNT> REQUIRED_IF_USED; + std::bitset<cmPolicies::CMPCOUNT> REQUIRED_ALWAYS; + }; }; #endif diff --git a/Source/cmProjectCommand.cxx b/Source/cmProjectCommand.cxx index afacc1b..176cb0d 100644 --- a/Source/cmProjectCommand.cxx +++ b/Source/cmProjectCommand.cxx @@ -53,7 +53,7 @@ bool cmProjectCommand // CMAKE_PROJECT_NAME will match PROJECT_NAME, and cmake --build // will work. if(!this->Makefile->GetDefinition("CMAKE_PROJECT_NAME") - || (this->Makefile->GetLocalGenerator()->GetParent() == 0) ) + || (this->Makefile->GetLocalGenerator()->IsRootMakefile())) { this->Makefile->AddDefinition("CMAKE_PROJECT_NAME", args[0].c_str()); this->Makefile->AddCacheDefinition @@ -216,8 +216,7 @@ bool cmProjectCommand if(!vw.empty()) { std::ostringstream w; - w << (this->Makefile->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0048)) + w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0048) << "\nThe following variable(s) would be set to empty:" << vw; this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, w.str()); } diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGenerators.cxx index 91b2b27..cbb06cd 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGenerators.cxx @@ -20,7 +20,7 @@ #include "cmAlgorithms.h" #if defined(_WIN32) && !defined(__CYGWIN__) -# include "cmLocalVisualStudioGenerator.h" +# include "cmGlobalVisualStudioGenerator.h" #endif #include <sys/stat.h> @@ -320,7 +320,7 @@ bool cmQtAutoGenerators::InitializeAutogenTarget(cmTarget* target) std::string targetDir = getAutogenTargetDir(target); cmCustomCommandLine currentLine; - currentLine.push_back(makefile->GetSafeDefinition("CMAKE_COMMAND")); + currentLine.push_back(cmSystemTools::GetCMakeCommand()); currentLine.push_back("-E"); currentLine.push_back("cmake_autogen"); currentLine.push_back(targetDir); @@ -372,13 +372,13 @@ bool cmQtAutoGenerators::InitializeAutogenTarget(cmTarget* target) cmGlobalGenerator* gg = localGen->GetGlobalGenerator(); if(gg->GetName().find("Visual Studio") != std::string::npos) { - cmLocalVisualStudioGenerator* vslg = - static_cast<cmLocalVisualStudioGenerator*>(localGen); + cmGlobalVisualStudioGenerator* vsgg = + static_cast<cmGlobalVisualStudioGenerator*>(gg); // Under VS >= 7 use a PRE_BUILD event instead of a separate target to // reduce the number of targets loaded into the IDE. // This also works around a VS 11 bug that may skip updating the target: // https://connect.microsoft.com/VisualStudio/feedback/details/769495 - usePRE_BUILD = vslg->GetVersion() >= cmLocalVisualStudioGenerator::VS7; + usePRE_BUILD = vsgg->GetVersion() >= cmGlobalVisualStudioGenerator::VS7; if(usePRE_BUILD) { for (std::vector<std::string>::iterator it = depends.begin(); @@ -396,7 +396,7 @@ bool cmQtAutoGenerators::InitializeAutogenTarget(cmTarget* target) std::vector<std::string> rcc_output; bool const isNinja = - makefile->GetLocalGenerator()->GetGlobalGenerator()->GetName() == "Ninja"; + makefile->GetGlobalGenerator()->GetName() == "Ninja"; if(isNinja #if defined(_WIN32) && !defined(__CYGWIN__) || usePRE_BUILD @@ -524,9 +524,8 @@ static void GetCompileDefinitionsAndDirectories(cmTarget const* target, cmMakefile* makefile = target->GetMakefile(); cmLocalGenerator* localGen = makefile->GetLocalGenerator(); std::vector<std::string> includeDirs; - cmGeneratorTarget *gtgt = target->GetMakefile()->GetLocalGenerator() - ->GetGlobalGenerator() - ->GetGeneratorTarget(target); + cmGeneratorTarget *gtgt = localGen->GetGlobalGenerator() + ->GetGeneratorTarget(target); // Get the include dirs for this target, without stripping the implicit // include dirs off, see http://public.kitware.com/Bug/view.php?id=13667 localGen->GetIncludeDirectories(includeDirs, gtgt, "CXX", config, false); @@ -1204,23 +1203,6 @@ std::string cmQtAutoGenerators::GetRccExecutable(cmTarget const* target) return std::string(); } -static cmGlobalGenerator* CreateGlobalGenerator(cmake* cm, - const std::string& targetDirectory) -{ - cmGlobalGenerator* gg = new cmGlobalGenerator(); - gg->SetCMakeInstance(cm); - - cm->SetHomeOutputDirectory(targetDirectory); - cm->SetHomeDirectory(targetDirectory); - - cmLocalGenerator* lg = gg->CreateLocalGenerator(); - lg->GetMakefile()->SetCurrentBinaryDirectory(targetDirectory); - lg->GetMakefile()->SetCurrentSourceDirectory(targetDirectory); - gg->SetCurrentLocalGenerator(lg); - - return gg; -} - bool cmQtAutoGenerators::Run(const std::string& targetDirectory, const std::string& config) { @@ -1228,25 +1210,26 @@ bool cmQtAutoGenerators::Run(const std::string& targetDirectory, cmake cm; cm.SetHomeOutputDirectory(targetDirectory); cm.SetHomeDirectory(targetDirectory); - cmGlobalGenerator* gg = CreateGlobalGenerator(&cm, targetDirectory); - cmMakefile* makefile = gg->GetCurrentLocalGenerator()->GetMakefile(); + cmGlobalGenerator gg(&cm); + + cmLocalGenerator* lg = gg.MakeLocalGenerator(); + lg->GetMakefile()->SetCurrentBinaryDirectory(targetDirectory); + lg->GetMakefile()->SetCurrentSourceDirectory(targetDirectory); + gg.SetCurrentLocalGenerator(lg); - this->ReadAutogenInfoFile(makefile, targetDirectory, config); - this->ReadOldMocDefinitionsFile(makefile, targetDirectory); + this->ReadAutogenInfoFile(lg->GetMakefile(), targetDirectory, config); + this->ReadOldMocDefinitionsFile(lg->GetMakefile(), targetDirectory); this->Init(); if (this->QtMajorVersion == "4" || this->QtMajorVersion == "5") { - success = this->RunAutogen(makefile); + success = this->RunAutogen(lg->GetMakefile()); } this->WriteOldMocDefinitionsFile(targetDirectory); - delete gg->GetCurrentLocalGenerator(); - delete gg; - gg = NULL; - makefile = NULL; + delete lg; return success; } diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx index 35262b6..31e460f 100644 --- a/Source/cmSetPropertyCommand.cxx +++ b/Source/cmSetPropertyCommand.cxx @@ -207,8 +207,7 @@ bool cmSetPropertyCommand::HandleDirectoryMode() // Lookup the generator. if(cmLocalGenerator* lg = - (this->Makefile->GetLocalGenerator() - ->GetGlobalGenerator()->FindLocalGenerator(dir))) + this->Makefile->GetGlobalGenerator()->FindLocalGenerator(dir)) { // Use the makefile for the directory found. mf = lg->GetMakefile(); diff --git a/Source/cmSourceFile.cxx b/Source/cmSourceFile.cxx index cdd04ed..724ab39 100644 --- a/Source/cmSourceFile.cxx +++ b/Source/cmSourceFile.cxx @@ -282,7 +282,7 @@ void cmSourceFile::CheckLanguage(std::string const& ext) { // Try to identify the source file language from the extension. cmMakefile const* mf = this->Location.GetMakefile(); - cmGlobalGenerator* gg = mf->GetLocalGenerator()->GetGlobalGenerator(); + cmGlobalGenerator* gg = mf->GetGlobalGenerator(); std::string l = gg->GetLanguageFromExtension(ext.c_str()); if(!l.empty()) { diff --git a/Source/cmSourceFileLocation.cxx b/Source/cmSourceFileLocation.cxx index a0eba5e..4a87cc2 100644 --- a/Source/cmSourceFileLocation.cxx +++ b/Source/cmSourceFileLocation.cxx @@ -120,8 +120,7 @@ void cmSourceFileLocation::UpdateExtension(const std::string& name) if(!ext.empty()) { ext = ext.substr(1); } // The global generator checks extensions of enabled languages. - cmGlobalGenerator* gg = - this->Makefile->GetLocalGenerator()->GetGlobalGenerator(); + cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator(); cmMakefile const* mf = this->Makefile; const std::vector<std::string>& srcExts = mf->GetSourceExtensions(); const std::vector<std::string>& hdrExts = mf->GetHeaderExtensions(); diff --git a/Source/cmState.cxx b/Source/cmState.cxx index d6899a4..58885d3 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -20,10 +20,14 @@ cmState::cmState(cmake* cm) : CMakeInstance(cm), - IsInTryCompile(false) + IsInTryCompile(false), + WindowsShell(false), + WindowsVSIDE(false), + WatcomWMake(false), + MinGWMake(false), + NMake(false), + MSYSShell(false) { - this->CreateSnapshot(Snapshot()); - this->Initialize(); } cmState::~cmState() @@ -191,11 +195,35 @@ void cmState::RemoveCacheEntryProperty(std::string const& key, ->GetCacheIterator(key.c_str()).SetProperty(propertyName, (void*)0); } -void cmState::Initialize() +void cmState::Reset() { this->GlobalProperties.clear(); - this->PropertyDefinitions.clear(); + + assert(this->Locations.size() > 0); + assert(this->OutputLocations.size() > 0); + assert(this->ParentPositions.size() > 0); + assert(this->CurrentSourceDirectoryComponents.size() > 0); + assert(this->CurrentBinaryDirectoryComponents.size() > 0); + assert(this->RelativePathTopSource.size() > 0); + assert(this->RelativePathTopBinary.size() > 0); + + this->Locations.erase(this->Locations.begin() + 1, this->Locations.end()); + this->OutputLocations.erase(this->OutputLocations.begin() + 1, + this->OutputLocations.end()); + this->ParentPositions.erase(this->ParentPositions.begin() + 1, + this->ParentPositions.end()); + this->CurrentSourceDirectoryComponents.erase( + this->CurrentSourceDirectoryComponents.begin() + 1, + this->CurrentSourceDirectoryComponents.end()); + this->CurrentBinaryDirectoryComponents.erase( + this->CurrentBinaryDirectoryComponents.begin() + 1, + this->CurrentBinaryDirectoryComponents.end()); + this->RelativePathTopSource.erase(this->RelativePathTopSource.begin() + 1, + this->RelativePathTopSource.end()); + this->RelativePathTopBinary.erase(this->RelativePathTopBinary.begin() + 1, + this->RelativePathTopBinary.end()); + this->DefineProperty ("RULE_LAUNCH_COMPILE", cmProperty::DIRECTORY, "", "", true); @@ -273,6 +301,11 @@ std::vector<std::string> cmState::GetEnabledLanguages() const return this->EnabledLanguages; } +void cmState::SetEnabledLanguages(std::vector<std::string> const& langs) +{ + this->EnabledLanguages = langs; +} + void cmState::ClearEnabledLanguages() { this->EnabledLanguages.clear(); @@ -450,6 +483,10 @@ void cmState::SetSourceDirectory(std::string const& sourceDirectory) { this->SourceDirectory = sourceDirectory; cmSystemTools::ConvertToUnixSlashes(this->SourceDirectory); + + cmSystemTools::SplitPath( + cmSystemTools::CollapseFullPath(this->SourceDirectory), + this->SourceDirectoryComponents); } const char* cmState::GetSourceDirectory() const @@ -457,10 +494,79 @@ const char* cmState::GetSourceDirectory() const return this->SourceDirectory.c_str(); } +std::vector<std::string> const& cmState::GetSourceDirectoryComponents() const +{ + return this->SourceDirectoryComponents; +} + void cmState::SetBinaryDirectory(std::string const& binaryDirectory) { this->BinaryDirectory = binaryDirectory; cmSystemTools::ConvertToUnixSlashes(this->BinaryDirectory); + + cmSystemTools::SplitPath( + cmSystemTools::CollapseFullPath(this->BinaryDirectory), + this->BinaryDirectoryComponents); +} + +void cmState::SetWindowsShell(bool windowsShell) +{ + this->WindowsShell = windowsShell; +} + +bool cmState::UseWindowsShell() const +{ + return this->WindowsShell; +} + +void cmState::SetWindowsVSIDE(bool windowsVSIDE) +{ + this->WindowsVSIDE = windowsVSIDE; +} + +bool cmState::UseWindowsVSIDE() const +{ + return this->WindowsVSIDE; +} + +void cmState::SetWatcomWMake(bool watcomWMake) +{ + this->WatcomWMake = watcomWMake; +} + +bool cmState::UseWatcomWMake() const +{ + return this->WatcomWMake; +} + +void cmState::SetMinGWMake(bool minGWMake) +{ + this->MinGWMake = minGWMake; +} + +bool cmState::UseMinGWMake() const +{ + return this->MinGWMake; +} + +void cmState::SetNMake(bool nMake) +{ + this->NMake = nMake; +} + +bool cmState::UseNMake() const +{ + return this->NMake; +} + +void cmState::SetMSYSShell(bool mSYSShell) +{ + this->MSYSShell = mSYSShell; +} + +bool cmState::UseMSYSShell() const +{ + return this->MSYSShell; } const char* cmState::GetBinaryDirectory() const @@ -468,12 +574,107 @@ const char* cmState::GetBinaryDirectory() const return this->BinaryDirectory.c_str(); } +std::vector<std::string> const& cmState::GetBinaryDirectoryComponents() const +{ + return this->BinaryDirectoryComponents; +} + +void cmState::Snapshot::ComputeRelativePathTopSource() +{ + // Relative path conversion inside the source tree is not used to + // construct relative paths passed to build tools so it is safe to use + // even when the source is a network path. + + cmState::Snapshot snapshot = *this; + std::vector<cmState::Snapshot> snapshots; + snapshots.push_back(snapshot); + while (true) + { + snapshot = snapshot.GetParent(); + if (snapshot.IsValid()) + { + snapshots.push_back(snapshot); + } + else + { + break; + } + } + + std::string result = snapshots.front().GetCurrentSourceDirectory(); + + for (std::vector<cmState::Snapshot>::const_iterator it = + snapshots.begin() + 1; it != snapshots.end(); ++it) + { + std::string currentSource = it->GetCurrentSourceDirectory(); + if(cmSystemTools::IsSubDirectory(result, currentSource)) + { + result = currentSource; + } + } + this->State->RelativePathTopSource[this->Position] = result; +} + +void cmState::Snapshot::ComputeRelativePathTopBinary() +{ + cmState::Snapshot snapshot = *this; + std::vector<cmState::Snapshot> snapshots; + snapshots.push_back(snapshot); + while (true) + { + snapshot = snapshot.GetParent(); + if (snapshot.IsValid()) + { + snapshots.push_back(snapshot); + } + else + { + break; + } + } + + std::string result = + snapshots.front().GetCurrentBinaryDirectory(); + + for (std::vector<cmState::Snapshot>::const_iterator it = + snapshots.begin() + 1; it != snapshots.end(); ++it) + { + std::string currentBinary = it->GetCurrentBinaryDirectory(); + if(cmSystemTools::IsSubDirectory(result, currentBinary)) + { + result = currentBinary; + } + } + + // The current working directory on Windows cannot be a network + // path. Therefore relative paths cannot work when the binary tree + // is a network path. + if(result.size() < 2 || result.substr(0, 2) != "//") + { + this->State->RelativePathTopBinary[this->Position] = result; + } + else + { + this->State->RelativePathTopBinary[this->Position] = ""; + } +} + cmState::Snapshot cmState::CreateSnapshot(Snapshot originSnapshot) { + if (!originSnapshot.IsValid()) + { + originSnapshot.State = this; + } PositionType pos = this->ParentPositions.size(); this->ParentPositions.push_back(originSnapshot.Position); this->Locations.resize(this->Locations.size() + 1); this->OutputLocations.resize(this->OutputLocations.size() + 1); + this->CurrentSourceDirectoryComponents.resize( + this->CurrentSourceDirectoryComponents.size() + 1); + this->CurrentBinaryDirectoryComponents.resize( + this->CurrentBinaryDirectoryComponents.size() + 1); + this->RelativePathTopSource.resize(this->RelativePathTopSource.size() + 1); + this->RelativePathTopBinary.resize(this->RelativePathTopBinary.size() + 1); return cmState::Snapshot(this, pos); } @@ -491,12 +692,18 @@ const char* cmState::Snapshot::GetCurrentSourceDirectory() const void cmState::Snapshot::SetCurrentSourceDirectory(std::string const& dir) { + assert(this->State); assert(this->State->Locations.size() > this->Position); this->State->Locations[this->Position] = dir; cmSystemTools::ConvertToUnixSlashes( this->State->Locations[this->Position]); this->State->Locations[this->Position] = cmSystemTools::CollapseFullPath(this->State->Locations[this->Position]); + + cmSystemTools::SplitPath( + this->State->Locations[this->Position], + this->State->CurrentSourceDirectoryComponents[this->Position]); + this->ComputeRelativePathTopSource(); } const char* cmState::Snapshot::GetCurrentBinaryDirectory() const @@ -513,4 +720,59 @@ void cmState::Snapshot::SetCurrentBinaryDirectory(std::string const& dir) this->State->OutputLocations[this->Position] = cmSystemTools::CollapseFullPath( this->State->OutputLocations[this->Position]); + + cmSystemTools::SplitPath( + this->State->OutputLocations[this->Position], + this->State->CurrentBinaryDirectoryComponents[this->Position]); + this->ComputeRelativePathTopBinary(); +} + +std::vector<std::string> const& +cmState::Snapshot::GetCurrentSourceDirectoryComponents() +{ + return this->State->CurrentSourceDirectoryComponents[this->Position]; +} + +std::vector<std::string> const& +cmState::Snapshot::GetCurrentBinaryDirectoryComponents() +{ + return this->State->CurrentBinaryDirectoryComponents[this->Position]; +} + +const char* cmState::Snapshot::GetRelativePathTopSource() const +{ + return this->State->RelativePathTopSource[this->Position].c_str(); +} + +const char* cmState::Snapshot::GetRelativePathTopBinary() const +{ + return this->State->RelativePathTopBinary[this->Position].c_str(); +} + +void cmState::Snapshot::SetRelativePathTopSource(const char* dir) +{ + this->State->RelativePathTopSource[this->Position] = dir; +} + +void cmState::Snapshot::SetRelativePathTopBinary(const char* dir) +{ + this->State->RelativePathTopBinary[this->Position] = dir; +} + +bool cmState::Snapshot::IsValid() const +{ + return this->State ? true : false; +} + +cmState::Snapshot cmState::Snapshot::GetParent() const +{ + Snapshot snapshot; + if (!this->State || this->Position == 0) + { + return snapshot; + } + PositionType parentPos = this->State->ParentPositions[this->Position]; + snapshot = Snapshot(this->State, parentPos); + + return snapshot; } diff --git a/Source/cmState.h b/Source/cmState.h index 9902db9..77a066f 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -36,6 +36,21 @@ public: const char* GetCurrentBinaryDirectory() const; void SetCurrentBinaryDirectory(std::string const& dir); + std::vector<std::string> const& GetCurrentSourceDirectoryComponents(); + std::vector<std::string> const& GetCurrentBinaryDirectoryComponents(); + + const char* GetRelativePathTopSource() const; + const char* GetRelativePathTopBinary() const; + void SetRelativePathTopSource(const char* dir); + void SetRelativePathTopBinary(const char* dir); + + bool IsValid() const; + Snapshot GetParent() const; + + private: + void ComputeRelativePathTopSource(); + void ComputeRelativePathTopBinary(); + private: friend class cmState; cmState* State; @@ -78,7 +93,7 @@ public: void RemoveCacheEntryProperty(std::string const& key, std::string const& propertyName); - void Initialize(); + void Reset(); // Define a property void DefineProperty(const std::string& name, cmProperty::ScopeType scope, const char *ShortDescription, @@ -96,6 +111,7 @@ public: void SetLanguageEnabled(std::string const& l); bool GetLanguageEnabled(std::string const& l) const; std::vector<std::string> GetEnabledLanguages() const; + void SetEnabledLanguages(std::vector<std::string> const& langs); void ClearEnabledLanguages(); bool GetIsInTryCompile() const; @@ -119,6 +135,22 @@ public: const char* GetBinaryDirectory() const; void SetBinaryDirectory(std::string const& binaryDirectory); + std::vector<std::string> const& GetSourceDirectoryComponents() const; + std::vector<std::string> const& GetBinaryDirectoryComponents() const; + + void SetWindowsShell(bool windowsShell); + bool UseWindowsShell() const; + void SetWindowsVSIDE(bool windowsVSIDE); + bool UseWindowsVSIDE() const; + void SetWatcomWMake(bool watcomWMake); + bool UseWatcomWMake() const; + void SetMinGWMake(bool minGWMake); + bool UseMinGWMake() const; + void SetNMake(bool nMake); + bool UseNMake() const; + void SetMSYSShell(bool mSYSShell); + bool UseMSYSShell() const; + private: std::map<cmProperty::ScopeType, cmPropertyDefinitionMap> PropertyDefinitions; std::vector<std::string> EnabledLanguages; @@ -128,9 +160,28 @@ private: std::vector<std::string> Locations; std::vector<std::string> OutputLocations; std::vector<PositionType> ParentPositions; + + std::vector<std::vector<std::string> > CurrentSourceDirectoryComponents; + std::vector<std::vector<std::string> > CurrentBinaryDirectoryComponents; + // The top-most directories for relative path conversion. Both the + // source and destination location of a relative path conversion + // must be underneath one of these directories (both under source or + // both under binary) in order for the relative path to be evaluated + // safely by the build tools. + std::vector<std::string> RelativePathTopSource; + std::vector<std::string> RelativePathTopBinary; + + std::vector<std::string> SourceDirectoryComponents; + std::vector<std::string> BinaryDirectoryComponents; std::string SourceDirectory; std::string BinaryDirectory; bool IsInTryCompile; + bool WindowsShell; + bool WindowsVSIDE; + bool WatcomWMake; + bool MinGWMake; + bool NMake; + bool MSYSShell; }; #endif diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index f69e9ae..70005b4 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -333,9 +333,11 @@ void cmTarget::SetMakefile(cmMakefile* mf) this->SetPropertyDefault("MACOSX_BUNDLE", 0); this->SetPropertyDefault("MACOSX_RPATH", 0); this->SetPropertyDefault("NO_SYSTEM_FROM_IMPORTED", 0); + this->SetPropertyDefault("C_INCLUDE_WHAT_YOU_USE", 0); this->SetPropertyDefault("C_STANDARD", 0); this->SetPropertyDefault("C_STANDARD_REQUIRED", 0); this->SetPropertyDefault("C_EXTENSIONS", 0); + this->SetPropertyDefault("CXX_INCLUDE_WHAT_YOU_USE", 0); this->SetPropertyDefault("CXX_STANDARD", 0); this->SetPropertyDefault("CXX_STANDARD_REQUIRED", 0); this->SetPropertyDefault("CXX_EXTENSIONS", 0); @@ -511,7 +513,7 @@ void cmTarget::FinishConfigure() #if defined(_WIN32) && !defined(__CYGWIN__) // Do old-style link dependency analysis only for CM_USE_OLD_VS6. - if(this->Makefile->GetLocalGenerator()->GetGlobalGenerator()->IsForVS6()) + if(this->Makefile->GetGlobalGenerator()->IsForVS6()) { this->AnalyzeLibDependenciesForVS6(*this->Makefile); } @@ -847,8 +849,7 @@ cmTarget::GetConfigCommonSourceFiles(std::vector<cmSourceFile*>& files) const std::ostringstream e; e << "Target \"" << this->Name << "\" has source files which vary by " "configuration. This is not supported by the \"" - << this->Makefile->GetLocalGenerator() - ->GetGlobalGenerator()->GetName() + << this->Makefile->GetGlobalGenerator()->GetName() << "\" generator.\n" "Config \"" << firstConfig << "\":\n" " " << firstConfigFiles << "\n" @@ -974,8 +975,7 @@ std::string cmTarget::ProcessSourceItemCMP0049(const std::string& s) switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0049)) { case cmPolicies::WARN: - e << (this->Makefile->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0049)) << "\n"; + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0049) << "\n"; break; case cmPolicies::OLD: noMessage = true; @@ -1188,7 +1188,7 @@ void cmTarget::ClearDependencyInformation( cmMakefile& mf, //---------------------------------------------------------------------------- bool cmTarget::NameResolvesToFramework(const std::string& libname) const { - return this->Makefile->GetLocalGenerator()->GetGlobalGenerator()-> + return this->Makefile->GetGlobalGenerator()-> NameResolvesToFramework(libname); } @@ -1241,8 +1241,11 @@ bool cmTarget::PushTLLCommandTrace(TLLSignature signature) ret = false; } } - cmListFileBacktrace lfbt = this->Makefile->GetBacktrace(); - this->TLLCommands.push_back(std::make_pair(signature, lfbt)); + cmListFileContext lfc = this->Makefile->GetExecutionContext(); + if (this->TLLCommands.empty() || this->TLLCommands.back().second != lfc) + { + this->TLLCommands.push_back(std::make_pair(signature, lfc)); + } return ret; } @@ -1250,39 +1253,19 @@ bool cmTarget::PushTLLCommandTrace(TLLSignature signature) void cmTarget::GetTllSignatureTraces(std::ostringstream &s, TLLSignature sig) const { - std::vector<cmListFileBacktrace> sigs; - typedef std::vector<std::pair<TLLSignature, cmListFileBacktrace> > Container; + const char *sigString = (sig == cmTarget::KeywordTLLSignature ? "keyword" + : "plain"); + s << "The uses of the " << sigString << " signature are here:\n"; + typedef std::vector<std::pair<TLLSignature, cmListFileContext> > Container; + cmLocalGenerator* lg = this->GetMakefile()->GetLocalGenerator(); for(Container::const_iterator it = this->TLLCommands.begin(); it != this->TLLCommands.end(); ++it) { if (it->first == sig) { - sigs.push_back(it->second); - } - } - if (!sigs.empty()) - { - const char *sigString - = (sig == cmTarget::KeywordTLLSignature ? "keyword" - : "plain"); - s << "The uses of the " << sigString << " signature are here:\n"; - UNORDERED_SET<std::string> emitted; - for(std::vector<cmListFileBacktrace>::iterator it = sigs.begin(); - it != sigs.end(); ++it) - { - it->MakeRelative(); - cmListFileBacktrace::const_iterator i = it->begin(); - if(i != it->end()) - { - cmListFileContext const& lfc = *i; - std::ostringstream line; - line << " * " << (lfc.Line? "": " in ") << lfc << std::endl; - if (emitted.insert(line.str()).second) - { - s << line.str(); - } - ++i; - } + cmListFileContext lfc = it->second; + lfc.FilePath = lg->Convert(lfc.FilePath, cmLocalGenerator::HOME); + s << " * " << lfc << std::endl; } } } @@ -2008,8 +1991,7 @@ static void processIncludeDirectories(cmTarget const* tgt, switch(tgt->GetPolicyStatusCMP0027()) { case cmPolicies::WARN: - e << (mf->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0027)) << "\n"; + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0027) << "\n"; case cmPolicies::OLD: messageType = cmake::AUTHOR_WARNING; break; @@ -2049,8 +2031,7 @@ static void processIncludeDirectories(cmTarget const* tgt, { case cmPolicies::WARN: { - e << (mf->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0021)) << "\n"; + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0021) << "\n"; messageType = cmake::AUTHOR_WARNING; } break; @@ -2398,8 +2379,7 @@ void cmTarget::GetCompileDefinitions(std::vector<std::string> &list, case cmPolicies::WARN: { std::ostringstream e; - e << this->Makefile->GetCMakeInstance()->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0043); + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0043); this->Makefile->IssueMessage(cmake::AUTHOR_WARNING, e.str()); } @@ -2874,8 +2854,7 @@ bool cmTarget::HandleLocationPropertyPolicy(cmMakefile* context) const switch (context->GetPolicyStatus(cmPolicies::CMP0026)) { case cmPolicies::WARN: - e << (this->Makefile->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0026)) << "\n"; + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0026) << "\n"; modal = "should"; case cmPolicies::OLD: break; @@ -3138,8 +3117,7 @@ const char *cmTarget::GetProperty(const std::string& prop, switch(context->GetPolicyStatus(cmPolicies::CMP0051)) { case cmPolicies::WARN: - e << (this->Makefile->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0051)) << "\n"; + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0051) << "\n"; noMessage = false; case cmPolicies::OLD: break; @@ -3236,8 +3214,7 @@ public: { case cmPolicies::WARN: { - e << (this->Makefile->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0028)) << "\n"; + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0028) << "\n"; messageType = cmake::AUTHOR_WARNING; } break; @@ -3329,7 +3306,7 @@ public: cmTargetSelectLinker(cmTarget const* target): Preference(0), Target(target) { this->Makefile = this->Target->GetMakefile(); - this->GG = this->Makefile->GetLocalGenerator()->GetGlobalGenerator(); + this->GG = this->Makefile->GetGlobalGenerator(); } void Consider(const std::string& lang) { @@ -3764,7 +3741,7 @@ bool cmTarget::MacOSXRpathInstallNameDirDefault() const if(cmp0042 == cmPolicies::WARN) { - this->Makefile->GetLocalGenerator()->GetGlobalGenerator()-> + this->Makefile->GetGlobalGenerator()-> AddCMP0042WarnTarget(this->GetName()); } @@ -4551,7 +4528,7 @@ bool cmTarget::ComputeOutputDir(const std::string& config, "CMAKE_XCODE_EFFECTIVE_PLATFORMS"); std::string suffix = usesDefaultOutputDir && platforms ? "$(EFFECTIVE_PLATFORM_NAME)" : ""; - this->Makefile->GetLocalGenerator()->GetGlobalGenerator()-> + this->Makefile->GetGlobalGenerator()-> AppendDirectoryForConfig("/", conf, suffix, out); } @@ -4613,7 +4590,7 @@ bool cmTarget::ComputePDBOutputDir(const std::string& kind, // The generator may add the configuration's subdirectory. if(!conf.empty()) { - this->Makefile->GetLocalGenerator()->GetGlobalGenerator()-> + this->Makefile->GetGlobalGenerator()-> AppendDirectoryForConfig("/", conf, "", out); } return true; @@ -5276,8 +5253,7 @@ void cmTarget::GetLanguages(std::set<std::string>& languages, } else { - cmGeneratorTarget* gt = this->Makefile->GetLocalGenerator() - ->GetGlobalGenerator() + cmGeneratorTarget* gt = this->Makefile->GetGlobalGenerator() ->GetGeneratorTarget(this); gt->GetExternalObjects(externalObjects, config); for(std::vector<cmSourceFile const*>::const_iterator @@ -5993,9 +5969,7 @@ cmTargetInternals::ComputeLinkInterfaceLibraries( && strcmp(newExplicitLibraries, explicitLibraries) != 0) { std::ostringstream w; - w << - (thisTarget->Makefile->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0022)) << "\n" + w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0022) << "\n" "Target \"" << thisTarget->GetName() << "\" has an " "INTERFACE_LINK_LIBRARIES property which differs from its " << linkIfaceProp << " properties." @@ -6064,9 +6038,7 @@ cmTargetInternals::ComputeLinkInterfaceLibraries( { newLibraries = "(empty)"; } std::ostringstream w; - w << - (thisTarget->Makefile->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0022)) << "\n" + w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0022) << "\n" "Target \"" << thisTarget->GetName() << "\" has an " "INTERFACE_LINK_LIBRARIES property. " "This should be preferred as the source of the link interface " @@ -6323,8 +6295,7 @@ cmTargetInternals::ComputeLinkImplementationLibraries( { case cmPolicies::WARN: { - e << (thisTarget->Makefile->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0038)) << "\n"; + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0038) << "\n"; messageType = cmake::AUTHOR_WARNING; } break; @@ -6461,8 +6432,7 @@ std::string cmTarget::CheckCMP0004(std::string const& item) const case cmPolicies::WARN: { std::ostringstream w; - w << (this->Makefile->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0004)) << "\n" + w << cmPolicies::GetPolicyWarning(cmPolicies::CMP0004) << "\n" << "Target \"" << this->GetName() << "\" links to item \"" << item << "\" which has leading or trailing whitespace."; cm->IssueMessage(cmake::AUTHOR_WARNING, w.str(), @@ -6483,8 +6453,7 @@ std::string cmTarget::CheckCMP0004(std::string const& item) const case cmPolicies::REQUIRED_ALWAYS: { std::ostringstream e; - e << (this->Makefile->GetPolicies() - ->GetRequiredPolicyError(cmPolicies::CMP0004)) << "\n" + e << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0004) << "\n" << "Target \"" << this->GetName() << "\" links to item \"" << item << "\" which has leading or trailing whitespace."; cm->IssueMessage(cmake::FATAL_ERROR, e.str(), this->GetBacktrace()); diff --git a/Source/cmTarget.h b/Source/cmTarget.h index a032414..2150b83 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -19,7 +19,11 @@ #include <cmsys/auto_ptr.hxx> #if defined(CMAKE_BUILD_WITH_CMAKE) -#include <cmsys/hash_map.hxx> +# ifdef CMake_HAVE_CXX11_UNORDERED_MAP +# include <unordered_map> +# else +# include <cmsys/hash_map.hxx> +# endif #endif #define CM_FOR_EACH_TARGET_POLICY(F) \ @@ -35,7 +39,8 @@ F(CMP0042) \ F(CMP0046) \ F(CMP0052) \ - F(CMP0060) + F(CMP0060) \ + F(CMP0063) class cmake; class cmMakefile; @@ -641,7 +646,7 @@ private: // directories. std::set<std::string> SystemIncludeDirectories; - std::vector<std::pair<TLLSignature, cmListFileBacktrace> > TLLCommands; + std::vector<std::pair<TLLSignature, cmListFileContext> > TLLCommands; #if defined(_WIN32) && !defined(__CYGWIN__) /** @@ -849,7 +854,11 @@ private: }; #ifdef CMAKE_BUILD_WITH_CMAKE -typedef cmsys::hash_map<std::string,cmTarget> cmTargets; +#ifdef CMake_HAVE_CXX11_UNORDERED_MAP +typedef std::unordered_map<std::string, cmTarget> cmTargets; +#else +typedef cmsys::hash_map<std::string, cmTarget> cmTargets; +#endif #else typedef std::map<std::string,cmTarget> cmTargets; #endif diff --git a/Source/cmTargetLinkLibrariesCommand.cxx b/Source/cmTargetLinkLibrariesCommand.cxx index 9be7d46..df37d66 100644 --- a/Source/cmTargetLinkLibrariesCommand.cxx +++ b/Source/cmTargetLinkLibrariesCommand.cxx @@ -58,16 +58,14 @@ bool cmTargetLinkLibrariesCommand e << "\n" << "CMake does not support this but it used to work accidentally " << "and is being allowed for compatibility." - << "\n" << this->Makefile->GetPolicies()-> - GetPolicyWarning(cmPolicies::CMP0016); + << "\n" << cmPolicies::GetPolicyWarning(cmPolicies::CMP0016); break; case cmPolicies::OLD: // OLD behavior does not warn. t = cmake::MESSAGE; break; case cmPolicies::REQUIRED_IF_USED: case cmPolicies::REQUIRED_ALWAYS: - e << "\n" << this->Makefile->GetPolicies()-> - GetRequiredPolicyError(cmPolicies::CMP0016); + e << "\n" << cmPolicies::GetRequiredPolicyError(cmPolicies::CMP0016); break; case cmPolicies::NEW: // NEW behavior prints the error. break; @@ -108,8 +106,7 @@ bool cmTargetLinkLibrariesCommand switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0039)) { case cmPolicies::WARN: - e << this->Makefile->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0039) << "\n"; + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0039) << "\n"; modal = "should"; case cmPolicies::OLD: break; @@ -379,8 +376,7 @@ cmTargetLinkLibrariesCommand::HandleLibrary(const std::string& lib, switch(this->Makefile->GetPolicyStatus(cmPolicies::CMP0023)) { case cmPolicies::WARN: - e << this->Makefile->GetPolicies() - ->GetPolicyWarning(cmPolicies::CMP0023) << "\n"; + e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0023) << "\n"; modal = "should"; case cmPolicies::OLD: break; diff --git a/Source/cmTest.h b/Source/cmTest.h index c6e7e42..ca88afe 100644 --- a/Source/cmTest.h +++ b/Source/cmTest.h @@ -40,11 +40,6 @@ public: return this->Command; } - /** - * Print the structure to std::cout. - */ - void Print() const; - ///! Set/Get a property of this source file void SetProperty(const std::string& prop, const char *value); void AppendProperty(const std::string& prop, diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx index add80fa..7e11d8c 100644 --- a/Source/cmTestGenerator.cxx +++ b/Source/cmTestGenerator.cxx @@ -82,7 +82,6 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, // be translated. std::string exe = command[0]; cmMakefile* mf = this->Test->GetMakefile(); - cmLocalGenerator* lg = mf->GetLocalGenerator(); cmTarget* target = mf->FindTargetToUse(exe); if(target && target->GetType() == cmTarget::EXECUTABLE) { @@ -98,13 +97,13 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, cmSystemTools::ExpandListArgument(emulator, emulatorWithArgs); std::string emulatorExe(emulatorWithArgs[0]); cmSystemTools::ConvertToUnixSlashes(emulatorExe); - os << lg->EscapeForCMake(emulatorExe) << " "; + os << cmLocalGenerator::EscapeForCMake(emulatorExe) << " "; for(std::vector<std::string>::const_iterator ei = emulatorWithArgs.begin()+1; ei != emulatorWithArgs.end(); ++ei) { - os << lg->EscapeForCMake(*ei) << " "; + os << cmLocalGenerator::EscapeForCMake(*ei) << " "; } } } @@ -116,11 +115,12 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, } // Generate the command line with full escapes. - os << lg->EscapeForCMake(exe); + os << cmLocalGenerator::EscapeForCMake(exe); for(std::vector<std::string>::const_iterator ci = command.begin()+1; ci != command.end(); ++ci) { - os << " " << lg->EscapeForCMake(ge.Parse(*ci)->Evaluate(mf, config)); + os << " " << cmLocalGenerator::EscapeForCMake( + ge.Parse(*ci)->Evaluate(mf, config)); } // Finish the test command. @@ -136,7 +136,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, i != pm.end(); ++i) { os << " " << i->first - << " " << lg->EscapeForCMake( + << " " << cmLocalGenerator::EscapeForCMake( ge.Parse(i->second.GetValue())->Evaluate(mf, config)); } os << ")" << std::endl; @@ -197,8 +197,6 @@ void cmTestGenerator::GenerateOldStyle(std::ostream& fout, fout << ")" << std::endl; // Output properties for the test. - cmMakefile* mf = this->Test->GetMakefile(); - cmLocalGenerator* lg = mf->GetLocalGenerator(); cmPropertyMap& pm = this->Test->GetProperties(); if(!pm.empty()) { @@ -208,7 +206,7 @@ void cmTestGenerator::GenerateOldStyle(std::ostream& fout, i != pm.end(); ++i) { fout << " " << i->first - << " " << lg->EscapeForCMake(i->second.GetValue()); + << " " << cmLocalGenerator::EscapeForCMake(i->second.GetValue()); } fout << ")" << std::endl; } diff --git a/Source/cmTryRunCommand.cxx b/Source/cmTryRunCommand.cxx index 3cd92cb..b9ffe5e 100644 --- a/Source/cmTryRunCommand.cxx +++ b/Source/cmTryRunCommand.cxx @@ -375,7 +375,7 @@ void cmTryRunCommand::DoNotRunExecutable(const std::string& runArgs, comment += "Run arguments : "; comment += runArgs; comment += "\n"; - comment += " Called from: " + this->Makefile->GetListFileStack(); + comment += " Called from: " + this->Makefile->FormatListFileStack(); cmsys::SystemTools::ReplaceString(comment, "\n", "\n# "); file << comment << "\n\n"; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 131a134..5dfdb14 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -47,13 +47,13 @@ cmIDEFlagTable const* cmVisualStudio10TargetGenerator::GetClFlagTable() const { if(this->MSTools) { - cmLocalVisualStudioGenerator::VSVersion + cmGlobalVisualStudioGenerator::VSVersion v = this->LocalGenerator->GetVersion(); - if(v >= cmLocalVisualStudioGenerator::VS14) + if(v >= cmGlobalVisualStudioGenerator::VS14) { return cmVS14CLFlagTable; } - else if(v >= cmLocalVisualStudioGenerator::VS12) + else if(v >= cmGlobalVisualStudioGenerator::VS12) { return cmVS12CLFlagTable; } - else if(v == cmLocalVisualStudioGenerator::VS11) + else if(v == cmGlobalVisualStudioGenerator::VS11) { return cmVS11CLFlagTable; } else { return cmVS10CLFlagTable; } @@ -65,13 +65,13 @@ cmIDEFlagTable const* cmVisualStudio10TargetGenerator::GetRcFlagTable() const { if(this->MSTools) { - cmLocalVisualStudioGenerator::VSVersion + cmGlobalVisualStudioGenerator::VSVersion v = this->LocalGenerator->GetVersion(); - if(v >= cmLocalVisualStudioGenerator::VS14) + if(v >= cmGlobalVisualStudioGenerator::VS14) { return cmVS14RCFlagTable; } - else if(v >= cmLocalVisualStudioGenerator::VS12) + else if(v >= cmGlobalVisualStudioGenerator::VS12) { return cmVS12RCFlagTable; } - else if(v == cmLocalVisualStudioGenerator::VS11) + else if(v == cmGlobalVisualStudioGenerator::VS11) { return cmVS11RCFlagTable; } else { return cmVS10RCFlagTable; } @@ -83,13 +83,13 @@ cmIDEFlagTable const* cmVisualStudio10TargetGenerator::GetLibFlagTable() const { if(this->MSTools) { - cmLocalVisualStudioGenerator::VSVersion + cmGlobalVisualStudioGenerator::VSVersion v = this->LocalGenerator->GetVersion(); - if(v >= cmLocalVisualStudioGenerator::VS14) + if(v >= cmGlobalVisualStudioGenerator::VS14) { return cmVS14LibFlagTable; } - else if(v >= cmLocalVisualStudioGenerator::VS12) + else if(v >= cmGlobalVisualStudioGenerator::VS12) { return cmVS12LibFlagTable; } - else if(v == cmLocalVisualStudioGenerator::VS11) + else if(v == cmGlobalVisualStudioGenerator::VS11) { return cmVS11LibFlagTable; } else { return cmVS10LibFlagTable; } @@ -101,13 +101,13 @@ cmIDEFlagTable const* cmVisualStudio10TargetGenerator::GetLinkFlagTable() const { if(this->MSTools) { - cmLocalVisualStudioGenerator::VSVersion + cmGlobalVisualStudioGenerator::VSVersion v = this->LocalGenerator->GetVersion(); - if(v >= cmLocalVisualStudioGenerator::VS14) + if(v >= cmGlobalVisualStudioGenerator::VS14) { return cmVS14LinkFlagTable; } - else if(v >= cmLocalVisualStudioGenerator::VS12) + else if(v >= cmGlobalVisualStudioGenerator::VS12) { return cmVS12LinkFlagTable; } - else if(v == cmLocalVisualStudioGenerator::VS11) + else if(v == cmGlobalVisualStudioGenerator::VS11) { return cmVS11LinkFlagTable; } else { return cmVS10LinkFlagTable; } @@ -119,13 +119,13 @@ cmIDEFlagTable const* cmVisualStudio10TargetGenerator::GetMasmFlagTable() const { if(this->MSTools) { - cmLocalVisualStudioGenerator::VSVersion + cmGlobalVisualStudioGenerator::VSVersion v = this->LocalGenerator->GetVersion(); - if(v >= cmLocalVisualStudioGenerator::VS14) + if(v >= cmGlobalVisualStudioGenerator::VS14) { return cmVS14MASMFlagTable; } - else if(v >= cmLocalVisualStudioGenerator::VS12) + else if(v >= cmGlobalVisualStudioGenerator::VS12) { return cmVS12MASMFlagTable; } - else if(v == cmLocalVisualStudioGenerator::VS11) + else if(v == cmGlobalVisualStudioGenerator::VS11) { return cmVS11MASMFlagTable; } else { return cmVS10MASMFlagTable; } @@ -173,6 +173,7 @@ cmVisualStudio10TargetGenerator(cmTarget* target, this->Target = target; this->GeneratorTarget = gg->GetGeneratorTarget(target); this->Makefile = target->GetMakefile(); + this->Makefile->GetConfigurations(this->Configurations); this->LocalGenerator = (cmLocalVisualStudio7Generator*) this->Makefile->GetLocalGenerator(); @@ -525,10 +526,9 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup() std::string hFileName = obj.substr(0, obj.find_last_of(".")) + ".h"; (*this->BuildFileStream) << hFileName << "</DependentUpon>\n"; - std::vector<std::string> const * configs = - this->GlobalGenerator->GetConfigurations(); - for(std::vector<std::string>::const_iterator i = configs->begin(); - i != configs->end(); ++i) + for(std::vector<std::string>::const_iterator + i = this->Configurations.begin(); + i != this->Configurations.end(); ++i) { this->WritePlatformConfigTag("LogicalName", i->c_str(), 3); if(this->Target->GetProperty("VS_GLOBAL_ROOTNAMESPACE")) @@ -629,11 +629,9 @@ void cmVisualStudio10TargetGenerator::WriteWinRTReferences() void cmVisualStudio10TargetGenerator::WriteProjectConfigurations() { this->WriteString("<ItemGroup Label=\"ProjectConfigurations\">\n", 1); - std::vector<std::string> *configs = - static_cast<cmGlobalVisualStudio7Generator *> - (this->GlobalGenerator)->GetConfigurations(); - for(std::vector<std::string>::iterator i = configs->begin(); - i != configs->end(); ++i) + for(std::vector<std::string>::const_iterator + i = this->Configurations.begin(); + i != this->Configurations.end(); ++i) { this->WriteString("<ProjectConfiguration Include=\"", 2); (*this->BuildFileStream ) << *i << "|" << this->Platform << "\">\n"; @@ -649,11 +647,9 @@ void cmVisualStudio10TargetGenerator::WriteProjectConfigurations() void cmVisualStudio10TargetGenerator::WriteProjectConfigurationValues() { - std::vector<std::string> *configs = - static_cast<cmGlobalVisualStudio7Generator *> - (this->GlobalGenerator)->GetConfigurations(); - for(std::vector<std::string>::iterator i = configs->begin(); - i != configs->end(); ++i) + for(std::vector<std::string>::const_iterator + i = this->Configurations.begin(); + i != this->Configurations.end(); ++i) { this->WritePlatformConfigTag("PropertyGroup", i->c_str(), @@ -864,14 +860,12 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile const* source, } } cmLocalVisualStudio7Generator* lg = this->LocalGenerator; - std::vector<std::string> *configs = - static_cast<cmGlobalVisualStudio7Generator *> - (this->GlobalGenerator)->GetConfigurations(); this->WriteSource("CustomBuild", source, ">\n"); - for(std::vector<std::string>::iterator i = configs->begin(); - i != configs->end(); ++i) + for(std::vector<std::string>::const_iterator + i = this->Configurations.begin(); + i != this->Configurations.end(); ++i) { cmCustomCommandGenerator ccg(command, *i, this->Makefile); std::string comment = lg->ConstructComment(ccg); @@ -911,7 +905,8 @@ cmVisualStudio10TargetGenerator::WriteCustomRule(cmSourceFile const* source, sep = ";"; } (*this->BuildFileStream ) << "</Outputs>\n"; - if(this->LocalGenerator->GetVersion() > cmLocalVisualStudioGenerator::VS10) + if(this->LocalGenerator->GetVersion() + > cmGlobalVisualStudioGenerator::VS10) { // VS >= 11 let us turn off linking of custom command outputs. this->WritePlatformConfigTag("LinkObjects", i->c_str(), 3); @@ -1339,8 +1334,6 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf) if(!deployContent.empty()) { - std::vector<std::string> const* configs = - this->GlobalGenerator->GetConfigurations(); cmGeneratorExpression ge; cmsys::auto_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(deployContent); @@ -1352,13 +1345,14 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf) << "\\%(FileName)%(Extension)"; this->WriteString("</Link>\n", 0); } - for(size_t i = 0; i != configs->size(); ++i) + for(size_t i = 0; i != this->Configurations.size(); ++i) { - if(0 == strcmp(cge->Evaluate(this->Makefile, (*configs)[i]), "1")) + if(0 == strcmp(cge->Evaluate(this->Makefile, + this->Configurations[i]), "1")) { this->WriteString("<DeploymentContent Condition=\"" "'$(Configuration)|$(Platform)'=='", 3); - (*this->BuildFileStream) << (*configs)[i] << "|" + (*this->BuildFileStream) << this->Configurations[i] << "|" << this->Platform << "'\">true"; this->WriteString("</DeploymentContent>\n", 0); } @@ -1366,7 +1360,7 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf) { this->WriteString("<ExcludedFromBuild Condition=\"" "'$(Configuration)|$(Platform)'=='", 3); - (*this->BuildFileStream) << (*configs)[i] << "|" + (*this->BuildFileStream) << this->Configurations[i] << "|" << this->Platform << "'\">true"; this->WriteString("</ExcludedFromBuild>\n", 0); } @@ -1416,7 +1410,7 @@ void cmVisualStudio10TargetGenerator::WriteSource( // conversion uses full paths when possible to allow deeper trees. bool forceRelative = false; std::string sourceFile = this->ConvertPath(sf->GetFullPath(), false); - if(this->LocalGenerator->GetVersion() == cmLocalVisualStudioGenerator::VS10 + if(this->LocalGenerator->GetVersion() == cmGlobalVisualStudioGenerator::VS10 && cmSystemTools::FileIsFullPath(sourceFile.c_str())) { // Normal path conversion resulted in a full path. VS 10 (but not 11) @@ -1544,7 +1538,7 @@ void cmVisualStudio10TargetGenerator::WriteAllSources() ++si; } } - if(this->LocalGenerator->GetVersion() > cmLocalVisualStudioGenerator::VS10) + if(this->LocalGenerator->GetVersion() > cmGlobalVisualStudioGenerator::VS10) { // For VS >= 11 we use LinkObjects to avoid linking custom command // outputs. Use Object for all external objects, generated or not. @@ -1654,11 +1648,9 @@ bool cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( (*this->BuildFileStream ) << "$(IntDir)/" << objectName << "</ObjectFileName>\n"; } - std::vector<std::string> *configs = - static_cast<cmGlobalVisualStudio7Generator *> - (this->GlobalGenerator)->GetConfigurations(); - for( std::vector<std::string>::iterator config = configs->begin(); - config != configs->end(); ++config) + for(std::vector<std::string>::const_iterator + config = this->Configurations.begin(); + config != this->Configurations.end(); ++config) { std::string configUpper = cmSystemTools::UpperCase(*config); std::string configDefines = defines; @@ -1736,11 +1728,9 @@ void cmVisualStudio10TargetGenerator::WritePathAndIncrementalLinkOptions() this->WriteString("<PropertyGroup>\n", 2); this->WriteString("<_ProjectFileVersion>10.0.20506.1" "</_ProjectFileVersion>\n", 3); - std::vector<std::string> *configs = - static_cast<cmGlobalVisualStudio7Generator *> - (this->GlobalGenerator)->GetConfigurations(); - for(std::vector<std::string>::iterator config = configs->begin(); - config != configs->end(); ++config) + for(std::vector<std::string>::const_iterator + config = this->Configurations.begin(); + config != this->Configurations.end(); ++config) { if(ttype >= cmTarget::UTILITY) { @@ -1854,10 +1844,9 @@ OutputLinkIncremental(std::string const& configName) //---------------------------------------------------------------------------- bool cmVisualStudio10TargetGenerator::ComputeClOptions() { - std::vector<std::string> const* configs = - this->GlobalGenerator->GetConfigurations(); - for(std::vector<std::string>::const_iterator i = configs->begin(); - i != configs->end(); ++i) + for(std::vector<std::string>::const_iterator + i = this->Configurations.begin(); + i != this->Configurations.end(); ++i) { if(!this->ComputeClOptions(*i)) { @@ -2025,10 +2014,9 @@ void cmVisualStudio10TargetGenerator::WriteClOptions( //---------------------------------------------------------------------------- bool cmVisualStudio10TargetGenerator::ComputeRcOptions() { - std::vector<std::string> const* configs = - this->GlobalGenerator->GetConfigurations(); - for(std::vector<std::string>::const_iterator i = configs->begin(); - i != configs->end(); ++i) + for(std::vector<std::string>::const_iterator + i = this->Configurations.begin(); + i != this->Configurations.end(); ++i) { if(!this->ComputeRcOptions(*i)) { @@ -2091,10 +2079,9 @@ bool cmVisualStudio10TargetGenerator::ComputeMasmOptions() { return true; } - std::vector<std::string> const* configs = - this->GlobalGenerator->GetConfigurations(); - for(std::vector<std::string>::const_iterator i = configs->begin(); - i != configs->end(); ++i) + for(std::vector<std::string>::const_iterator + i = this->Configurations.begin(); + i != this->Configurations.end(); ++i) { if(!this->ComputeMasmOptions(*i)) { @@ -2238,10 +2225,9 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions() this->Target->GetType() == cmTarget::SHARED_LIBRARY || this->Target->GetType() == cmTarget::MODULE_LIBRARY) { - std::vector<std::string> const* configs = - this->GlobalGenerator->GetConfigurations(); - for(std::vector<std::string>::const_iterator i = configs->begin(); - i != configs->end(); ++i) + for(std::vector<std::string>::const_iterator + i = this->Configurations.begin(); + i != this->Configurations.end(); ++i) { if(!this->ComputeLinkOptions(*i)) { @@ -2590,11 +2576,9 @@ WriteMidlOptions(std::string const& /*config*/, void cmVisualStudio10TargetGenerator::WriteItemDefinitionGroups() { - std::vector<std::string> *configs = - static_cast<cmGlobalVisualStudio7Generator *> - (this->GlobalGenerator)->GetConfigurations(); - for(std::vector<std::string>::iterator i = configs->begin(); - i != configs->end(); ++i) + for(std::vector<std::string>::const_iterator + i = this->Configurations.begin(); + i != this->Configurations.end(); ++i) { std::vector<std::string> includes; this->LocalGenerator->GetIncludeDirectories(includes, diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index a2776de..451f8b2 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -137,6 +137,7 @@ private: OptionsMap MasmOptions; OptionsMap LinkOptions; std::string PathToVcxproj; + std::vector<std::string> Configurations; cmTarget* Target; cmGeneratorTarget* GeneratorTarget; cmMakefile* Makefile; diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx index 00386f6..6512fc2 100644 --- a/Source/cmVisualStudioGeneratorOptions.cxx +++ b/Source/cmVisualStudioGeneratorOptions.cxx @@ -96,14 +96,14 @@ void cmVisualStudioGeneratorOptions::FixExceptionHandlingDefault() // remove the flag we need to override the IDE default of on. switch (this->Version) { - case cmLocalVisualStudioGenerator::VS7: - case cmLocalVisualStudioGenerator::VS71: + case cmGlobalVisualStudioGenerator::VS7: + case cmGlobalVisualStudioGenerator::VS71: this->FlagMap["ExceptionHandling"] = "FALSE"; break; - case cmLocalVisualStudioGenerator::VS10: - case cmLocalVisualStudioGenerator::VS11: - case cmLocalVisualStudioGenerator::VS12: - case cmLocalVisualStudioGenerator::VS14: + case cmGlobalVisualStudioGenerator::VS10: + case cmGlobalVisualStudioGenerator::VS11: + case cmGlobalVisualStudioGenerator::VS12: + case cmGlobalVisualStudioGenerator::VS14: // by default VS puts <ExceptionHandling></ExceptionHandling> empty // for a project, to make our projects look the same put a new line // and space over for the closing </ExceptionHandling> as the default @@ -132,7 +132,7 @@ void cmVisualStudioGeneratorOptions::SetVerboseMakefile(bool verbose) this->FlagMap.find("SuppressStartupBanner") == this->FlagMap.end()) { this->FlagMap["SuppressStartupBanner"] = - this->Version < cmLocalVisualStudioGenerator::VS10 ? "FALSE" : ""; + this->Version < cmGlobalVisualStudioGenerator::VS10 ? "FALSE" : ""; } } @@ -270,7 +270,7 @@ cmVisualStudioGeneratorOptions { return; } - if(this->Version >= cmLocalVisualStudioGenerator::VS10) + if(this->Version >= cmGlobalVisualStudioGenerator::VS10) { // if there are configuration specific flags, then // use the configuration specific tag for PreprocessorDefinitions @@ -298,7 +298,7 @@ cmVisualStudioGeneratorOptions { // Escape the definition for the compiler. std::string define; - if(this->Version < cmLocalVisualStudioGenerator::VS10) + if(this->Version < cmGlobalVisualStudioGenerator::VS10) { define = this->LocalGenerator->EscapeForShell(di->c_str(), true); @@ -308,7 +308,7 @@ cmVisualStudioGeneratorOptions define = *di; } // Escape this flag for the IDE. - if(this->Version >= cmLocalVisualStudioGenerator::VS10) + if(this->Version >= cmGlobalVisualStudioGenerator::VS10) { define = cmVisualStudio10GeneratorOptionsEscapeForXML(define); @@ -325,7 +325,7 @@ cmVisualStudioGeneratorOptions fout << sep << define; sep = ";"; } - if(this->Version >= cmLocalVisualStudioGenerator::VS10) + if(this->Version >= cmGlobalVisualStudioGenerator::VS10) { fout << ";%(PreprocessorDefinitions)</PreprocessorDefinitions>" << suffix; } @@ -340,7 +340,7 @@ void cmVisualStudioGeneratorOptions ::OutputFlagMap(std::ostream& fout, const char* indent) { - if(this->Version >= cmLocalVisualStudioGenerator::VS10) + if(this->Version >= cmGlobalVisualStudioGenerator::VS10) { for(std::map<std::string, FlagValue>::iterator m = this->FlagMap.begin(); m != this->FlagMap.end(); ++m) @@ -395,7 +395,7 @@ cmVisualStudioGeneratorOptions { if(!this->FlagString.empty()) { - if(this->Version >= cmLocalVisualStudioGenerator::VS10) + if(this->Version >= cmGlobalVisualStudioGenerator::VS10) { fout << prefix; if(this->Configuration.size()) diff --git a/Source/cmVisualStudioGeneratorOptions.h b/Source/cmVisualStudioGeneratorOptions.h index 5490a43..0179134 100644 --- a/Source/cmVisualStudioGeneratorOptions.h +++ b/Source/cmVisualStudioGeneratorOptions.h @@ -73,7 +73,7 @@ public: void SetConfiguration(const char* config); private: cmLocalVisualStudioGenerator* LocalGenerator; - cmLocalVisualStudioGenerator::VSVersion Version; + cmGlobalVisualStudioGenerator::VSVersion Version; std::string Configuration; Tool CurrentTool; diff --git a/Source/cmXMLWriter.cxx b/Source/cmXMLWriter.cxx new file mode 100644 index 0000000..f9b3b49 --- /dev/null +++ b/Source/cmXMLWriter.cxx @@ -0,0 +1,134 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2015 Daniel Pfeifer <daniel@pfeifer-mail.de> + + 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 "cmXMLWriter.h" +#include "cmXMLSafe.h" + +#include <cassert> +#include <fstream> + +cmXMLWriter::cmXMLWriter(std::ostream& output, std::size_t level) +: Output(output) +, Level(level) +, ElementOpen(false) +, BreakAttrib(false) +, IsContent(false) +{ +} + +cmXMLWriter::~cmXMLWriter() +{ + assert(this->Elements.empty()); +} + +void cmXMLWriter::StartDocument(const char* encoding) +{ + this->Output << "<?xml version=\"1.0\" encoding=\"" << encoding << "\"?>"; +} + +void cmXMLWriter::EndDocument() +{ + assert(this->Elements.empty()); + this->Output << '\n'; +} + +void cmXMLWriter::StartElement(std::string const& name) +{ + this->CloseStartElement(); + this->ConditionalLineBreak(!this->IsContent, this->Elements.size()); + this->Output << '<' << name; + this->Elements.push(name); + this->ElementOpen = true; + this->BreakAttrib = false; +} + +void cmXMLWriter::EndElement() +{ + assert(!this->Elements.empty()); + if (this->ElementOpen) + { + this->Output << "/>"; + } + else + { + this->ConditionalLineBreak(!this->IsContent, this->Elements.size() - 1); + this->IsContent = false; + this->Output << "</" << this->Elements.top() << '>'; + } + this->Elements.pop(); + this->ElementOpen = false; +} + +void cmXMLWriter::BreakAttributes() +{ + this->BreakAttrib = true; +} + +void cmXMLWriter::Comment(const char* comment) +{ + this->CloseStartElement(); + this->ConditionalLineBreak(!this->IsContent, this->Elements.size()); + this->Output << "<!-- " << comment << " -->"; +} + +void cmXMLWriter::CData(std::string const& data) +{ + this->PreContent(); + this->Output << "<![CDATA[" << data << "]]>"; +} + +void cmXMLWriter::ProcessingInstruction(const char* target, const char* data) +{ + this->CloseStartElement(); + this->ConditionalLineBreak(!this->IsContent, this->Elements.size()); + this->Output << "<?" << target << ' ' << data << "?>"; +} + +void cmXMLWriter::FragmentFile(const char* fname) +{ + this->CloseStartElement(); + std::ifstream fin(fname, std::ios::in | std::ios::binary); + this->Output << fin.rdbuf(); +} + +void cmXMLWriter::ConditionalLineBreak(bool condition, std::size_t indent) +{ + if (condition) + { + this->Output << '\n' << std::string(indent + this->Level, '\t'); + } +} + +void cmXMLWriter::PreAttribute() +{ + assert(this->ElementOpen); + this->ConditionalLineBreak(this->BreakAttrib, this->Elements.size()); + if (!this->BreakAttrib) + { + this->Output << ' '; + } +} + +void cmXMLWriter::PreContent() +{ + this->CloseStartElement(); + this->IsContent = true; +} + +void cmXMLWriter::CloseStartElement() +{ + if (this->ElementOpen) + { + this->ConditionalLineBreak(this->BreakAttrib, this->Elements.size()); + this->Output << '>'; + this->ElementOpen = false; + } +} diff --git a/Source/cmXMLWriter.h b/Source/cmXMLWriter.h new file mode 100644 index 0000000..c38c0de --- /dev/null +++ b/Source/cmXMLWriter.h @@ -0,0 +1,120 @@ +/*============================================================================ + CMake - Cross Platform Makefile Generator + Copyright 2015 Daniel Pfeifer <daniel@pfeifer-mail.de> + + 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 cmXMLWiter_h +#define cmXMLWiter_h + +#include "cmStandardIncludes.h" +#include "cmXMLSafe.h" + +#include <ostream> +#include <stack> +#include <string> +#include <vector> + +class cmXMLWriter +{ +public: + cmXMLWriter(std::ostream& output, std::size_t level = 0); + ~cmXMLWriter(); + + void StartDocument(const char* encoding = "UTF-8"); + void EndDocument(); + + void StartElement(std::string const& name); + void EndElement(); + + void BreakAttributes(); + + template <typename T> + void Attribute(const char* name, T const& value) + { + this->PreAttribute(); + this->Output << name << "=\"" << SafeAttribute(value) << '"'; + } + + template <typename T> + void Element(std::string const& name, T const& value) + { + this->StartElement(name); + this->Content(value); + this->EndElement(); + } + + template <typename T> + void Content(T const& content) + { + this->PreContent(); + this->Output << SafeContent(content); + } + + void Comment(const char* comment); + + void CData(std::string const& data); + + void ProcessingInstruction(const char* target, const char* data); + + void FragmentFile(const char* fname); + +private: + cmXMLWriter(const cmXMLWriter&); + cmXMLWriter& operator=(const cmXMLWriter&); + + void ConditionalLineBreak(bool condition, std::size_t indent); + + void PreAttribute(); + void PreContent(); + + void CloseStartElement(); + +private: + static cmXMLSafe SafeAttribute(const char* value) + { + return cmXMLSafe(value); + } + + static cmXMLSafe SafeAttribute(std::string const& value) + { + return cmXMLSafe(value); + } + + template <typename T> + static T SafeAttribute(T value) + { + return value; + } + + static cmXMLSafe SafeContent(const char* value) + { + return cmXMLSafe(value).Quotes(false); + } + + static cmXMLSafe SafeContent(std::string const& value) + { + return cmXMLSafe(value).Quotes(false); + } + + template <typename T> + static T SafeContent(T value) + { + return value; + } + +private: + std::ostream& Output; + std::stack<std::string, std::vector<std::string> > Elements; + std::size_t Level; + bool ElementOpen; + bool BreakAttrib; + bool IsContent; +}; + +#endif diff --git a/Source/cmake.cxx b/Source/cmake.cxx index 5c5c428..23803ef 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -88,8 +88,6 @@ # include "cmGlobalKdevelopGenerator.h" #endif -#include "cmExtraQbsGenerator.h" - #ifdef CMAKE_USE_ECLIPSE # include "cmExtraEclipseCDT4Generator.h" #endif @@ -136,6 +134,7 @@ cmake::cmake() this->Policies = new cmPolicies(); this->State = new cmState(this); + this->CurrentSnapshot = this->State->CreateSnapshot(cmState::Snapshot()); #ifdef __APPLE__ struct rlimit rlp; @@ -187,7 +186,7 @@ cmake::~cmake() void cmake::CleanupCommandsAndMacros() { - this->State->Initialize(); + this->State->Reset(); this->State->RemoveUserDefinedCommands(); } @@ -364,8 +363,7 @@ void cmake::ReadListFile(const std::vector<std::string>& args, // if a generator was not specified use a generic one if (!gg) { - gg = new cmGlobalGenerator; - gg->SetCMakeInstance(this); + gg = new cmGlobalGenerator(this); created = true; } @@ -376,7 +374,7 @@ void cmake::ReadListFile(const std::vector<std::string>& args, std::string homeOutputDir = this->GetHomeOutputDirectory(); this->SetHomeDirectory(cmSystemTools::GetCurrentWorkingDirectory()); this->SetHomeOutputDirectory(cmSystemTools::GetCurrentWorkingDirectory()); - cmsys::auto_ptr<cmLocalGenerator> lg(gg->CreateLocalGenerator()); + cmsys::auto_ptr<cmLocalGenerator> lg(gg->MakeLocalGenerator()); lg->GetMakefile()->SetCurrentBinaryDirectory (cmSystemTools::GetCurrentWorkingDirectory()); lg->GetMakefile()->SetCurrentSourceDirectory @@ -413,12 +411,11 @@ bool cmake::FindPackage(const std::vector<std::string>& args) (cmSystemTools::GetCurrentWorkingDirectory()); // if a generator was not yet created, temporarily create one - cmGlobalGenerator *gg = new cmGlobalGenerator; - gg->SetCMakeInstance(this); + cmGlobalGenerator *gg = new cmGlobalGenerator(this); this->SetGlobalGenerator(gg); // read in the list file to fill the cache - cmsys::auto_ptr<cmLocalGenerator> lg(gg->CreateLocalGenerator()); + cmsys::auto_ptr<cmLocalGenerator> lg(gg->MakeLocalGenerator()); cmMakefile* mf = lg->GetMakefile(); mf->SetCurrentBinaryDirectory (cmSystemTools::GetCurrentWorkingDirectory()); @@ -456,8 +453,7 @@ bool cmake::FindPackage(const std::vector<std::string>& args) std::vector<std::string> includeDirs; cmSystemTools::ExpandListArgument(includes, includeDirs); - std::string includeFlags = lg->GetIncludeFlags(includeDirs, 0, - language, false); + std::string includeFlags = lg->GetIncludeFlags(includeDirs, 0, language); std::string definitions = mf->GetSafeDefinition("PACKAGE_DEFINITIONS"); printf("%s %s\n", includeFlags.c_str(), definitions.c_str()); @@ -903,8 +899,6 @@ void cmake::AddDefaultExtraGenerators() &cmExtraSublimeTextGenerator::New); this->AddExtraGenerator(cmExtraKateGenerator::GetActualName(), &cmExtraKateGenerator::New); - this->AddExtraGenerator(cmExtraQbsGenerator::GetActualName(), - &cmExtraQbsGenerator::New); #ifdef CMAKE_USE_ECLIPSE this->AddExtraGenerator(cmExtraEclipseCDT4Generator::GetActualName(), @@ -956,7 +950,7 @@ cmGlobalGenerator* cmake::CreateGlobalGenerator(const std::string& gname) for (RegisteredGeneratorsVector::const_iterator i = this->Generators.begin(); i != this->Generators.end(); ++i) { - generator = (*i)->CreateGlobalGenerator(name); + generator = (*i)->CreateGlobalGenerator(name, this); if (generator) { break; @@ -965,7 +959,6 @@ cmGlobalGenerator* cmake::CreateGlobalGenerator(const std::string& gname) if (generator) { - generator->SetCMakeInstance(this); generator->SetExternalMakefileProjectGenerator(extraGenerator); } else @@ -1050,8 +1043,6 @@ void cmake::SetGlobalGenerator(cmGlobalGenerator *gg) { this->CCEnvironment = ""; } - // set the cmake instance just to be sure - gg->SetCMakeInstance(this); } int cmake::DoPreConfigureChecks() @@ -1304,12 +1295,12 @@ int cmake::ActualConfigure() = this->CreateGlobalGenerator(installedCompiler.c_str()); if(!gen) { - gen = new cmGlobalNMakeMakefileGenerator; + gen = new cmGlobalNMakeMakefileGenerator(this); } this->SetGlobalGenerator(gen); std::cout << "-- Building for: " << gen->GetName() << "\n"; #else - this->SetGlobalGenerator(new cmGlobalUnixMakefileGenerator3); + this->SetGlobalGenerator(new cmGlobalUnixMakefileGenerator3(this)); #endif } if(!this->GlobalGenerator) @@ -1625,11 +1616,6 @@ int cmake::Run(const std::vector<std::string>& args, bool noconfigure) std::string message = "Build files have been written to: "; message += this->GetHomeOutputDirectory(); this->UpdateProgress(message.c_str(), -1); - if(ret) - { - return ret; - } - return ret; } @@ -1925,9 +1911,10 @@ int cmake::CheckBuildSystem() // Read the rerun check file and use it to decide whether to do the // global generate. cmake cm; - cmGlobalGenerator gg; - gg.SetCMakeInstance(&cm); - cmsys::auto_ptr<cmLocalGenerator> lg(gg.CreateLocalGenerator()); + cm.SetHomeDirectory(""); + cm.SetHomeOutputDirectory(""); + cmGlobalGenerator gg(&cm); + cmsys::auto_ptr<cmLocalGenerator> lg(gg.MakeLocalGenerator()); cmMakefile* mf = lg->GetMakefile(); if(!mf->ReadListFile(this->CheckBuildSystemArgument.c_str()) || cmSystemTools::GetErrorOccuredFlag()) @@ -1957,7 +1944,7 @@ int cmake::CheckBuildSystem() ggd(this->CreateGlobalGenerator(genName)); if(ggd.get()) { - cmsys::auto_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator()); + cmsys::auto_ptr<cmLocalGenerator> lgd(ggd->MakeLocalGenerator()); lgd->ClearDependencies(mf, verbose); } } @@ -2435,24 +2422,15 @@ static bool cmakeCheckStampList(const char* stampList) return true; } -//---------------------------------------------------------------------------- -void cmake::IssueMessage(cmake::MessageType t, std::string const& text, - cmListFileBacktrace const& bt) +bool cmake::PrintMessagePreamble(cmake::MessageType t, std::ostream& msg) { - cmListFileBacktrace backtrace = bt; - backtrace.MakeRelative(); - - std::ostringstream msg; - bool isError = false; // Construct the message header. if(t == cmake::FATAL_ERROR) { - isError = true; msg << "CMake Error"; } else if(t == cmake::INTERNAL_ERROR) { - isError = true; msg << "CMake Internal Error (please report a bug)"; } else if(t == cmake::LOG) @@ -2462,7 +2440,6 @@ void cmake::IssueMessage(cmake::MessageType t, std::string const& text, else if(t == cmake::DEPRECATION_ERROR) { msg << "CMake Deprecation Error"; - isError = true; } else if (t == cmake::DEPRECATION_WARNING) { @@ -2478,40 +2455,24 @@ void cmake::IssueMessage(cmake::MessageType t, std::string const& text, "CMAKE_SUPPRESS_DEVELOPER_WARNINGS"); if(suppress && cmSystemTools::IsOn(suppress)) { - return; + return false; } msg << " (dev)"; } } + return true; +} - // Add the immediate context. - cmListFileBacktrace::const_iterator i = backtrace.begin(); - if(i != backtrace.end()) - { - cmListFileContext const& lfc = *i; - msg << (lfc.Line? " at ": " in ") << lfc; - ++i; - } - - // Add the message text. - { - msg << ":\n"; - cmDocumentationFormatter formatter; - formatter.SetIndent(" "); - formatter.PrintFormatted(msg, text.c_str()); - } +void printMessageText(std::ostream& msg, std::string const& text) +{ + msg << ":\n"; + cmDocumentationFormatter formatter; + formatter.SetIndent(" "); + formatter.PrintFormatted(msg, text.c_str()); +} - // Add the rest of the context. - if(i != backtrace.end()) - { - msg << "Call Stack (most recent call first):\n"; - while(i != backtrace.end()) - { - cmListFileContext const& lfc = *i; - msg << " " << lfc << "\n"; - ++i; - } - } +void displayMessage(cmake::MessageType t, std::ostringstream& msg) +{ // Add a note about warning suppression. if(t == cmake::AUTHOR_WARNING) @@ -2540,7 +2501,9 @@ void cmake::IssueMessage(cmake::MessageType t, std::string const& text, #endif // Output the message. - if(isError) + if(t == cmake::FATAL_ERROR + || t == cmake::INTERNAL_ERROR + || t == cmake::DEPRECATION_ERROR) { cmSystemTools::SetErrorOccured(); cmSystemTools::Message(msg.str().c_str(), "Error"); @@ -2552,6 +2515,48 @@ void cmake::IssueMessage(cmake::MessageType t, std::string const& text, } //---------------------------------------------------------------------------- +void cmake::IssueMessage(cmake::MessageType t, std::string const& text, + cmListFileBacktrace const& bt) +{ + cmListFileBacktrace backtrace = bt; + backtrace.MakeRelative(); + + std::ostringstream msg; + if (!this->PrintMessagePreamble(t, msg)) + { + return; + } + + // Add the immediate context. + backtrace.PrintTitle(msg); + + printMessageText(msg, text); + + // Add the rest of the context. + backtrace.PrintCallStack(msg); + + displayMessage(t, msg); +} + +//---------------------------------------------------------------------------- +void cmake::IssueMessage(cmake::MessageType t, std::string const& text, + cmListFileContext const& lfc) +{ + std::ostringstream msg; + if (!this->PrintMessagePreamble(t, msg)) + { + return; + } + + // Add the immediate context. + msg << (lfc.Line ? " at " : " in ") << lfc; + + printMessageText(msg, text); + + displayMessage(t, msg); +} + +//---------------------------------------------------------------------------- std::vector<std::string> cmake::GetDebugConfigs() { std::vector<std::string> configs; @@ -2580,6 +2585,9 @@ int cmake::Build(const std::string& dir, const std::vector<std::string>& nativeOptions, bool clean) { + + this->SetHomeDirectory(""); + this->SetHomeOutputDirectory(""); if(!cmSystemTools::FileIsDirectory(dir)) { std::cerr << "Error: " << dir << " is not a directory\n"; diff --git a/Source/cmake.h b/Source/cmake.h index 0d1977e..12b7e68 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -30,7 +30,6 @@ class cmDocumentationSection; class cmPolicies; class cmTarget; class cmGeneratedFileStream; -class cmState; /** \brief Represents a cmake invocation. * @@ -303,6 +302,9 @@ class cmake /** Display a message to the user. */ void IssueMessage(cmake::MessageType t, std::string const& text, cmListFileBacktrace const& backtrace = cmListFileBacktrace(NULL)); + void IssueMessage(cmake::MessageType t, std::string const& text, + cmListFileContext const& lfc); + ///! run the --build option int Build(const std::string& dir, const std::string& target, @@ -314,6 +316,10 @@ class cmake void WatchUnusedCli(const std::string& var); cmState* GetState() const { return this->State; } + void SetCurrentSnapshot(cmState::Snapshot snapshot) + { this->CurrentSnapshot = snapshot; } + cmState::Snapshot GetCurrentSnapshot() const + { return this->CurrentSnapshot; } protected: void RunCheckForUnusedVariables(); @@ -394,16 +400,19 @@ private: InstalledFilesMap InstalledFiles; cmState* State; + cmState::Snapshot CurrentSnapshot; void UpdateConversionPathTable(); // Print a list of valid generators to stderr. void PrintGeneratorList(); + + bool PrintMessagePreamble(cmake::MessageType t, std::ostream& msg); }; #define CMAKE_STANDARD_OPTIONS_TABLE \ {"-C <initial-cache>", "Pre-load a script to populate the cache."}, \ - {"-D <var>:<type>=<value>", "Create a cmake cache entry."}, \ + {"-D <var>[:<type>]=<value>", "Create a cmake cache entry."}, \ {"-U <globbing_expr>", "Remove matching entries from CMake cache."}, \ {"-G <generator-name>", "Specify a build system generator."},\ {"-T <toolset-name>", "Specify toolset name if supported by generator."}, \ diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index d82087f..e5f4700 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -130,7 +130,7 @@ static std::string cmakemainGetStack(void *clientdata) cmMakefile* mf=cmakemainGetMakefile(clientdata); if (mf) { - msg = mf->GetListFileStack(); + msg = mf->FormatListFileStack(); if (!msg.empty()) { msg = "\n Called from: " + msg; @@ -214,6 +214,8 @@ int do_cmake(int ac, char const* const* av) { // Construct and print requested documentation. cmake hcm; + hcm.SetHomeDirectory(""); + hcm.SetHomeOutputDirectory(""); hcm.AddCMakePaths(); // the command line args are processed here so that you can do @@ -317,10 +319,14 @@ int do_cmake(int ac, char const* const* av) if (sysinfo) { cmake cm; + cm.SetHomeDirectory(""); + cm.SetHomeOutputDirectory(""); int ret = cm.GetSystemInformation(args); return ret; } cmake cm; + cm.SetHomeDirectory(""); + cm.SetHomeOutputDirectory(""); cmSystemTools::SetMessageCallback(cmakemainMessageCallback, (void *)&cm); cm.SetProgressCallback(cmakemainProgressCallback, (void *)&cm); cm.SetWorkingMode(workingMode); diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 12bb8ee..3ea2186 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -211,6 +211,88 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) return 0; } + // run include what you use command and then run the compile + // command. This is an internal undocumented option and should + // only be used by CMake itself when running iwyu. + else if (args[1] == "__run_iwyu") + { + if (args.size() < 3) + { + std::cerr << "__run_iwyu Usage: -E __run_iwyu [--iwyu=/path/iwyu]" + " -- compile command\n"; + return 1; + } + bool doing_options = true; + std::vector<std::string> orig_cmd; + std::string iwyu; + for (std::string::size_type cc = 2; cc < args.size(); cc ++) + { + std::string const& arg = args[cc]; + if (arg == "--") + { + doing_options = false; + } + else if (doing_options && cmHasLiteralPrefix(arg, "--iwyu=")) + { + iwyu = arg.substr(7); + } + else if (doing_options) + { + std::cerr << "__run_iwyu given unknown argument: " << arg << "\n"; + return 1; + } + else + { + orig_cmd.push_back(arg); + } + } + if (iwyu.empty()) + { + std::cerr << "__run_iwyu missing --iwyu=\n"; + return 1; + } + if (orig_cmd.empty()) + { + std::cerr << "__run_iwyu missing compile command after --\n"; + return 1; + } + + // Construct the iwyu command line by taking what was given + // and adding all the arguments we give to the compiler. + std::vector<std::string> iwyu_cmd; + cmSystemTools::ExpandListArgument(iwyu, iwyu_cmd, true); + iwyu_cmd.insert(iwyu_cmd.end(), orig_cmd.begin()+1, orig_cmd.end()); + + // Run the iwyu command line. Capture its stderr and hide its stdout. + int ret = 0; + std::string stdErr; + if(!cmSystemTools::RunSingleCommand(iwyu_cmd, 0, &stdErr, &ret, + 0, cmSystemTools::OUTPUT_NONE)) + { + std::cerr << "Error running '" << iwyu_cmd[0] << "': " + << stdErr << "\n"; + return 1; + } + + // Warn if iwyu reported anything. + if(stdErr.find("should remove these lines:") != stdErr.npos + || stdErr.find("should add these lines:") != stdErr.npos) + { + std::cerr << "Warning: include-what-you-use reported diagnostics:\n" + << stdErr << "\n"; + } + + // Now run the real compiler command and return its result value. + if(!cmSystemTools::RunSingleCommand(orig_cmd, 0, &stdErr, &ret, 0, + cmSystemTools::OUTPUT_PASSTHROUGH)) + { + std::cerr << "Error running '" << orig_cmd[0] << "': " + << stdErr << "\n"; + return 1; + } + return ret; + } + // Echo string else if (args[1] == "echo" ) { @@ -646,7 +728,7 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) if(cmGlobalGenerator* ggd = cm.CreateGlobalGenerator(gen)) { cm.SetGlobalGenerator(ggd); - cmsys::auto_ptr<cmLocalGenerator> lgd(ggd->CreateLocalGenerator()); + cmsys::auto_ptr<cmLocalGenerator> lgd(ggd->MakeLocalGenerator()); lgd->GetMakefile()->SetCurrentSourceDirectory(startDir); lgd->GetMakefile()->SetCurrentBinaryDirectory(startOutDir); diff --git a/Source/ctest.cxx b/Source/ctest.cxx index 0fc47b7..e784759 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -160,6 +160,8 @@ int main (int argc, char const* const* argv) if(doc.CheckOptions(argc, argv)) { cmake hcm; + hcm.SetHomeDirectory(""); + hcm.SetHomeOutputDirectory(""); hcm.AddCMakePaths(); // Construct and print requested documentation. diff --git a/Source/kwsys/.gitattributes b/Source/kwsys/.gitattributes new file mode 100644 index 0000000..a9c4e77 --- /dev/null +++ b/Source/kwsys/.gitattributes @@ -0,0 +1,12 @@ +.git* export-ignore + +/CONTRIBUTING.rst conflict-marker-size=78 + +*.c whitespace=tab-in-indent,no-lf-at-eof +*.h whitespace=tab-in-indent,no-lf-at-eof +*.h.in whitespace=tab-in-indent,no-lf-at-eof +*.cxx whitespace=tab-in-indent,no-lf-at-eof +*.hxx whitespace=tab-in-indent,no-lf-at-eof +*.hxx.in whitespace=tab-in-indent,no-lf-at-eof +*.txt whitespace=tab-in-indent,no-lf-at-eof +*.cmake whitespace=tab-in-indent,no-lf-at-eof diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt index 8069ee2..c88e888 100644 --- a/Source/kwsys/CMakeLists.txt +++ b/Source/kwsys/CMakeLists.txt @@ -88,6 +88,9 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6.3 FATAL_ERROR) IF(POLICY CMP0025) CMAKE_POLICY(SET CMP0025 NEW) ENDIF() +IF(POLICY CMP0056) + CMAKE_POLICY(SET CMP0056 NEW) +ENDIF() #----------------------------------------------------------------------------- # If a namespace is not specified, use "kwsys" and enable testing. diff --git a/Source/kwsys/CPU.h.in b/Source/kwsys/CPU.h.in index 626914b..884d71a 100644 --- a/Source/kwsys/CPU.h.in +++ b/Source/kwsys/CPU.h.in @@ -76,7 +76,15 @@ #elif defined(__m68k__) || defined(M68000) # define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG -/* MIPS */ +/* MIPSel (MIPS little endian) */ +#elif defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) +# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_LITTLE + +/* MIPSeb (MIPS big endian) */ +#elif defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) +# define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG + +/* MIPS (fallback, big endian) */ #elif defined(__mips) || defined(__mips__) || defined(__MIPS__) # define @KWSYS_NAMESPACE@_CPU_ENDIAN_ID @KWSYS_NAMESPACE@_CPU_ENDIAN_ID_BIG diff --git a/Source/kwsys/DynamicLoader.cxx b/Source/kwsys/DynamicLoader.cxx index 66c7d57..a776f97 100644 --- a/Source/kwsys/DynamicLoader.cxx +++ b/Source/kwsys/DynamicLoader.cxx @@ -48,6 +48,10 @@ DynamicLoader::LibraryHandle DynamicLoader::OpenLibrary(const kwsys_stl::string& //---------------------------------------------------------------------------- int DynamicLoader::CloseLibrary(DynamicLoader::LibraryHandle lib) { + if (!lib) + { + return 0; + } return !shl_unload(lib); } diff --git a/Source/kwsys/Glob.hxx.in b/Source/kwsys/Glob.hxx.in index 39b7ce7..5239ccd 100644 --- a/Source/kwsys/Glob.hxx.in +++ b/Source/kwsys/Glob.hxx.in @@ -59,6 +59,12 @@ public: type(msg.type), content(msg.content) {} + Message& operator=(Message const& msg) + { + this->type = msg.type; + this->content = msg.content; + return *this; + } }; typedef kwsys_stl::vector<Message> GlobMessages; diff --git a/Source/kwsys/Process.h.in b/Source/kwsys/Process.h.in index c5995ea..e35939f 100644 --- a/Source/kwsys/Process.h.in +++ b/Source/kwsys/Process.h.in @@ -36,6 +36,7 @@ # define kwsysProcess_SetPipeShared kwsys_ns(Process_SetPipeShared) # define kwsysProcess_Option_Detach kwsys_ns(Process_Option_Detach) # define kwsysProcess_Option_HideWindow kwsys_ns(Process_Option_HideWindow) +# define kwsysProcess_Option_MergeOutput kwsys_ns(Process_Option_MergeOutput) # define kwsysProcess_Option_Verbatim kwsys_ns(Process_Option_Verbatim) # define kwsysProcess_GetOption kwsys_ns(Process_GetOption) # define kwsysProcess_SetOption kwsys_ns(Process_SetOption) @@ -186,6 +187,12 @@ kwsysEXPORT void kwsysProcess_SetPipeNative(kwsysProcess* cp, int pipe, * 0 = No (default) * 1 = Yes * + * kwsysProcess_Option_MergeOutput = Whether to merge stdout/stderr. + * No content will be returned as stderr. + * Any actual stderr will be on stdout. + * 0 = No (default) + * 1 = Yes + * * kwsysProcess_Option_Verbatim = Whether SetCommand and AddCommand * should treat the first argument * as a verbatim command line @@ -200,6 +207,7 @@ enum kwsysProcess_Option_e { kwsysProcess_Option_HideWindow, kwsysProcess_Option_Detach, + kwsysProcess_Option_MergeOutput, kwsysProcess_Option_Verbatim }; @@ -384,6 +392,7 @@ kwsysEXPORT void kwsysProcess_Kill(kwsysProcess* cp); # undef kwsysProcess_SetPipeShared # undef kwsysProcess_Option_Detach # undef kwsysProcess_Option_HideWindow +# undef kwsysProcess_Option_MergeOutput # undef kwsysProcess_Option_Verbatim # undef kwsysProcess_GetOption # undef kwsysProcess_SetOption diff --git a/Source/kwsys/ProcessUNIX.c b/Source/kwsys/ProcessUNIX.c index 1be6d02..0393a6d 100644 --- a/Source/kwsys/ProcessUNIX.c +++ b/Source/kwsys/ProcessUNIX.c @@ -157,7 +157,7 @@ static void kwsysProcessCleanupDescriptor(int* pfd); static void kwsysProcessClosePipes(kwsysProcess* cp); static int kwsysProcessSetNonBlocking(int fd); static int kwsysProcessCreate(kwsysProcess* cp, int prIndex, - kwsysProcessCreateInformation* si, int* readEnd); + kwsysProcessCreateInformation* si); static void kwsysProcessDestroy(kwsysProcess* cp); static int kwsysProcessSetupOutputPipeFile(int* p, const char* name); static int kwsysProcessSetupOutputPipeNative(int* p, int des[2]); @@ -203,6 +203,10 @@ struct kwsysProcess_s the signal pipe. */ int PipeReadEnds[KWSYSPE_PIPE_COUNT]; + /* Descriptors for the child's ends of the pipes. + Used temporarily during process creation. */ + int PipeChildStd[3]; + /* Write descriptor for child termination signal pipe. */ int SignalPipe; @@ -230,6 +234,9 @@ struct kwsysProcess_s /* Whether to treat command lines as verbatim. */ int Verbatim; + /* Whether to merge stdout/stderr of the child. */ + int MergeOutput; + /* Time at which the child started. Negative for no timeout. */ kwsysProcessTime StartTime; @@ -640,6 +647,7 @@ int kwsysProcess_GetOption(kwsysProcess* cp, int optionId) switch(optionId) { case kwsysProcess_Option_Detach: return cp->OptionDetach; + case kwsysProcess_Option_MergeOutput: return cp->MergeOutput; case kwsysProcess_Option_Verbatim: return cp->Verbatim; default: return 0; } @@ -656,6 +664,7 @@ void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value) switch(optionId) { case kwsysProcess_Option_Detach: cp->OptionDetach = value; break; + case kwsysProcess_Option_MergeOutput: cp->MergeOutput = value; break; case kwsysProcess_Option_Verbatim: cp->Verbatim = value; break; default: break; } @@ -717,7 +726,6 @@ const char* kwsysProcess_GetExceptionString(kwsysProcess* cp) void kwsysProcess_Execute(kwsysProcess* cp) { int i; - kwsysProcessCreateInformation si = {-1, -1, -1, {-1, -1}}; /* Do not execute a second copy simultaneously. */ if(!cp || cp->State == kwsysProcess_State_Executing) @@ -785,7 +793,50 @@ void kwsysProcess_Execute(kwsysProcess* cp) } } - /* Setup the stderr pipe to be shared by all processes. */ + /* Setup the stdin pipe for the first process. */ + if(cp->PipeFileSTDIN) + { + /* Open a file for the child's stdin to read. */ + cp->PipeChildStd[0] = open(cp->PipeFileSTDIN, O_RDONLY); + if(cp->PipeChildStd[0] < 0) + { + kwsysProcessCleanup(cp, 1); + return; + } + + /* Set close-on-exec flag on the pipe's end. */ + if(fcntl(cp->PipeChildStd[0], F_SETFD, FD_CLOEXEC) < 0) + { + kwsysProcessCleanup(cp, 1); + return; + } + } + else if(cp->PipeSharedSTDIN) + { + cp->PipeChildStd[0] = 0; + } + else if(cp->PipeNativeSTDIN[0] >= 0) + { + cp->PipeChildStd[0] = cp->PipeNativeSTDIN[0]; + + /* Set close-on-exec flag on the pipe's ends. The read end will + be dup2-ed into the stdin descriptor after the fork but before + the exec. */ + if((fcntl(cp->PipeNativeSTDIN[0], F_SETFD, FD_CLOEXEC) < 0) || + (fcntl(cp->PipeNativeSTDIN[1], F_SETFD, FD_CLOEXEC) < 0)) + { + kwsysProcessCleanup(cp, 1); + return; + } + } + else + { + cp->PipeChildStd[0] = -1; + } + + /* Create the output pipe for the last process. + We always create this so the pipe can be passed to select even if + it will report closed immediately. */ { /* Create the pipe. */ int p[2]; @@ -796,15 +847,14 @@ void kwsysProcess_Execute(kwsysProcess* cp) } /* Store the pipe. */ - cp->PipeReadEnds[KWSYSPE_PIPE_STDERR] = p[0]; - si.StdErr = p[1]; + cp->PipeReadEnds[KWSYSPE_PIPE_STDOUT] = p[0]; + cp->PipeChildStd[1] = p[1]; /* Set close-on-exec flag on the pipe's ends. */ if((fcntl(p[0], F_SETFD, FD_CLOEXEC) < 0) || (fcntl(p[1], F_SETFD, FD_CLOEXEC) < 0)) { kwsysProcessCleanup(cp, 1); - kwsysProcessCleanupDescriptor(&si.StdErr); return; } @@ -813,41 +863,93 @@ void kwsysProcess_Execute(kwsysProcess* cp) if(!kwsysProcessSetNonBlocking(p[0])) { kwsysProcessCleanup(cp, 1); - kwsysProcessCleanupDescriptor(&si.StdErr); return; } } - /* Replace the stderr pipe with a file if requested. In this case - the select call will report that stderr is closed immediately. */ - if(cp->PipeFileSTDERR) + if (cp->PipeFileSTDOUT) { - if(!kwsysProcessSetupOutputPipeFile(&si.StdErr, cp->PipeFileSTDERR)) + /* Use a file for stdout. */ + if(!kwsysProcessSetupOutputPipeFile(&cp->PipeChildStd[1], + cp->PipeFileSTDOUT)) + { + kwsysProcessCleanup(cp, 1); + return; + } + } + else if (cp->PipeSharedSTDOUT) + { + /* Use the parent stdout. */ + kwsysProcessCleanupDescriptor(&cp->PipeChildStd[1]); + cp->PipeChildStd[1] = 1; + } + else if (cp->PipeNativeSTDOUT[1] >= 0) + { + /* Use the given descriptor for stdout. */ + if(!kwsysProcessSetupOutputPipeNative(&cp->PipeChildStd[1], + cp->PipeNativeSTDOUT)) { kwsysProcessCleanup(cp, 1); - kwsysProcessCleanupDescriptor(&si.StdErr); return; } } - /* Replace the stderr pipe with the parent's if requested. In this - case the select call will report that stderr is closed - immediately. */ - if(cp->PipeSharedSTDERR) + /* Create stderr pipe to be shared by all processes in the pipeline. + We always create this so the pipe can be passed to select even if + it will report closed immediately. */ + { + /* Create the pipe. */ + int p[2]; + if(pipe(p KWSYSPE_VMS_NONBLOCK) < 0) + { + kwsysProcessCleanup(cp, 1); + return; + } + + /* Store the pipe. */ + cp->PipeReadEnds[KWSYSPE_PIPE_STDERR] = p[0]; + cp->PipeChildStd[2] = p[1]; + + /* Set close-on-exec flag on the pipe's ends. */ + if((fcntl(p[0], F_SETFD, FD_CLOEXEC) < 0) || + (fcntl(p[1], F_SETFD, FD_CLOEXEC) < 0)) { - kwsysProcessCleanupDescriptor(&si.StdErr); - si.StdErr = 2; + kwsysProcessCleanup(cp, 1); + return; } - /* Replace the stderr pipe with the native pipe provided if any. In - this case the select call will report that stderr is closed - immediately. */ - if(cp->PipeNativeSTDERR[1] >= 0) + /* Set to non-blocking in case select lies, or for the polling + implementation. */ + if(!kwsysProcessSetNonBlocking(p[0])) { - if(!kwsysProcessSetupOutputPipeNative(&si.StdErr, cp->PipeNativeSTDERR)) + kwsysProcessCleanup(cp, 1); + return; + } + } + + if (cp->PipeFileSTDERR) + { + /* Use a file for stderr. */ + if(!kwsysProcessSetupOutputPipeFile(&cp->PipeChildStd[2], + cp->PipeFileSTDERR)) + { + kwsysProcessCleanup(cp, 1); + return; + } + } + else if (cp->PipeSharedSTDERR) + { + /* Use the parent stderr. */ + kwsysProcessCleanupDescriptor(&cp->PipeChildStd[2]); + cp->PipeChildStd[2] = 2; + } + else if (cp->PipeNativeSTDERR[1] >= 0) + { + /* Use the given handle for stderr. */ + if(!kwsysProcessSetupOutputPipeNative(&cp->PipeChildStd[2], + cp->PipeNativeSTDERR)) { kwsysProcessCleanup(cp, 1); - kwsysProcessCleanupDescriptor(&si.StdErr); return; } } @@ -859,54 +961,85 @@ void kwsysProcess_Execute(kwsysProcess* cp) /* Create the pipeline of processes. */ { - int readEnd = -1; - int failed = 0; + kwsysProcessCreateInformation si = {-1, -1, -1, {-1, -1}}; + int nextStdIn = cp->PipeChildStd[0]; for(i=0; i < cp->NumberOfCommands; ++i) { - if(!kwsysProcessCreate(cp, i, &si, &readEnd)) + /* Setup the process's pipes. */ + si.StdIn = nextStdIn; + if (i == cp->NumberOfCommands-1) { - failed = 1; + nextStdIn = -1; + si.StdOut = cp->PipeChildStd[1]; } - - /* Set the output pipe of the last process to be non-blocking in - case select lies, or for the polling implementation. */ - if(i == (cp->NumberOfCommands-1) && !kwsysProcessSetNonBlocking(readEnd)) - { - failed = 1; - } - - if(failed) + else { - kwsysProcessCleanup(cp, 1); - - /* Release resources that may have been allocated for this - process before an error occurred. */ - kwsysProcessCleanupDescriptor(&readEnd); - if(si.StdIn != 0) - { - kwsysProcessCleanupDescriptor(&si.StdIn); - } - if(si.StdOut != 1) + /* Create a pipe to sit between the children. */ + int p[2] = {-1,-1}; + if(pipe(p KWSYSPE_VMS_NONBLOCK) < 0) { - kwsysProcessCleanupDescriptor(&si.StdOut); + if (nextStdIn != cp->PipeChildStd[0]) + { + kwsysProcessCleanupDescriptor(&nextStdIn); + } + kwsysProcessCleanup(cp, 1); + return; } - if(si.StdErr != 2) + + /* Set close-on-exec flag on the pipe's ends. */ + if((fcntl(p[0], F_SETFD, FD_CLOEXEC) < 0) || + (fcntl(p[1], F_SETFD, FD_CLOEXEC) < 0)) { - kwsysProcessCleanupDescriptor(&si.StdErr); + close(p[0]); + close(p[1]); + if (nextStdIn != cp->PipeChildStd[0]) + { + kwsysProcessCleanupDescriptor(&nextStdIn); + } + kwsysProcessCleanup(cp, 1); + return; } + nextStdIn = p[0]; + si.StdOut = p[1]; + } + si.StdErr = cp->MergeOutput? cp->PipeChildStd[1] : cp->PipeChildStd[2]; + + { + int res = kwsysProcessCreate(cp, i, &si); + + /* Close our copies of pipes used between children. */ + if (si.StdIn != cp->PipeChildStd[0]) + { + kwsysProcessCleanupDescriptor(&si.StdIn); + } + if (si.StdOut != cp->PipeChildStd[1]) + { + kwsysProcessCleanupDescriptor(&si.StdOut); + } + if (si.StdErr != cp->PipeChildStd[2] && !cp->MergeOutput) + { + kwsysProcessCleanupDescriptor(&si.StdErr); + } + + if(!res) + { kwsysProcessCleanupDescriptor(&si.ErrorPipe[0]); kwsysProcessCleanupDescriptor(&si.ErrorPipe[1]); + if (nextStdIn != cp->PipeChildStd[0]) + { + kwsysProcessCleanupDescriptor(&nextStdIn); + } + kwsysProcessCleanup(cp, 1); return; } } - /* Save a handle to the output pipe for the last process. */ - cp->PipeReadEnds[KWSYSPE_PIPE_STDOUT] = readEnd; + } } - /* The parent process does not need the output pipe write ends. */ - if(si.StdErr != 2) + /* The parent process does not need the child's pipe ends. */ + for (i=0; i < 3; ++i) { - kwsysProcessCleanupDescriptor(&si.StdErr); + kwsysProcessCleanupDescriptor(&cp->PipeChildStd[i]); } /* Restore the working directory. */ @@ -1414,6 +1547,10 @@ static int kwsysProcessInitialize(kwsysProcess* cp) { cp->PipeReadEnds[i] = -1; } + for(i=0; i < 3; ++i) + { + cp->PipeChildStd[i] = -1; + } cp->SignalPipe = -1; cp->SelectError = 0; cp->StartTime.tv_sec = -1; @@ -1548,13 +1685,17 @@ static void kwsysProcessCleanup(kwsysProcess* cp, int error) { kwsysProcessCleanupDescriptor(&cp->PipeReadEnds[i]); } + for(i=0; i < 3; ++i) + { + kwsysProcessCleanupDescriptor(&cp->PipeChildStd[i]); + } } /*--------------------------------------------------------------------------*/ /* Close the given file descriptor if it is open. Reset its value to -1. */ static void kwsysProcessCleanupDescriptor(int* pfd) { - if(pfd && *pfd >= 0) + if(pfd && *pfd > 2) { /* Keep trying to close until it is not interrupted by a * signal. */ @@ -1615,100 +1756,8 @@ int decc$set_child_standard_streams(int fd1, int fd2, int fd3); /*--------------------------------------------------------------------------*/ static int kwsysProcessCreate(kwsysProcess* cp, int prIndex, - kwsysProcessCreateInformation* si, int* readEnd) + kwsysProcessCreateInformation* si) { - /* Setup the process's stdin. */ - if(prIndex > 0) - { - si->StdIn = *readEnd; - *readEnd = 0; - } - else if(cp->PipeFileSTDIN) - { - /* Open a file for the child's stdin to read. */ - si->StdIn = open(cp->PipeFileSTDIN, O_RDONLY); - if(si->StdIn < 0) - { - return 0; - } - - /* Set close-on-exec flag on the pipe's end. */ - if(fcntl(si->StdIn, F_SETFD, FD_CLOEXEC) < 0) - { - return 0; - } - } - else if(cp->PipeSharedSTDIN) - { - si->StdIn = 0; - } - else if(cp->PipeNativeSTDIN[0] >= 0) - { - si->StdIn = cp->PipeNativeSTDIN[0]; - - /* Set close-on-exec flag on the pipe's ends. The read end will - be dup2-ed into the stdin descriptor after the fork but before - the exec. */ - if((fcntl(cp->PipeNativeSTDIN[0], F_SETFD, FD_CLOEXEC) < 0) || - (fcntl(cp->PipeNativeSTDIN[1], F_SETFD, FD_CLOEXEC) < 0)) - { - return 0; - } - } - else - { - si->StdIn = -1; - } - - /* Setup the process's stdout. */ - { - /* Create the pipe. */ - int p[2]; - if(pipe(p KWSYSPE_VMS_NONBLOCK) < 0) - { - return 0; - } - *readEnd = p[0]; - si->StdOut = p[1]; - - /* Set close-on-exec flag on the pipe's ends. */ - if((fcntl(p[0], F_SETFD, FD_CLOEXEC) < 0) || - (fcntl(p[1], F_SETFD, FD_CLOEXEC) < 0)) - { - return 0; - } - } - - /* Replace the stdout pipe with a file if requested. In this case - the select call will report that stdout is closed immediately. */ - if(prIndex == cp->NumberOfCommands-1 && cp->PipeFileSTDOUT) - { - if(!kwsysProcessSetupOutputPipeFile(&si->StdOut, cp->PipeFileSTDOUT)) - { - return 0; - } - } - - /* Replace the stdout pipe with the parent's if requested. In this - case the select call will report that stderr is closed - immediately. */ - if(prIndex == cp->NumberOfCommands-1 && cp->PipeSharedSTDOUT) - { - kwsysProcessCleanupDescriptor(&si->StdOut); - si->StdOut = 1; - } - - /* Replace the stdout pipe with the native pipe provided if any. In - this case the select call will report that stdout is closed - immediately. */ - if(prIndex == cp->NumberOfCommands-1 && cp->PipeNativeSTDOUT[1] >= 0) - { - if(!kwsysProcessSetupOutputPipeNative(&si->StdOut, cp->PipeNativeSTDOUT)) - { - return 0; - } - } - /* Create the error reporting pipe. */ if(pipe(si->ErrorPipe) < 0) { @@ -1819,19 +1868,6 @@ static int kwsysProcessCreate(kwsysProcess* cp, int prIndex, } } - /* Successfully created this child process. */ - if(prIndex > 0 || si->StdIn > 0) - { - /* The parent process does not need the input pipe read end. */ - kwsysProcessCleanupDescriptor(&si->StdIn); - } - - /* The parent process does not need the output pipe write ends. */ - if(si->StdOut != 1) - { - kwsysProcessCleanupDescriptor(&si->StdOut); - } - return 1; } diff --git a/Source/kwsys/ProcessWin32.c b/Source/kwsys/ProcessWin32.c index c2965ea..f630171 100644 --- a/Source/kwsys/ProcessWin32.c +++ b/Source/kwsys/ProcessWin32.c @@ -94,6 +94,11 @@ typedef struct kwsysProcessCreateInformation_s { /* Windows child startup control data. */ STARTUPINFOW StartupInfo; + + /* Original handles before making inherited duplicates. */ + HANDLE hStdInput; + HANDLE hStdOutput; + HANDLE hStdError; } kwsysProcessCreateInformation; @@ -107,15 +112,12 @@ static void kwsysProcessPipeThreadWakePipe(kwsysProcess* cp, kwsysProcessPipeData* td); static int kwsysProcessInitialize(kwsysProcess* cp); static int kwsysProcessCreate(kwsysProcess* cp, int index, - kwsysProcessCreateInformation* si, - PHANDLE readEnd); + kwsysProcessCreateInformation* si); static void kwsysProcessDestroy(kwsysProcess* cp, int event); static int kwsysProcessSetupOutputPipeFile(PHANDLE handle, const char* name); -static int kwsysProcessSetupSharedPipe(DWORD nStdHandle, PHANDLE handle); -static int kwsysProcessSetupPipeNative(PHANDLE handle, HANDLE p[2], - int isWrite); +static void kwsysProcessSetupSharedPipe(DWORD nStdHandle, PHANDLE handle); +static void kwsysProcessSetupPipeNative(HANDLE native, PHANDLE handle); static void kwsysProcessCleanupHandle(PHANDLE h); -static void kwsysProcessCleanupHandleSafe(PHANDLE h, DWORD nStdHandle); static void kwsysProcessCleanup(kwsysProcess* cp, int error); static void kwsysProcessCleanErrorMessage(kwsysProcess* cp); static int kwsysProcessComputeCommandLength(kwsysProcess* cp, @@ -224,6 +226,9 @@ struct kwsysProcess_s /* Whether to treat command lines as verbatim. */ int Verbatim; + /* Whether to merge stdout/stderr of the child. */ + int MergeOutput; + /* Mutex to protect the shared index used by threads to report data. */ HANDLE SharedIndexMutex; @@ -306,6 +311,10 @@ struct kwsysProcess_s /* Real working directory of our own process. */ DWORD RealWorkingDirectoryLength; wchar_t* RealWorkingDirectory; + + /* Own handles for the child's ends of the pipes in the parent process. + Used temporarily during process creation. */ + HANDLE PipeChildStd[3]; }; /*--------------------------------------------------------------------------*/ @@ -446,6 +455,10 @@ kwsysProcess* kwsysProcess_New(void) return 0; } } + for(i=0; i < 3; ++i) + { + cp->PipeChildStd[i] = INVALID_HANDLE_VALUE; + } return cp; } @@ -796,6 +809,7 @@ int kwsysProcess_GetOption(kwsysProcess* cp, int optionId) { case kwsysProcess_Option_Detach: return cp->OptionDetach; case kwsysProcess_Option_HideWindow: return cp->HideWindow; + case kwsysProcess_Option_MergeOutput: return cp->MergeOutput; case kwsysProcess_Option_Verbatim: return cp->Verbatim; default: return 0; } @@ -813,6 +827,7 @@ void kwsysProcess_SetOption(kwsysProcess* cp, int optionId, int value) { case kwsysProcess_Option_Detach: cp->OptionDetach = value; break; case kwsysProcess_Option_HideWindow: cp->HideWindow = value; break; + case kwsysProcess_Option_MergeOutput: cp->MergeOutput = value; break; case kwsysProcess_Option_Verbatim: cp->Verbatim = value; break; default: break; } @@ -875,9 +890,6 @@ void kwsysProcess_Execute(kwsysProcess* cp) { int i; - /* Child startup control data. */ - kwsysProcessCreateInformation si; - /* Do not execute a second time. */ if(!cp || cp->State == kwsysProcess_State_Executing) { @@ -914,117 +926,211 @@ void kwsysProcess_Execute(kwsysProcess* cp) SetCurrentDirectoryW(cp->WorkingDirectory); } - /* Initialize startup info data. */ - ZeroMemory(&si, sizeof(si)); - si.StartupInfo.cb = sizeof(si.StartupInfo); - - /* Decide whether a child window should be shown. */ - si.StartupInfo.dwFlags |= STARTF_USESHOWWINDOW; - si.StartupInfo.wShowWindow = - (unsigned short)(cp->HideWindow?SW_HIDE:SW_SHOWDEFAULT); - - /* Connect the child's output pipes to the threads. */ - si.StartupInfo.dwFlags |= STARTF_USESTDHANDLES; - /* Create stderr pipe to be shared by all processes in the pipeline. - Neither end is directly inherited. */ - if(!CreatePipe(&cp->Pipe[KWSYSPE_PIPE_STDERR].Read, - &cp->Pipe[KWSYSPE_PIPE_STDERR].Write, 0, 0)) + /* Setup the stdin pipe for the first process. */ + if(cp->PipeFileSTDIN) { - kwsysProcessCleanup(cp, 1); - return; + /* Create a handle to read a file for stdin. */ + wchar_t* wstdin = kwsysEncoding_DupToWide(cp->PipeFileSTDIN); + cp->PipeChildStd[0] = + CreateFileW(wstdin, GENERIC_READ|GENERIC_WRITE, + FILE_SHARE_READ|FILE_SHARE_WRITE, + 0, OPEN_EXISTING, 0, 0); + free(wstdin); + if(cp->PipeChildStd[0] == INVALID_HANDLE_VALUE) + { + kwsysProcessCleanup(cp, 1); + return; + } + } + else if(cp->PipeSharedSTDIN) + { + /* Share this process's stdin with the child. */ + kwsysProcessSetupSharedPipe(STD_INPUT_HANDLE, &cp->PipeChildStd[0]); + } + else if(cp->PipeNativeSTDIN[0]) + { + /* Use the provided native pipe. */ + kwsysProcessSetupPipeNative(cp->PipeNativeSTDIN[0], &cp->PipeChildStd[0]); + } + else + { + /* Explicitly give the child no stdin. */ + cp->PipeChildStd[0] = INVALID_HANDLE_VALUE; } - /* Create an inherited duplicate of the write end, but do not - close the non-inherited version. We need to keep it open - to use in waking up the pipe threads. */ - if(!DuplicateHandle(GetCurrentProcess(), cp->Pipe[KWSYSPE_PIPE_STDERR].Write, - GetCurrentProcess(), &si.StartupInfo.hStdError, - 0, TRUE, DUPLICATE_SAME_ACCESS)) + /* Create the output pipe for the last process. + We always create this so the pipe thread can run even if we + do not end up giving the write end to the child below. */ + if(!CreatePipe(&cp->Pipe[KWSYSPE_PIPE_STDOUT].Read, + &cp->Pipe[KWSYSPE_PIPE_STDOUT].Write, 0, 0)) { kwsysProcessCleanup(cp, 1); - kwsysProcessCleanupHandle(&si.StartupInfo.hStdError); return; } - /* Replace the stderr pipe with a file if requested. In this case - the pipe thread will still run but never report data. */ - if(cp->PipeFileSTDERR) + if(cp->PipeFileSTDOUT) { - if(!kwsysProcessSetupOutputPipeFile(&si.StartupInfo.hStdError, - cp->PipeFileSTDERR)) + /* Use a file for stdout. */ + if(!kwsysProcessSetupOutputPipeFile(&cp->PipeChildStd[1], + cp->PipeFileSTDOUT)) { kwsysProcessCleanup(cp, 1); - kwsysProcessCleanupHandle(&si.StartupInfo.hStdError); return; } } - - /* Replace the stderr pipe with the parent process's if requested. - In this case the pipe thread will still run but never report - data. */ - if(cp->PipeSharedSTDERR) + else if(cp->PipeSharedSTDOUT) + { + /* Use the parent stdout. */ + kwsysProcessSetupSharedPipe(STD_OUTPUT_HANDLE, &cp->PipeChildStd[1]); + } + else if(cp->PipeNativeSTDOUT[1]) { - if(!kwsysProcessSetupSharedPipe(STD_ERROR_HANDLE, - &si.StartupInfo.hStdError)) + /* Use the given handle for stdout. */ + kwsysProcessSetupPipeNative(cp->PipeNativeSTDOUT[1], &cp->PipeChildStd[1]); + } + else + { + /* Use our pipe for stdout. Duplicate the handle since our waker + thread will use the original. Do not make it inherited yet. */ + if(!DuplicateHandle(GetCurrentProcess(), + cp->Pipe[KWSYSPE_PIPE_STDOUT].Write, + GetCurrentProcess(), &cp->PipeChildStd[1], + 0, FALSE, DUPLICATE_SAME_ACCESS)) { kwsysProcessCleanup(cp, 1); - kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError, - STD_ERROR_HANDLE); return; } } - /* Replace the stderr pipe with the native pipe provided if any. In - this case the pipe thread will still run but never report - data. */ - if(cp->PipeNativeSTDERR[1]) + /* Create stderr pipe to be shared by all processes in the pipeline. + We always create this so the pipe thread can run even if we do not + end up giving the write end to the child below. */ + if(!CreatePipe(&cp->Pipe[KWSYSPE_PIPE_STDERR].Read, + &cp->Pipe[KWSYSPE_PIPE_STDERR].Write, 0, 0)) + { + kwsysProcessCleanup(cp, 1); + return; + } + + if(cp->PipeFileSTDERR) + { + /* Use a file for stderr. */ + if(!kwsysProcessSetupOutputPipeFile(&cp->PipeChildStd[2], + cp->PipeFileSTDERR)) + { + kwsysProcessCleanup(cp, 1); + return; + } + } + else if(cp->PipeSharedSTDERR) + { + /* Use the parent stderr. */ + kwsysProcessSetupSharedPipe(STD_ERROR_HANDLE, &cp->PipeChildStd[2]); + } + else if(cp->PipeNativeSTDERR[1]) { - if(!kwsysProcessSetupPipeNative(&si.StartupInfo.hStdError, - cp->PipeNativeSTDERR, 1)) + /* Use the given handle for stderr. */ + kwsysProcessSetupPipeNative(cp->PipeNativeSTDERR[1], &cp->PipeChildStd[2]); + } + else + { + /* Use our pipe for stderr. Duplicate the handle since our waker + thread will use the original. Do not make it inherited yet. */ + if(!DuplicateHandle(GetCurrentProcess(), + cp->Pipe[KWSYSPE_PIPE_STDERR].Write, + GetCurrentProcess(), &cp->PipeChildStd[2], + 0, FALSE, DUPLICATE_SAME_ACCESS)) { kwsysProcessCleanup(cp, 1); - kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError, - STD_ERROR_HANDLE); return; } } /* Create the pipeline of processes. */ { - HANDLE readEnd = 0; + /* Child startup control data. */ + kwsysProcessCreateInformation si; + HANDLE nextStdInput = cp->PipeChildStd[0]; + + /* Initialize startup info data. */ + ZeroMemory(&si, sizeof(si)); + si.StartupInfo.cb = sizeof(si.StartupInfo); + + /* Decide whether a child window should be shown. */ + si.StartupInfo.dwFlags |= STARTF_USESHOWWINDOW; + si.StartupInfo.wShowWindow = + (unsigned short)(cp->HideWindow?SW_HIDE:SW_SHOWDEFAULT); + + /* Connect the child's output pipes to the threads. */ + si.StartupInfo.dwFlags |= STARTF_USESTDHANDLES; + for(i=0; i < cp->NumberOfCommands; ++i) { - if(kwsysProcessCreate(cp, i, &si, &readEnd)) + /* Setup the process's pipes. */ + si.hStdInput = nextStdInput; + if (i == cp->NumberOfCommands-1) + { + /* The last child gets the overall stdout. */ + nextStdInput = INVALID_HANDLE_VALUE; + si.hStdOutput = cp->PipeChildStd[1]; + } + else + { + /* Create a pipe to sit between the children. */ + HANDLE p[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}; + if (!CreatePipe(&p[0], &p[1], 0, 0)) + { + if (nextStdInput != cp->PipeChildStd[0]) + { + kwsysProcessCleanupHandle(&nextStdInput); + } + kwsysProcessCleanup(cp, 1); + return; + } + nextStdInput = p[0]; + si.hStdOutput = p[1]; + } + si.hStdError = cp->MergeOutput? cp->PipeChildStd[1] : cp->PipeChildStd[2]; + + { + int res = kwsysProcessCreate(cp, i, &si); + + /* Close our copies of pipes used between children. */ + if (si.hStdInput != cp->PipeChildStd[0]) + { + kwsysProcessCleanupHandle(&si.hStdInput); + } + if (si.hStdOutput != cp->PipeChildStd[1]) + { + kwsysProcessCleanupHandle(&si.hStdOutput); + } + if (si.hStdError != cp->PipeChildStd[2] && !cp->MergeOutput) + { + kwsysProcessCleanupHandle(&si.hStdError); + } + if (res) { cp->ProcessEvents[i+1] = cp->ProcessInformation[i].hProcess; } else { + if (nextStdInput != cp->PipeChildStd[0]) + { + kwsysProcessCleanupHandle(&nextStdInput); + } kwsysProcessCleanup(cp, 1); - - /* Release resources that may have been allocated for this - process before an error occurred. */ - kwsysProcessCleanupHandle(&readEnd); - kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdInput, - STD_INPUT_HANDLE); - kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdOutput, - STD_OUTPUT_HANDLE); - kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError, - STD_ERROR_HANDLE); return; } } - - /* Save a handle to the output pipe for the last process. */ - cp->Pipe[KWSYSPE_PIPE_STDOUT].Read = readEnd; + } } - /* Close the inherited handles to the stderr pipe shared by all - processes in the pipeline. The stdout and stdin pipes are not - shared among all children and are therefore closed by - kwsysProcessCreate after each child is created. */ - kwsysProcessCleanupHandleSafe(&si.StartupInfo.hStdError, STD_ERROR_HANDLE); + /* The parent process does not need the child's pipe ends. */ + for (i=0; i < 3; ++i) + { + kwsysProcessCleanupHandle(&cp->PipeChildStd[i]); + } /* Restore the working directory. */ if(cp->RealWorkingDirectory) @@ -1543,162 +1649,90 @@ int kwsysProcessInitialize(kwsysProcess* cp) } } } + { + int i; + for (i=0; i < 3; ++i) + { + cp->PipeChildStd[i] = INVALID_HANDLE_VALUE; + } + } return 1; } /*--------------------------------------------------------------------------*/ -int kwsysProcessCreate(kwsysProcess* cp, int index, - kwsysProcessCreateInformation* si, - PHANDLE readEnd) +static int kwsysProcessCreateChildHandle(PHANDLE out, HANDLE in, int isStdIn) { - /* Setup the process's stdin. */ - if(*readEnd) - { - /* Create an inherited duplicate of the read end from the output - pipe of the previous process. This also closes the - non-inherited version. */ - if(!DuplicateHandle(GetCurrentProcess(), *readEnd, - GetCurrentProcess(), readEnd, - 0, TRUE, (DUPLICATE_CLOSE_SOURCE | - DUPLICATE_SAME_ACCESS))) - { - return 0; - } - si->StartupInfo.hStdInput = *readEnd; + DWORD flags; - /* This function is done with this handle. */ - *readEnd = 0; - } - else if(cp->PipeFileSTDIN) - { - /* Create a handle to read a file for stdin. */ - wchar_t* wstdin = kwsysEncoding_DupToWide(cp->PipeFileSTDIN); - HANDLE fin = CreateFileW(wstdin, GENERIC_READ|GENERIC_WRITE, - FILE_SHARE_READ|FILE_SHARE_WRITE, - 0, OPEN_EXISTING, 0, 0); - free(wstdin); - if(fin == INVALID_HANDLE_VALUE) - { - return 0; - } - /* Create an inherited duplicate of the handle. This also closes - the non-inherited version. */ - if(!DuplicateHandle(GetCurrentProcess(), fin, - GetCurrentProcess(), &fin, - 0, TRUE, (DUPLICATE_CLOSE_SOURCE | - DUPLICATE_SAME_ACCESS))) - { - return 0; - } - si->StartupInfo.hStdInput = fin; - } - else if(cp->PipeSharedSTDIN) - { - /* Share this process's stdin with the child. */ - if(!kwsysProcessSetupSharedPipe(STD_INPUT_HANDLE, - &si->StartupInfo.hStdInput)) - { - return 0; - } - } - else if(cp->PipeNativeSTDIN[0]) + /* Check whether the handle is valid for this process. */ + if (in != INVALID_HANDLE_VALUE && GetHandleInformation(in, &flags)) { - /* Use the provided native pipe. */ - if(!kwsysProcessSetupPipeNative(&si->StartupInfo.hStdInput, - cp->PipeNativeSTDIN, 0)) + /* Use the handle as-is if it is already inherited. */ + if (flags & HANDLE_FLAG_INHERIT) { - return 0; + *out = in; + return 1; } + + /* Create an inherited copy of this handle. */ + return DuplicateHandle(GetCurrentProcess(), in, + GetCurrentProcess(), out, + 0, TRUE, DUPLICATE_SAME_ACCESS); } else { - /* Explicitly give the child no stdin. */ - si->StartupInfo.hStdInput = INVALID_HANDLE_VALUE; + /* The given handle is not valid for this process. Some child + processes may break if they do not have a valid standard handle, + so open NUL to give to the child. */ + SECURITY_ATTRIBUTES sa; + ZeroMemory(&sa, sizeof(sa)); + sa.nLength = (DWORD)sizeof(sa); + sa.bInheritHandle = 1; + *out = CreateFileW(L"NUL", + (isStdIn ? GENERIC_READ : + (GENERIC_WRITE | FILE_READ_ATTRIBUTES)), + FILE_SHARE_READ|FILE_SHARE_WRITE, + &sa, OPEN_EXISTING, 0, 0); + return *out != INVALID_HANDLE_VALUE; } - /* Setup the process's stdout. */ - { - DWORD maybeClose = DUPLICATE_CLOSE_SOURCE; - HANDLE writeEnd; +} - /* Create the output pipe for this process. Neither end is directly - inherited. */ - if(!CreatePipe(readEnd, &writeEnd, 0, 0)) - { - return 0; - } +/*--------------------------------------------------------------------------*/ +int kwsysProcessCreate(kwsysProcess* cp, int index, + kwsysProcessCreateInformation* si) +{ + int res = - /* Create an inherited duplicate of the write end. Close the - non-inherited version unless this is the last process. Save the - non-inherited write end of the last process. */ - if(index == cp->NumberOfCommands-1) - { - cp->Pipe[KWSYSPE_PIPE_STDOUT].Write = writeEnd; - maybeClose = 0; - } - if(!DuplicateHandle(GetCurrentProcess(), writeEnd, - GetCurrentProcess(), &writeEnd, - 0, TRUE, (maybeClose | DUPLICATE_SAME_ACCESS))) - { - return 0; - } - si->StartupInfo.hStdOutput = writeEnd; - } + /* Create inherited copies the handles. */ + kwsysProcessCreateChildHandle(&si->StartupInfo.hStdInput, + si->hStdInput, 1) && + kwsysProcessCreateChildHandle(&si->StartupInfo.hStdOutput, + si->hStdOutput, 0) && + kwsysProcessCreateChildHandle(&si->StartupInfo.hStdError, + si->hStdError, 0) && - /* Replace the stdout pipe with a file if requested. In this case - the pipe thread will still run but never report data. */ - if(index == cp->NumberOfCommands-1 && cp->PipeFileSTDOUT) - { - if(!kwsysProcessSetupOutputPipeFile(&si->StartupInfo.hStdOutput, - cp->PipeFileSTDOUT)) - { - return 0; - } - } + /* Create the child in a suspended state so we can wait until all + children have been created before running any one. */ + CreateProcessW(0, cp->Commands[index], 0, 0, TRUE, CREATE_SUSPENDED, 0, + 0, &si->StartupInfo, &cp->ProcessInformation[index]); - /* Replace the stdout pipe of the last child with the parent - process's if requested. In this case the pipe thread will still - run but never report data. */ - if(index == cp->NumberOfCommands-1 && cp->PipeSharedSTDOUT) + /* Close the inherited copies of the handles. */ + if (si->StartupInfo.hStdInput != si->hStdInput) { - if(!kwsysProcessSetupSharedPipe(STD_OUTPUT_HANDLE, - &si->StartupInfo.hStdOutput)) - { - return 0; - } + kwsysProcessCleanupHandle(&si->StartupInfo.hStdInput); } - - /* Replace the stdout pipe with the native pipe provided if any. In - this case the pipe thread will still run but never report - data. */ - if(index == cp->NumberOfCommands-1 && cp->PipeNativeSTDOUT[1]) + if (si->StartupInfo.hStdOutput != si->hStdOutput) { - if(!kwsysProcessSetupPipeNative(&si->StartupInfo.hStdOutput, - cp->PipeNativeSTDOUT, 1)) - { - return 0; - } + kwsysProcessCleanupHandle(&si->StartupInfo.hStdOutput); } - - /* Create the child in a suspended state so we can wait until all - children have been created before running any one. */ - if(!CreateProcessW(0, cp->Commands[index], 0, 0, TRUE, CREATE_SUSPENDED, 0, - 0, &si->StartupInfo, &cp->ProcessInformation[index])) + if (si->StartupInfo.hStdError != si->hStdError) { - return 0; + kwsysProcessCleanupHandle(&si->StartupInfo.hStdError); } - /* Successfully created this child process. Close the current - process's copies of the inherited stdout and stdin handles. The - stderr handle is shared among all children and is closed by - kwsysProcess_Execute after all children have been created. */ - kwsysProcessCleanupHandleSafe(&si->StartupInfo.hStdInput, - STD_INPUT_HANDLE); - kwsysProcessCleanupHandleSafe(&si->StartupInfo.hStdOutput, - STD_OUTPUT_HANDLE); - - return 1; + return res; } /*--------------------------------------------------------------------------*/ @@ -1763,7 +1797,7 @@ int kwsysProcessSetupOutputPipeFile(PHANDLE phandle, const char* name) return 1; } - /* Close the existing inherited handle. */ + /* Close the existing handle. */ kwsysProcessCleanupHandle(phandle); /* Create a handle to write a file for the pipe. */ @@ -1776,103 +1810,27 @@ int kwsysProcessSetupOutputPipeFile(PHANDLE phandle, const char* name) return 0; } - /* Create an inherited duplicate of the handle. This also closes - the non-inherited version. */ - if(!DuplicateHandle(GetCurrentProcess(), fout, - GetCurrentProcess(), &fout, - 0, TRUE, (DUPLICATE_CLOSE_SOURCE | - DUPLICATE_SAME_ACCESS))) - { - return 0; - } - /* Assign the replacement handle. */ *phandle = fout; return 1; } /*--------------------------------------------------------------------------*/ -int kwsysProcessSetupSharedPipe(DWORD nStdHandle, PHANDLE handle) +void kwsysProcessSetupSharedPipe(DWORD nStdHandle, PHANDLE handle) { - /* Check whether the handle to be shared is already inherited. */ - DWORD flags; - int inherited = 0; - if(GetHandleInformation(GetStdHandle(nStdHandle), &flags) && - (flags & HANDLE_FLAG_INHERIT)) - { - inherited = 1; - } - - /* Cleanup the previous handle. */ + /* Close the existing handle. */ kwsysProcessCleanupHandle(handle); - - /* If the standard handle is not inherited then duplicate it to - create an inherited copy. Do not close the original handle when - duplicating! */ - if(inherited) - { - *handle = GetStdHandle(nStdHandle); - return 1; - } - else if(DuplicateHandle(GetCurrentProcess(), GetStdHandle(nStdHandle), - GetCurrentProcess(), handle, - 0, TRUE, DUPLICATE_SAME_ACCESS)) - { - return 1; - } - else - { - /* The given standard handle is not valid for this process. Some - child processes may break if they do not have a valid standard - pipe, so give the child an empty pipe. For the stdin pipe we - want to close the write end and give the read end to the child. - For stdout and stderr we want to close the read end and give - the write end to the child. */ - int child_end = (nStdHandle == STD_INPUT_HANDLE)? 0:1; - int parent_end = (nStdHandle == STD_INPUT_HANDLE)? 1:0; - HANDLE emptyPipe[2]; - if(!CreatePipe(&emptyPipe[0], &emptyPipe[1], 0, 0)) - { - return 0; - } - - /* Close the non-inherited end so the pipe will be broken - immediately. */ - CloseHandle(emptyPipe[parent_end]); - - /* Create an inherited duplicate of the handle. This also - closes the non-inherited version. */ - if(!DuplicateHandle(GetCurrentProcess(), emptyPipe[child_end], - GetCurrentProcess(), &emptyPipe[child_end], - 0, TRUE, (DUPLICATE_CLOSE_SOURCE | - DUPLICATE_SAME_ACCESS))) - { - return 0; - } - - /* Give the inherited handle to the child. */ - *handle = emptyPipe[child_end]; - return 1; - } + /* Store the new standard handle. */ + *handle = GetStdHandle(nStdHandle); } /*--------------------------------------------------------------------------*/ -int kwsysProcessSetupPipeNative(PHANDLE handle, HANDLE p[2], int isWrite) +void kwsysProcessSetupPipeNative(HANDLE native, PHANDLE handle) { - /* Close the existing inherited handle. */ + /* Close the existing handle. */ kwsysProcessCleanupHandle(handle); - - /* Create an inherited duplicate of the handle. This also closes - the non-inherited version. */ - if(!DuplicateHandle(GetCurrentProcess(), p[isWrite? 1:0], - GetCurrentProcess(), handle, - 0, TRUE, (DUPLICATE_CLOSE_SOURCE | - DUPLICATE_SAME_ACCESS))) - { - return 0; - } - - return 1; + /* Store the new given handle. */ + *handle = native; } /*--------------------------------------------------------------------------*/ @@ -1880,23 +1838,13 @@ int kwsysProcessSetupPipeNative(PHANDLE handle, HANDLE p[2], int isWrite) /* Close the given handle if it is open. Reset its value to 0. */ void kwsysProcessCleanupHandle(PHANDLE h) { - if(h && *h) - { - CloseHandle(*h); - *h = 0; - } -} - -/*--------------------------------------------------------------------------*/ - -/* Close the given handle if it is open and not a standard handle. - Reset its value to 0. */ -void kwsysProcessCleanupHandleSafe(PHANDLE h, DWORD nStdHandle) -{ - if(h && *h && (*h != GetStdHandle(nStdHandle))) + if(h && *h && *h != INVALID_HANDLE_VALUE && + *h != GetStdHandle(STD_INPUT_HANDLE) && + *h != GetStdHandle(STD_OUTPUT_HANDLE) && + *h != GetStdHandle(STD_ERROR_HANDLE)) { CloseHandle(*h); - *h = 0; + *h = INVALID_HANDLE_VALUE; } } @@ -1986,6 +1934,10 @@ void kwsysProcessCleanup(kwsysProcess* cp, int error) kwsysProcessCleanupHandle(&cp->Pipe[i].Read); cp->Pipe[i].Closed = 0; } + for(i=0; i < 3; ++i) + { + kwsysProcessCleanupHandle(&cp->PipeChildStd[i]); + } } /*--------------------------------------------------------------------------*/ diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index 6c4a7a6..c834e34 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -2674,27 +2674,43 @@ kwsys_stl::string SystemTools::GetLastSystemError() bool SystemTools::RemoveFile(const kwsys_stl::string& source) { #ifdef _WIN32 + kwsys_stl::wstring const& ws = + SystemTools::ConvertToWindowsExtendedPath(source); + if (DeleteFileW(ws.c_str())) + { + return true; + } + DWORD err = GetLastError(); + if (err == ERROR_FILE_NOT_FOUND || + err == ERROR_PATH_NOT_FOUND) + { + return true; + } + if (err != ERROR_ACCESS_DENIED) + { + return false; + } + /* The file may be read-only. Try adding write permission. */ mode_t mode; - if ( !SystemTools::GetPermissions(source, mode) ) + if (!SystemTools::GetPermissions(source, mode) || + !SystemTools::SetPermissions(source, S_IWRITE)) { + SetLastError(err); return false; } - /* Win32 unlink is stupid --- it fails if the file is read-only */ - SystemTools::SetPermissions(source, S_IWRITE); -#endif -#ifdef _WIN32 - bool res = - _wunlink(SystemTools::ConvertToWindowsExtendedPath(source).c_str()) == 0; -#else - bool res = unlink(source.c_str()) != 0 ? false : true; -#endif -#ifdef _WIN32 - if ( !res ) + if (DeleteFileW(ws.c_str()) || + GetLastError() == ERROR_FILE_NOT_FOUND || + GetLastError() == ERROR_PATH_NOT_FOUND) { - SystemTools::SetPermissions(source, mode); + return true; } + /* Try to restore the original permissions. */ + SystemTools::SetPermissions(source, mode); + SetLastError(err); + return false; +#else + return unlink(source.c_str()) == 0 || errno == ENOENT; #endif - return res; } bool SystemTools::RemoveADirectory(const kwsys_stl::string& source) diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx index 42b6249..15d8eab 100644 --- a/Source/kwsys/testSystemTools.cxx +++ b/Source/kwsys/testSystemTools.cxx @@ -156,6 +156,24 @@ static bool CheckFileOperations() res = false; } + kwsys_stl::string const testFileMissing(testNewDir + "/testMissingFile.txt"); + if (!kwsys::SystemTools::RemoveFile(testFileMissing)) + { + std::string const& msg = kwsys::SystemTools::GetLastSystemError(); + kwsys_ios::cerr << + "RemoveFile(\"" << testFileMissing << "\") failed: " << msg << "\n"; + res = false; + } + + kwsys_stl::string const testFileMissingDir(testNewDir + "/missing/file.txt"); + if (!kwsys::SystemTools::RemoveFile(testFileMissingDir)) + { + std::string const& msg = kwsys::SystemTools::GetLastSystemError(); + kwsys_ios::cerr << + "RemoveFile(\"" << testFileMissingDir << "\") failed: " << msg << "\n"; + res = false; + } + kwsys::SystemTools::Touch(testNewFile.c_str(), true); if (!kwsys::SystemTools::RemoveADirectory(testNewDir)) { |