diff options
Diffstat (limited to 'Source')
86 files changed, 2874 insertions, 2288 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index a8d77b2..33ab093 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -216,6 +216,8 @@ set(SRCS cmFileTimeComparison.cxx cmFileTimeComparison.h cmFortranParserImpl.cxx + cmFSPermissions.cxx + cmFSPermissions.h cmGeneratedFileStream.cxx cmGeneratorExpressionContext.cxx cmGeneratorExpressionContext.h @@ -309,11 +311,14 @@ set(SRCS cmPropertyMap.h cmQtAutoGen.cxx cmQtAutoGen.h - cmQtAutoGenDigest.h + cmQtAutoGenerator.cxx + cmQtAutoGenerator.h cmQtAutoGeneratorInitializer.cxx cmQtAutoGeneratorInitializer.h - cmQtAutoGenerators.cxx - cmQtAutoGenerators.h + cmQtAutoGeneratorMocUic.cxx + cmQtAutoGeneratorMocUic.h + cmQtAutoGeneratorRcc.cxx + cmQtAutoGeneratorRcc.h cmRST.cxx cmRST.h cmScriptGenerator.h @@ -916,7 +921,7 @@ if(UNIX) # OpenBSD and also Linux and OSX. Look for the header and # the library; it's a warning on FreeBSD if they're not # found, and informational on other platforms. - find_path(FREEBSD_PKG_INCLUDE_DIRS "pkg.h" PATHS /usr/local) + find_path(FREEBSD_PKG_INCLUDE_DIRS "pkg.h") if(FREEBSD_PKG_INCLUDE_DIRS) find_library(FREEBSD_PKG_LIBRARIES pkg diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index c9ec2ee..eca7be2 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 10) -set(CMake_VERSION_PATCH 20171107) +set(CMake_VERSION_PATCH 20171129) #set(CMake_VERSION_RC 1) diff --git a/Source/CPack/cmCPackGenerator.cxx b/Source/CPack/cmCPackGenerator.cxx index ecb5adb..be75a9f 100644 --- a/Source/CPack/cmCPackGenerator.cxx +++ b/Source/CPack/cmCPackGenerator.cxx @@ -12,6 +12,7 @@ #include "cmCPackComponentGroup.h" #include "cmCPackLog.h" #include "cmCryptoHash.h" +#include "cmFSPermissions.h" #include "cmGeneratedFileStream.h" #include "cmGlobalGenerator.h" #include "cmMakefile.h" @@ -201,6 +202,29 @@ int cmCPackGenerator::InstallProject() cmSystemTools::PutEnv("DESTDIR="); } + // prepare default created directory permissions + mode_t default_dir_mode_v = 0; + mode_t* default_dir_mode = nullptr; + const char* default_dir_install_permissions = + this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"); + if (default_dir_install_permissions && *default_dir_install_permissions) { + std::vector<std::string> items; + cmSystemTools::ExpandListArgument(default_dir_install_permissions, items); + for (const auto& arg : items) { + if (!cmFSPermissions::stringToModeT(arg, default_dir_mode_v)) { + cmCPackLogger(cmCPackLog::LOG_ERROR, "Invalid permission value '" + << arg + << "'." + " CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS " + "value is invalid." + << std::endl); + return 0; + } + } + + default_dir_mode = &default_dir_mode_v; + } + // If the CPackConfig file sets CPACK_INSTALL_COMMANDS then run them // as listed if (!this->InstallProjectViaInstallCommands(setDestDir, @@ -218,15 +242,15 @@ int cmCPackGenerator::InstallProject() // If the CPackConfig file sets CPACK_INSTALLED_DIRECTORIES // then glob it and copy it to CPACK_TEMPORARY_DIRECTORY // This is used in Source packaging - if (!this->InstallProjectViaInstalledDirectories(setDestDir, - tempInstallDirectory)) { + if (!this->InstallProjectViaInstalledDirectories( + setDestDir, tempInstallDirectory, default_dir_mode)) { return 0; } // If the project is a CMAKE project then run pre-install // and then read the cmake_install script to run it - if (!this->InstallProjectViaInstallCMakeProjects(setDestDir, - bareTempInstallDirectory)) { + if (!this->InstallProjectViaInstallCMakeProjects( + setDestDir, bareTempInstallDirectory, default_dir_mode)) { return 0; } @@ -274,7 +298,8 @@ int cmCPackGenerator::InstallProjectViaInstallCommands( } int cmCPackGenerator::InstallProjectViaInstalledDirectories( - bool setDestDir, const std::string& tempInstallDirectory) + bool setDestDir, const std::string& tempInstallDirectory, + const mode_t* default_dir_mode) { (void)setDestDir; (void)tempInstallDirectory; @@ -385,7 +410,8 @@ int cmCPackGenerator::InstallProjectViaInstalledDirectories( // make sure directory exists for symlink std::string destDir = cmSystemTools::GetFilenamePath(symlinked.second); - if (!destDir.empty() && !cmSystemTools::MakeDirectory(destDir)) { + if (!destDir.empty() && + !cmSystemTools::MakeDirectory(destDir, default_dir_mode)) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Cannot create dir: " << destDir << "\nTrying to create symlink: " << symlinked.second << "--> " << symlinked.first @@ -464,7 +490,8 @@ int cmCPackGenerator::InstallProjectViaInstallScript( } int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( - bool setDestDir, const std::string& baseTempInstallDirectory) + bool setDestDir, const std::string& baseTempInstallDirectory, + const mode_t* default_dir_mode) { const char* cmakeProjects = this->GetOption("CPACK_INSTALL_CMAKE_PROJECTS"); const char* cmakeGenerator = this->GetOption("CPACK_CMAKE_GENERATOR"); @@ -631,6 +658,13 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( } } + const char* default_dir_inst_permissions = + this->GetOption("CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"); + if (default_dir_inst_permissions && *default_dir_inst_permissions) { + mf.AddDefinition("CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS", + default_dir_inst_permissions); + } + if (!setDestDir) { tempInstallDirectory += this->GetPackagingInstallPrefix(); } @@ -690,7 +724,7 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( cmCPackLogger(cmCPackLog::LOG_DEBUG, "- Creating directory: '" << dir << "'" << std::endl); - if (!cmsys::SystemTools::MakeDirectory(dir.c_str())) { + if (!cmsys::SystemTools::MakeDirectory(dir, default_dir_mode)) { cmCPackLogger( cmCPackLog::LOG_ERROR, "Problem creating temporary directory: " << dir << std::endl); @@ -700,8 +734,8 @@ int cmCPackGenerator::InstallProjectViaInstallCMakeProjects( mf.AddDefinition("CMAKE_INSTALL_PREFIX", tempInstallDirectory.c_str()); - if (!cmsys::SystemTools::MakeDirectory( - tempInstallDirectory.c_str())) { + if (!cmsys::SystemTools::MakeDirectory(tempInstallDirectory, + default_dir_mode)) { cmCPackLogger(cmCPackLog::LOG_ERROR, "Problem creating temporary directory: " << tempInstallDirectory << std::endl); diff --git a/Source/CPack/cmCPackGenerator.h b/Source/CPack/cmCPackGenerator.h index 4e3a6e0..8100b66 100644 --- a/Source/CPack/cmCPackGenerator.h +++ b/Source/CPack/cmCPackGenerator.h @@ -12,6 +12,7 @@ #include "cmCPackComponentGroup.h" #include "cmSystemTools.h" +#include "cm_sys_stat.h" class cmCPackLog; class cmInstalledFile; @@ -168,9 +169,11 @@ protected: virtual int InstallProjectViaInstallScript( bool setDestDir, const std::string& tempInstallDirectory); virtual int InstallProjectViaInstalledDirectories( - bool setDestDir, const std::string& tempInstallDirectory); + bool setDestDir, const std::string& tempInstallDirectory, + const mode_t* default_dir_mode); virtual int InstallProjectViaInstallCMakeProjects( - bool setDestDir, const std::string& tempInstallDirectory); + bool setDestDir, const std::string& tempInstallDirectory, + const mode_t* default_dir_mode); /** * The various level of support of diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx index a0d68a0..b603758 100644 --- a/Source/CTest/cmCTestBuildAndTestHandler.cxx +++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx @@ -10,6 +10,7 @@ #include "cmake.h" #include "cmsys/Process.h" +#include <chrono> #include <stdlib.h> cmCTestBuildAndTestHandler::cmCTestBuildAndTestHandler() @@ -192,7 +193,7 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) // we need to honor the timeout specified, the timeout include cmake, build // and test time - double clock_start = cmSystemTools::GetTime(); + auto clock_start = std::chrono::steady_clock::now(); // make sure the binary dir is there out << "Internal cmake changing into directory: " << this->BinaryDir @@ -222,10 +223,12 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) this->BuildTargets.push_back(""); } for (std::string const& tar : this->BuildTargets) { - double remainingTime = 0; + std::chrono::duration<double> remainingTime = std::chrono::seconds(0); if (this->Timeout > 0) { - remainingTime = this->Timeout - cmSystemTools::GetTime() + clock_start; - if (remainingTime <= 0) { + remainingTime = std::chrono::duration<double>(this->Timeout) - + std::chrono::duration_cast<std::chrono::seconds>( + std::chrono::steady_clock::now() - clock_start); + if (remainingTime <= std::chrono::seconds(0)) { if (outstring) { *outstring = "--build-and-test timeout exceeded. "; } @@ -248,7 +251,7 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) int retVal = cm.GetGlobalGenerator()->Build( this->SourceDir, this->BinaryDir, this->BuildProject, tar, output, this->BuildMakeProgram, config, !this->BuildNoClean, false, false, - remainingTime); + remainingTime.count()); out << output; // if the build failed then return if (retVal) { @@ -320,10 +323,12 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) out << "\n"; // how much time is remaining - double remainingTime = 0; + std::chrono::duration<double> remainingTime = std::chrono::seconds(0); if (this->Timeout > 0) { - remainingTime = this->Timeout - cmSystemTools::GetTime() + clock_start; - if (remainingTime <= 0) { + remainingTime = std::chrono::duration<double>(this->Timeout) - + std::chrono::duration_cast<std::chrono::seconds>( + std::chrono::steady_clock::now() - clock_start); + if (remainingTime <= std::chrono::seconds(0)) { if (outstring) { *outstring = "--build-and-test timeout exceeded. "; } @@ -332,7 +337,7 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) } int runTestRes = this->CTest->RunTest(testCommand, &outs, &retval, nullptr, - remainingTime, nullptr); + remainingTime.count(), nullptr); if (runTestRes != cmsysProcess_State_Exited || retval != 0) { out << "Test command failed: " << testCommand[0] << "\n"; diff --git a/Source/CTest/cmCTestBuildHandler.cxx b/Source/CTest/cmCTestBuildHandler.cxx index f4fc769..f25c9c3 100644 --- a/Source/CTest/cmCTestBuildHandler.cxx +++ b/Source/CTest/cmCTestBuildHandler.cxx @@ -17,6 +17,7 @@ #include <set> #include <stdlib.h> #include <string.h> +#include <type_traits> static const char* cmCTestErrorMatches[] = { "^[Bb]us [Ee]rror", @@ -327,7 +328,7 @@ int cmCTestBuildHandler::ProcessHandler() // Create a last build log cmGeneratedFileStream ofs; - double elapsed_time_start = cmSystemTools::GetTime(); + auto elapsed_time_start = std::chrono::steady_clock::now(); if (!this->StartLogFile("Build", ofs)) { cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot create build log file" << std::endl); @@ -406,7 +407,7 @@ int cmCTestBuildHandler::ProcessHandler() // Remember start build time this->StartBuild = this->CTest->CurrentTime(); - this->StartBuildTime = cmSystemTools::GetTime(); + this->StartBuildTime = std::chrono::system_clock::now(); int retVal = 0; int res = cmsysProcess_State_Exited; if (!this->CTest->GetShowOnly()) { @@ -420,8 +421,9 @@ int cmCTestBuildHandler::ProcessHandler() // Remember end build time and calculate elapsed time this->EndBuild = this->CTest->CurrentTime(); - this->EndBuildTime = cmSystemTools::GetTime(); - double elapsed_build_time = cmSystemTools::GetTime() - elapsed_time_start; + this->EndBuildTime = std::chrono::system_clock::now(); + auto elapsed_build_time = + std::chrono::steady_clock::now() - elapsed_time_start; // Cleanups strings in the errors and warnings list. if (!this->SimplifySourceDir.empty()) { @@ -486,8 +488,7 @@ void cmCTestBuildHandler::GenerateXMLHeader(cmXMLWriter& xml) this->CTest->GenerateSubprojectsOutput(xml); xml.StartElement("Build"); xml.Element("StartDateTime", this->StartBuild); - xml.Element("StartBuildTime", - static_cast<unsigned int>(this->StartBuildTime)); + xml.Element("StartBuildTime", this->StartBuildTime); xml.Element("BuildCommand", this->GetMakeCommand()); } @@ -633,8 +634,8 @@ void cmCTestBuildHandler::GenerateXMLLogScraped(cmXMLWriter& xml) } } -void cmCTestBuildHandler::GenerateXMLFooter(cmXMLWriter& xml, - double elapsed_build_time) +void cmCTestBuildHandler::GenerateXMLFooter( + cmXMLWriter& xml, std::chrono::duration<double> elapsed_build_time) { xml.StartElement("Log"); xml.Attribute("Encoding", "base64"); @@ -642,9 +643,11 @@ void cmCTestBuildHandler::GenerateXMLFooter(cmXMLWriter& xml, 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.Element("EndBuildTime", this->EndBuildTime); + xml.Element( + "ElapsedMinutes", + std::chrono::duration_cast<std::chrono::minutes>(elapsed_build_time) + .count()); xml.EndElement(); // Build this->CTest->EndXML(xml); } diff --git a/Source/CTest/cmCTestBuildHandler.h b/Source/CTest/cmCTestBuildHandler.h index 6e71ad6..d1b9b2e 100644 --- a/Source/CTest/cmCTestBuildHandler.h +++ b/Source/CTest/cmCTestBuildHandler.h @@ -9,6 +9,7 @@ #include "cmProcessOutput.h" #include "cmsys/RegularExpression.hxx" +#include <chrono> #include <deque> #include <iosfwd> #include <stddef.h> @@ -86,14 +87,15 @@ private: void GenerateXMLHeader(cmXMLWriter& xml); void GenerateXMLLaunched(cmXMLWriter& xml); void GenerateXMLLogScraped(cmXMLWriter& xml); - void GenerateXMLFooter(cmXMLWriter& xml, double elapsed_build_time); + void GenerateXMLFooter(cmXMLWriter& xml, + std::chrono::duration<double> elapsed_build_time); bool IsLaunchedErrorFile(const char* fname); bool IsLaunchedWarningFile(const char* fname); std::string StartBuild; std::string EndBuild; - double StartBuildTime; - double EndBuildTime; + std::chrono::system_clock::time_point StartBuildTime; + std::chrono::system_clock::time_point EndBuildTime; std::vector<std::string> CustomErrorMatches; std::vector<std::string> CustomErrorExceptions; diff --git a/Source/CTest/cmCTestConfigureHandler.cxx b/Source/CTest/cmCTestConfigureHandler.cxx index 56a038e..ab77986 100644 --- a/Source/CTest/cmCTestConfigureHandler.cxx +++ b/Source/CTest/cmCTestConfigureHandler.cxx @@ -4,11 +4,12 @@ #include "cmCTest.h" #include "cmGeneratedFileStream.h" -#include "cmSystemTools.h" #include "cmXMLWriter.h" +#include <chrono> #include <ostream> #include <string> +#include <type_traits> cmCTestConfigureHandler::cmCTestConfigureHandler() { @@ -43,7 +44,7 @@ int cmCTestConfigureHandler::ProcessHandler() return -1; } - double elapsed_time_start = cmSystemTools::GetTime(); + auto elapsed_time_start = std::chrono::steady_clock::now(); std::string output; int retVal = 0; int res = 0; @@ -55,8 +56,7 @@ int cmCTestConfigureHandler::ProcessHandler() return 1; } std::string start_time = this->CTest->CurrentTime(); - unsigned int start_time_time = - static_cast<unsigned int>(cmSystemTools::GetTime()); + auto start_time_time = std::chrono::system_clock::now(); cmGeneratedFileStream ofs; this->StartLogFile("Configure", ofs); @@ -82,12 +82,11 @@ int cmCTestConfigureHandler::ProcessHandler() 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.Element("EndConfigureTime", std::chrono::system_clock::now()); + xml.Element("ElapsedMinutes", + std::chrono::duration_cast<std::chrono::minutes>( + std::chrono::steady_clock::now() - elapsed_time_start) + .count()); xml.EndElement(); // Configure this->CTest->EndXML(xml); } diff --git a/Source/CTest/cmCTestCoverageHandler.cxx b/Source/CTest/cmCTestCoverageHandler.cxx index 56eeceb..bbfe9bd 100644 --- a/Source/CTest/cmCTestCoverageHandler.cxx +++ b/Source/CTest/cmCTestCoverageHandler.cxx @@ -21,11 +21,13 @@ #include "cmsys/Process.h" #include "cmsys/RegularExpression.hxx" #include <algorithm> +#include <chrono> #include <iomanip> #include <iterator> #include <sstream> #include <stdio.h> #include <stdlib.h> +#include <type_traits> #include <utility> class cmMakefile; @@ -173,14 +175,13 @@ 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())); + xml.Element("StartTime", std::chrono::system_clock::now()); } void cmCTestCoverageHandler::EndCoverageLogXML(cmXMLWriter& xml) { xml.Element("EndDateTime", this->CTest->CurrentTime()); - xml.Element("EndTime", static_cast<unsigned int>(cmSystemTools::GetTime())); + xml.Element("EndTime", std::chrono::system_clock::now()); xml.EndElement(); // CoverageLog this->CTest->EndXML(xml); } @@ -281,8 +282,7 @@ int cmCTestCoverageHandler::ProcessHandler() } std::string coverage_start_time = this->CTest->CurrentTime(); - unsigned int coverage_start_time_time = - static_cast<unsigned int>(cmSystemTools::GetTime()); + auto coverage_start_time_time = std::chrono::system_clock::now(); std::string sourceDir = this->CTest->GetCTestConfiguration("SourceDirectory"); std::string binaryDir = this->CTest->GetCTestConfiguration("BuildDirectory"); @@ -290,13 +290,14 @@ int cmCTestCoverageHandler::ProcessHandler() this->LoadLabels(); cmGeneratedFileStream ofs; - double elapsed_time_start = cmSystemTools::GetTime(); + auto elapsed_time_start = std::chrono::steady_clock::now(); if (!this->StartLogFile("Coverage", ofs)) { cmCTestLog(this->CTest, ERROR_MESSAGE, "Cannot create LastCoverage.log file" << std::endl); } - ofs << "Performing coverage: " << elapsed_time_start << std::endl; + ofs << "Performing coverage: " + << elapsed_time_start.time_since_epoch().count() << std::endl; this->CleanCoverageLogFiles(ofs); cmSystemTools::ConvertToUnixSlashes(sourceDir); @@ -619,12 +620,11 @@ int cmCTestCoverageHandler::ProcessHandler() 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.Element("EndTime", std::chrono::system_clock::now()); + covSumXML.Element("ElapsedMinutes", + std::chrono::duration_cast<std::chrono::minutes>( + std::chrono::steady_clock::now() - elapsed_time_start) + .count()); covSumXML.EndElement(); // Coverage this->CTest->EndXML(covSumXML); @@ -1963,12 +1963,11 @@ int cmCTestCoverageHandler::RunBullseyeSourceSummary( return 0; } this->CTest->StartXML(xml, this->AppendXML); - double elapsed_time_start = cmSystemTools::GetTime(); + auto elapsed_time_start = std::chrono::steady_clock::now(); std::string coverage_start_time = this->CTest->CurrentTime(); xml.StartElement("Coverage"); xml.Element("StartDateTime", coverage_start_time); - xml.Element("StartTime", - static_cast<unsigned int>(cmSystemTools::GetTime())); + xml.Element("StartTime", std::chrono::system_clock::now()); std::string stdline; std::string errline; // expected output: @@ -2089,11 +2088,11 @@ int cmCTestCoverageHandler::RunBullseyeSourceSummary( 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.Element("EndTime", std::chrono::system_clock::now()); + xml.Element("ElapsedMinutes", + std::chrono::duration_cast<std::chrono::minutes>( + std::chrono::steady_clock::now() - elapsed_time_start) + .count()); xml.EndElement(); // Coverage this->CTest->EndXML(xml); diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx index 3efb039..2e7874d 100644 --- a/Source/CTest/cmCTestMemCheckHandler.cxx +++ b/Source/CTest/cmCTestMemCheckHandler.cxx @@ -10,9 +10,11 @@ #include "cmsys/FStream.hxx" #include "cmsys/Glob.hxx" #include "cmsys/RegularExpression.hxx" +#include <chrono> #include <iostream> #include <sstream> #include <string.h> +#include <type_traits> struct CatToErrorType { @@ -408,8 +410,10 @@ void cmCTestMemCheckHandler::GenerateDartOutput(cmXMLWriter& xml) xml.Element("EndDateTime", this->EndTest); xml.Element("EndTestTime", this->EndTestTime); - xml.Element("ElapsedMinutes", - static_cast<int>(this->ElapsedTestingTime / 6) / 10.0); + xml.Element( + "ElapsedMinutes", + std::chrono::duration_cast<std::chrono::minutes>(this->ElapsedTestingTime) + .count()); xml.EndElement(); // DynamicAnalysis this->CTest->EndXML(xml); @@ -844,7 +848,7 @@ bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput( cmsys::RegularExpression vgABR("== .*pthread_mutex_unlock: mutex is " "locked by a different thread"); std::vector<std::string::size_type> nonValGrindOutput; - double sttime = cmSystemTools::GetTime(); + auto sttime = std::chrono::steady_clock::now(); cmCTestOptionalLog(this->CTest, DEBUG, "Start test: " << lines.size() << std::endl, this->Quiet); std::string::size_type totalOutputSize = 0; @@ -918,7 +922,10 @@ bool cmCTestMemCheckHandler::ProcessMemCheckValgrindOutput( } } cmCTestOptionalLog(this->CTest, DEBUG, "End test (elapsed: " - << (cmSystemTools::GetTime() - sttime) << std::endl, + << std::chrono::duration_cast<std::chrono::seconds>( + std::chrono::steady_clock::now() - sttime) + .count() + << "s)" << std::endl, this->Quiet); log = ostr.str(); this->DefectCount += defects; @@ -929,7 +936,7 @@ bool cmCTestMemCheckHandler::ProcessMemCheckBoundsCheckerOutput( const std::string& str, std::string& log, std::vector<int>& results) { log.clear(); - double sttime = cmSystemTools::GetTime(); + auto sttime = std::chrono::steady_clock::now(); std::vector<std::string> lines; cmSystemTools::Split(str.c_str(), lines); cmCTestOptionalLog(this->CTest, DEBUG, @@ -961,7 +968,10 @@ bool cmCTestMemCheckHandler::ProcessMemCheckBoundsCheckerOutput( defects++; } cmCTestOptionalLog(this->CTest, DEBUG, "End test (elapsed: " - << (cmSystemTools::GetTime() - sttime) << std::endl, + << std::chrono::duration_cast<std::chrono::seconds>( + std::chrono::steady_clock::now() - sttime) + .count() + << "s)" << std::endl, this->Quiet); if (defects) { // only put the output of Bounds Checker if there were diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index 6a7bdc0..ae07feb 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -326,10 +326,22 @@ void cmCTestMultiProcessHandler::StartNextTests() } if (allTestsFailedTestLoadCheck) { + // Find out whether there are any non RUN_SERIAL tests left, so that the + // correct warning may be displayed. + bool onlyRunSerialTestsLeft = true; + for (auto const& test : copy) { + if (!this->Properties[test]->RunSerial) { + onlyRunSerialTestsLeft = false; + } + } cmCTestLog(this->CTest, HANDLER_OUTPUT, "***** WAITING, "); + if (this->SerialTestRunning) { cmCTestLog(this->CTest, HANDLER_OUTPUT, "Waiting for RUN_SERIAL test to finish."); + } else if (onlyRunSerialTestsLeft) { + cmCTestLog(this->CTest, HANDLER_OUTPUT, + "Only RUN_SERIAL tests remain, awaiting available slot."); } else { /* clang-format off */ cmCTestLog(this->CTest, HANDLER_OUTPUT, diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index abdb643..99531af 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -14,6 +14,7 @@ #include "cmsys/Base64.h" #include "cmsys/Process.h" #include "cmsys/RegularExpression.hxx" +#include <chrono> #include <iomanip> #include <sstream> #include <stdio.h> @@ -46,11 +47,12 @@ cmCTestRunTest::~cmCTestRunTest() bool cmCTestRunTest::CheckOutput() { // Read lines for up to 0.1 seconds of total time. - double timeout = 0.1; - double timeEnd = cmSystemTools::GetTime() + timeout; + std::chrono::duration<double> timeout = std::chrono::milliseconds(100); + auto timeEnd = std::chrono::steady_clock::now() + timeout; std::string line; - while ((timeout = timeEnd - cmSystemTools::GetTime(), timeout > 0)) { - int p = this->TestProcess->GetNextOutputLine(line, timeout); + while ((timeout = timeEnd - std::chrono::steady_clock::now(), + timeout > std::chrono::seconds(0))) { + int p = this->TestProcess->GetNextOutputLine(line, timeout.count()); if (p == cmsysProcess_Pipe_None) { // Process has terminated and all output read. return false; diff --git a/Source/CTest/cmCTestScriptHandler.cxx b/Source/CTest/cmCTestScriptHandler.cxx index 198f6e5..3bf27a0 100644 --- a/Source/CTest/cmCTestScriptHandler.cxx +++ b/Source/CTest/cmCTestScriptHandler.cxx @@ -5,10 +5,12 @@ #include "cmsys/Directory.hxx" #include "cmsys/Process.h" #include <map> +#include <ratio> #include <sstream> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <type_traits> #include <utility> #include "cmCTest.h" @@ -79,7 +81,7 @@ cmCTestScriptHandler::cmCTestScriptHandler() this->CMake = nullptr; this->GlobalGenerator = nullptr; - this->ScriptStartTime = 0; + this->ScriptStartTime = std::chrono::steady_clock::time_point(); // the *60 is because the settings are in minutes but GetTime is seconds this->MinimumInterval = 30 * 60; @@ -111,7 +113,7 @@ void cmCTestScriptHandler::Initialize() this->ContinuousDuration = -1; // what time in seconds did this script start running - this->ScriptStartTime = 0; + this->ScriptStartTime = std::chrono::steady_clock::time_point(); delete this->Makefile; this->Makefile = nullptr; @@ -158,11 +160,10 @@ void cmCTestScriptHandler::UpdateElapsedTime() { if (this->Makefile) { // set the current elapsed time - char timeString[20]; - int itime = static_cast<unsigned int>(cmSystemTools::GetTime() - - this->ScriptStartTime); - sprintf(timeString, "%i", itime); - this->Makefile->AddDefinition("CTEST_ELAPSED_TIME", timeString); + auto itime = std::chrono::duration_cast<std::chrono::seconds>( + std::chrono::steady_clock::now() - this->ScriptStartTime); + auto timeString = std::to_string(itime.count()); + this->Makefile->AddDefinition("CTEST_ELAPSED_TIME", timeString.c_str()); } } @@ -507,7 +508,7 @@ int cmCTestScriptHandler::RunConfigurationScript( int result; - this->ScriptStartTime = cmSystemTools::GetTime(); + this->ScriptStartTime = std::chrono::steady_clock::now(); // read in the script if (pscope) { @@ -558,22 +559,27 @@ int cmCTestScriptHandler::RunCurrentScript() // for a continuous, do we ned to run it more than once? if (this->ContinuousDuration >= 0) { this->UpdateElapsedTime(); - double ending_time = cmSystemTools::GetTime() + this->ContinuousDuration; + auto ending_time = std::chrono::steady_clock::now() + + std::chrono::duration<double>(this->ContinuousDuration); if (this->EmptyBinDirOnce) { this->EmptyBinDir = true; } do { - double interval = cmSystemTools::GetTime(); + auto startOfInterval = std::chrono::steady_clock::now(); result = this->RunConfigurationDashboard(); - interval = cmSystemTools::GetTime() - interval; - if (interval < this->MinimumInterval) { - this->SleepInSeconds( - static_cast<unsigned int>(this->MinimumInterval - interval)); + auto interval = std::chrono::steady_clock::now() - startOfInterval; + auto minimumInterval = + std::chrono::duration<double>(this->MinimumInterval); + if (interval < minimumInterval) { + auto sleepTime = std::chrono::duration_cast<std::chrono::seconds>( + minimumInterval - interval) + .count(); + this->SleepInSeconds(static_cast<unsigned int>(sleepTime)); } if (this->EmptyBinDirOnce) { this->EmptyBinDir = false; } - } while (cmSystemTools::GetTime() < ending_time); + } while (std::chrono::steady_clock::now() < ending_time); } // otherwise just run it once else { @@ -967,7 +973,9 @@ double cmCTestScriptHandler::GetRemainingTimeAllowed() return 1.0e7; } - double timelimit = atof(timelimitS); + auto timelimit = std::chrono::duration<double>(atof(timelimitS)); - return timelimit - cmSystemTools::GetTime() + this->ScriptStartTime; + auto duration = std::chrono::duration_cast<std::chrono::duration<double>>( + std::chrono::steady_clock::now() - this->ScriptStartTime); + return (timelimit - duration).count(); } diff --git a/Source/CTest/cmCTestScriptHandler.h b/Source/CTest/cmCTestScriptHandler.h index b6cd97b..2090d04 100644 --- a/Source/CTest/cmCTestScriptHandler.h +++ b/Source/CTest/cmCTestScriptHandler.h @@ -7,6 +7,7 @@ #include "cmCTestGenericHandler.h" +#include <chrono> #include <string> #include <vector> @@ -104,6 +105,7 @@ public: void CreateCMake(); cmake* GetCMake() { return this->CMake; } + private: // reads in a script int ReadInScript(const std::string& total_script_arg); @@ -156,7 +158,7 @@ private: double ContinuousDuration; // what time in seconds did this script start running - double ScriptStartTime; + std::chrono::steady_clock::time_point ScriptStartTime; cmMakefile* Makefile; cmGlobalGenerator* GlobalGenerator; diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index 719688c..86fee7a 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -6,6 +6,7 @@ #include "cm_jsoncpp_reader.h" #include "cm_jsoncpp_value.h" #include "cmsys/Process.h" +#include <chrono> #include <sstream> #include <stdio.h> #include <stdlib.h> @@ -496,10 +497,11 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix, ? "" : this->GetOption("RetryCount"); - int delay = retryDelay.empty() - ? atoi(this->CTest->GetCTestConfiguration("CTestSubmitRetryDelay") - .c_str()) - : atoi(retryDelay.c_str()); + auto delay = std::chrono::duration<double>( + retryDelay.empty() + ? atoi(this->CTest->GetCTestConfiguration("CTestSubmitRetryDelay") + .c_str()) + : atoi(retryDelay.c_str())); int count = retryCount.empty() ? atoi(this->CTest->GetCTestConfiguration("CTestSubmitRetryCount") .c_str()) @@ -507,12 +509,12 @@ bool cmCTestSubmitHandler::SubmitUsingHTTP(const std::string& localprefix, for (int i = 0; i < count; i++) { cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, - " Submit failed, waiting " << delay + " Submit failed, waiting " << delay.count() << " seconds...\n", this->Quiet); - double stop = cmSystemTools::GetTime() + delay; - while (cmSystemTools::GetTime() < stop) { + auto stop = std::chrono::steady_clock::now() + delay; + while (std::chrono::steady_clock::now() < stop) { cmSystemTools::Delay(100); } @@ -1031,11 +1033,15 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, std::string retryCountString = this->GetOption("RetryCount") == nullptr ? "" : this->GetOption("RetryCount"); - unsigned long retryDelay = 0; + auto retryDelay = std::chrono::seconds(0); if (!retryDelayString.empty()) { - if (!cmSystemTools::StringToULong(retryDelayString.c_str(), &retryDelay)) { + unsigned long retryDelayValue = 0; + if (!cmSystemTools::StringToULong(retryDelayString.c_str(), + &retryDelayValue)) { cmCTestLog(this->CTest, WARNING, "Invalid value for 'RETRY_DELAY' : " << retryDelayString << std::endl); + } else { + retryDelay = std::chrono::seconds(retryDelayValue); } } unsigned long retryCount = 0; @@ -1063,6 +1069,8 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, if (subproject) { str << "subproject=" << curl.Escape(subproject) << "&"; } + auto timeNow = + std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); str << "stamp=" << curl.Escape(this->CTest->GetCurrentTag()) << "-" << curl.Escape(this->CTest->GetTestModelString()) << "&" << "model=" << curl.Escape(this->CTest->GetTestModelString()) << "&" @@ -1071,8 +1079,8 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, << "site=" << curl.Escape(this->CTest->GetCTestConfiguration("Site")) << "&" << "track=" << curl.Escape(this->CTest->GetTestModelString()) << "&" - << "starttime=" << static_cast<int>(cmSystemTools::GetTime()) << "&" - << "endtime=" << static_cast<int>(cmSystemTools::GetTime()) << "&" + << "starttime=" << timeNow << "&" + << "endtime=" << timeNow << "&" << "datafilesmd5[0]=" << md5sum << "&" << "type=" << curl.Escape(typeString); std::string fields = str.str(); @@ -1087,12 +1095,12 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, // If request failed, wait and retry. for (unsigned long i = 0; i < retryCount; i++) { cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, - " Request failed, waiting " << retryDelay + " Request failed, waiting " << retryDelay.count() << " seconds...\n", this->Quiet); - double stop = cmSystemTools::GetTime() + static_cast<double>(retryDelay); - while (cmSystemTools::GetTime() < stop) { + auto stop = std::chrono::steady_clock::now() + retryDelay; + while (std::chrono::steady_clock::now() < stop) { cmSystemTools::Delay(100); } @@ -1161,12 +1169,12 @@ int cmCTestSubmitHandler::HandleCDashUploadFile(std::string const& file, // If upload failed, wait and retry. for (unsigned long i = 0; i < retryCount; i++) { cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, - " Upload failed, waiting " << retryDelay + " Upload failed, waiting " << retryDelay.count() << " seconds...\n", this->Quiet); - double stop = cmSystemTools::GetTime() + static_cast<double>(retryDelay); - while (cmSystemTools::GetTime() < stop) { + auto stop = std::chrono::steady_clock::now() + retryDelay; + while (std::chrono::steady_clock::now() < stop) { cmSystemTools::Delay(100); } diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index c7ed927..e7c719c 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCTestTestHandler.h" #include <algorithm> +#include <chrono> #include <cmsys/Base64.h> #include <cmsys/Directory.hxx> #include <cmsys/RegularExpression.hxx> @@ -15,6 +16,7 @@ #include <stdlib.h> #include <string.h> #include <time.h> +#include <type_traits> #include "cmAlgorithms.h" #include "cmCTest.h" @@ -346,7 +348,7 @@ void cmCTestTestHandler::Initialize() { this->Superclass::Initialize(); - this->ElapsedTestingTime = -1; + this->ElapsedTestingTime = std::chrono::duration<double>(); this->TestResults.clear(); @@ -484,12 +486,11 @@ int cmCTestTestHandler::ProcessHandler() int total; // start the real time clock - double clock_start, clock_finish; - clock_start = cmSystemTools::GetTime(); + auto clock_start = std::chrono::steady_clock::now(); this->ProcessDirectory(passed, failed); - clock_finish = cmSystemTools::GetTime(); + auto clock_finish = std::chrono::steady_clock::now(); total = int(passed.size()) + int(failed.size()); @@ -540,7 +541,10 @@ int cmCTestTestHandler::ProcessHandler() this->PrintLabelOrSubprojectSummary(false); } char realBuf[1024]; - sprintf(realBuf, "%6.2f sec", clock_finish - clock_start); + auto durationInMs = std::chrono::duration_cast<std::chrono::milliseconds>( + clock_finish - clock_start) + .count(); + sprintf(realBuf, "%6.2f sec", static_cast<double>(durationInMs) / 1000.0); cmCTestOptionalLog(this->CTest, HANDLER_OUTPUT, "\nTotal Test time (real) = " << realBuf << "\n", this->Quiet); @@ -1200,8 +1204,8 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<std::string>& passed, { this->ComputeTestList(); this->StartTest = this->CTest->CurrentTime(); - this->StartTestTime = static_cast<unsigned int>(cmSystemTools::GetTime()); - double elapsed_time_start = cmSystemTools::GetTime(); + this->StartTestTime = std::chrono::system_clock::now(); + auto elapsed_time_start = std::chrono::steady_clock::now(); cmCTestMultiProcessHandler* parallel = this->CTest->GetBatchJobs() ? new cmCTestBatchTestHandler @@ -1267,8 +1271,9 @@ void cmCTestTestHandler::ProcessDirectory(std::vector<std::string>& passed, } delete parallel; this->EndTest = this->CTest->CurrentTime(); - this->EndTestTime = static_cast<unsigned int>(cmSystemTools::GetTime()); - this->ElapsedTestingTime = cmSystemTools::GetTime() - elapsed_time_start; + this->EndTestTime = std::chrono::system_clock::now(); + this->ElapsedTestingTime = + std::chrono::steady_clock::now() - elapsed_time_start; *this->LogFile << "End testing: " << this->CTest->CurrentTime() << std::endl; } @@ -1373,8 +1378,10 @@ void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml) xml.Element("EndDateTime", this->EndTest); xml.Element("EndTestTime", this->EndTestTime); - xml.Element("ElapsedMinutes", - static_cast<int>(this->ElapsedTestingTime / 6) / 10.0); + xml.Element( + "ElapsedMinutes", + std::chrono::duration_cast<std::chrono::minutes>(this->ElapsedTestingTime) + .count()); xml.EndElement(); // Testing this->CTest->EndXML(xml); } diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index 620e906..8572e7b 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -8,6 +8,7 @@ #include "cmCTestGenericHandler.h" #include "cmsys/RegularExpression.hxx" +#include <chrono> #include <iosfwd> #include <map> #include <set> @@ -198,7 +199,7 @@ protected: //! Clean test output to specified length bool CleanTestOutput(std::string& output, size_t length); - double ElapsedTestingTime; + std::chrono::duration<double> ElapsedTestingTime; typedef std::vector<cmCTestTestResult> TestResultsVector; TestResultsVector TestResults; @@ -206,8 +207,8 @@ protected: std::vector<std::string> CustomTestsIgnore; std::string StartTest; std::string EndTest; - unsigned int StartTestTime; - unsigned int EndTestTime; + std::chrono::system_clock::time_point StartTestTime; + std::chrono::system_clock::time_point EndTestTime; bool MemCheck; int CustomMaximumPassedTestOutputSize; int CustomMaximumFailedTestOutputSize; diff --git a/Source/CTest/cmCTestUpdateHandler.cxx b/Source/CTest/cmCTestUpdateHandler.cxx index 786ed5e..f86d4a3 100644 --- a/Source/CTest/cmCTestUpdateHandler.cxx +++ b/Source/CTest/cmCTestUpdateHandler.cxx @@ -17,8 +17,10 @@ #include "cmVersion.h" #include "cmXMLWriter.h" +#include <chrono> #include <memory> // IWYU pragma: keep #include <sstream> +#include <type_traits> static const char* cmCTestUpdateHandlerUpdateStrings[] = { "Unknown", "CVS", "SVN", "BZR", "GIT", "HG", "P4" @@ -175,9 +177,8 @@ int cmCTestUpdateHandler::ProcessHandler() return -1; } std::string start_time = this->CTest->CurrentTime(); - unsigned int start_time_time = - static_cast<unsigned int>(cmSystemTools::GetTime()); - double elapsed_time_start = cmSystemTools::GetTime(); + auto start_time_time = std::chrono::system_clock::now(); + auto elapsed_time_start = std::chrono::steady_clock::now(); bool updated = vc->Update(); std::string buildname = @@ -224,11 +225,11 @@ int cmCTestUpdateHandler::ProcessHandler() cmCTestOptionalLog(this->CTest, DEBUG, "End" << std::endl, this->Quiet); std::string end_time = this->CTest->CurrentTime(); 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.Element("EndTime", std::chrono::system_clock::now()); + xml.Element("ElapsedMinutes", + std::chrono::duration_cast<std::chrono::minutes>( + std::chrono::steady_clock::now() - elapsed_time_start) + .count()); xml.StartElement("UpdateReturnStatus"); if (localModifications) { diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx index f3c191b..78dd598 100644 --- a/Source/CTest/cmProcess.cxx +++ b/Source/CTest/cmProcess.cxx @@ -3,8 +3,8 @@ #include "cmProcess.h" #include "cmProcessOutput.h" -#include "cmSystemTools.h" #include <iostream> +#include <type_traits> cmProcess::cmProcess() { @@ -13,7 +13,7 @@ cmProcess::cmProcess() this->TotalTime = 0; this->ExitValue = 0; this->Id = 0; - this->StartTime = 0; + this->StartTime = std::chrono::steady_clock::time_point(); } cmProcess::~cmProcess() @@ -35,7 +35,7 @@ bool cmProcess::StartProcess() if (this->Command.empty()) { return false; } - this->StartTime = cmSystemTools::GetTime(); + this->StartTime = std::chrono::steady_clock::now(); this->ProcessArgs.clear(); // put the command as arg0 this->ProcessArgs.push_back(this->Command.c_str()); @@ -143,7 +143,11 @@ int cmProcess::GetNextOutputLine(std::string& line, double timeout) // Record exit information. this->ExitValue = cmsysProcess_GetExitValue(this->Process); - this->TotalTime = cmSystemTools::GetTime() - this->StartTime; + this->TotalTime = + static_cast<double>(std::chrono::duration_cast<std::chrono::milliseconds>( + std::chrono::steady_clock::now() - this->StartTime) + .count()) / + 1000.0; // Because of a processor clock scew the runtime may become slightly // negative. If someone changed the system clock while the process was // running this may be even more. Make sure not to report a negative @@ -231,7 +235,7 @@ void cmProcess::ChangeTimeout(double t) void cmProcess::ResetStartTime() { cmsysProcess_ResetStartTime(this->Process); - this->StartTime = cmSystemTools::GetTime(); + this->StartTime = std::chrono::steady_clock::now(); } int cmProcess::GetExitException() diff --git a/Source/CTest/cmProcess.h b/Source/CTest/cmProcess.h index dfb02fe..ddd69b6 100644 --- a/Source/CTest/cmProcess.h +++ b/Source/CTest/cmProcess.h @@ -6,6 +6,7 @@ #include "cmConfigure.h" // IWYU pragma: keep #include "cmsys/Process.h" +#include <chrono> #include <string> #include <vector> @@ -50,7 +51,7 @@ public: private: double Timeout; - double StartTime; + std::chrono::steady_clock::time_point StartTime; double TotalTime; cmsysProcess* Process; class Buffer : public std::vector<char> diff --git a/Source/QtDialog/CMakeLists.txt b/Source/QtDialog/CMakeLists.txt index 9e9df78..b38797b 100644 --- a/Source/QtDialog/CMakeLists.txt +++ b/Source/QtDialog/CMakeLists.txt @@ -33,6 +33,12 @@ if (Qt5Widgets_FOUND) PROPERTY COMPILE_DEFINITIONS USE_QXcbIntegrationPlugin) endif() + if(CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES) + list(APPEND CMake_QT_LIBRARIES ${CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES}) + set_property(SOURCE CMakeSetup.cxx + PROPERTY COMPILE_DEFINITIONS USE_QWindowsIntegrationPlugin) + endif() + # We need to install platform plugin and add qt.conf for Qt5 on Mac and Windows. # FIXME: This should be part of Qt5 CMake scripts, but unfortunatelly # Qt5 support is missing there. @@ -65,7 +71,7 @@ if (Qt5Widgets_FOUND) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" DESTINATION "${CMAKE_INSTALL_PREFIX}/Resources" ${COMPONENT}) - elseif(WIN32) + elseif(WIN32 AND NOT CMake_QT_STATIC_QWindowsIntegrationPlugin_LIBRARIES) install_qt5_plugin("Qt5::QWindowsIntegrationPlugin" QT_PLUGINS) file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/qt.conf" "[Paths]\nPlugins = ../${_qt_plugin_dir}\n") diff --git a/Source/QtDialog/CMakeSetup.cxx b/Source/QtDialog/CMakeSetup.cxx index ca0b015..bfd43cf 100644 --- a/Source/QtDialog/CMakeSetup.cxx +++ b/Source/QtDialog/CMakeSetup.cxx @@ -44,6 +44,10 @@ static void cmAddPluginPath(); Q_IMPORT_PLUGIN(QXcbIntegrationPlugin); #endif +#if defined(USE_QWindowsIntegrationPlugin) +Q_IMPORT_PLUGIN(QWindowsIntegrationPlugin); +#endif + int main(int argc, char** argv) { cmsys::Encoding::CommandLineArguments encoding_args = diff --git a/Source/cmAddCustomTargetCommand.cxx b/Source/cmAddCustomTargetCommand.cxx index f4b4f66..819c781 100644 --- a/Source/cmAddCustomTargetCommand.cxx +++ b/Source/cmAddCustomTargetCommand.cxx @@ -209,9 +209,9 @@ bool cmAddCustomTargetCommand::InitialPass( // Add the utility target to the makefile. bool escapeOldStyle = !verbatim; cmTarget* target = this->Makefile->AddUtilityCommand( - targetName, excludeFromAll, working_directory.c_str(), byproducts, depends, - commandLines, escapeOldStyle, comment, uses_terminal, - command_expand_lists); + targetName, cmMakefile::TargetOrigin::Project, excludeFromAll, + working_directory.c_str(), byproducts, depends, commandLines, + escapeOldStyle, comment, uses_terminal, command_expand_lists); // Add additional user-specified source files to the target. target->AddSources(sources); diff --git a/Source/cmAuxSourceDirectoryCommand.cxx b/Source/cmAuxSourceDirectoryCommand.cxx index 847a416..fcdc632 100644 --- a/Source/cmAuxSourceDirectoryCommand.cxx +++ b/Source/cmAuxSourceDirectoryCommand.cxx @@ -54,10 +54,8 @@ bool cmAuxSourceDirectoryCommand::InitialPass( std::string ext = file.substr(dotpos + 1); std::string base = file.substr(0, dotpos); // Process only source files - std::vector<std::string> const& srcExts = - this->Makefile->GetCMakeInstance()->GetSourceExtensions(); - if (!base.empty() && - std::find(srcExts.begin(), srcExts.end(), ext) != srcExts.end()) { + auto cm = this->Makefile->GetCMakeInstance(); + if (!base.empty() && cm->IsSourceExtension(ext)) { std::string fullname = templateDirectory; fullname += "/"; fullname += file; diff --git a/Source/cmCPluginAPI.cxx b/Source/cmCPluginAPI.cxx index e1e11af..18a1022 100644 --- a/Source/cmCPluginAPI.cxx +++ b/Source/cmCPluginAPI.cxx @@ -218,8 +218,8 @@ void CCONV cmAddUtilityCommand(void* arg, const char* utilityName, } // Pass the call to the makefile instance. - mf->AddUtilityCommand(utilityName, (all ? false : true), nullptr, depends2, - commandLines); + mf->AddUtilityCommand(utilityName, cmMakefile::TargetOrigin::Project, + (all ? false : true), nullptr, depends2, commandLines); } void CCONV cmAddCustomCommand(void* arg, const char* source, const char* command, int numArgs, diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 37ff901..d358e3d 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -12,7 +12,7 @@ #include "cmsys/String.hxx" #include "cmsys/SystemInformation.hxx" #include <algorithm> -#include <cstdint> +#include <chrono> #include <ctype.h> #include <iostream> #include <map> @@ -282,7 +282,6 @@ cmCTest::cmCTest() this->GlobalTimeout = 0; this->LastStopTimeout = 24 * 60 * 60; this->CompressXMLFiles = false; - this->CTestConfigFile.clear(); this->ScheduleType.clear(); this->StopTime.clear(); this->NextDayStopTime = false; @@ -623,12 +622,9 @@ bool cmCTest::UpdateCTestConfiguration() if (this->SuppressUpdatingCTestConfiguration) { return true; } - std::string fileName = this->CTestConfigFile; - if (fileName.empty()) { - fileName = this->BinaryDir + "/CTestConfiguration.ini"; - if (!cmSystemTools::FileExists(fileName.c_str())) { - fileName = this->BinaryDir + "/DartConfiguration.tcl"; - } + std::string fileName = this->BinaryDir + "/CTestConfiguration.ini"; + if (!cmSystemTools::FileExists(fileName.c_str())) { + fileName = this->BinaryDir + "/DartConfiguration.tcl"; } cmCTestLog(this, HANDLER_VERBOSE_OUTPUT, "UpdateCTestConfiguration from :" << fileName << "\n"); @@ -1422,7 +1418,7 @@ int cmCTest::GenerateCTestNotesOutput(cmXMLWriter& xml, std::string note_time = this->CurrentTime(); xml.StartElement("Note"); xml.Attribute("Name", file); - xml.Element("Time", static_cast<uint64_t>(cmSystemTools::GetTime())); + xml.Element("Time", std::chrono::system_clock::now()); xml.Element("DateTime", note_time); xml.StartElement("Text"); cmsys::ifstream ifs(file.c_str()); diff --git a/Source/cmCTest.h b/Source/cmCTest.h index dbd67dc..a2d6fc3 100644 --- a/Source/cmCTest.h +++ b/Source/cmCTest.h @@ -487,7 +487,6 @@ private: /** Map of configuration properties */ typedef std::map<std::string, std::string> CTestConfigurationMap; - std::string CTestConfigFile; // TODO: The ctest configuration should be a hierarchy of // configuration option sources: command-line, script, ini file. // Then the ini file can get re-loaded whenever it changes without diff --git a/Source/cmConnection.cxx b/Source/cmConnection.cxx index f482412..28ba12c 100644 --- a/Source/cmConnection.cxx +++ b/Source/cmConnection.cxx @@ -97,11 +97,10 @@ void cmEventBasedConnection::ReadData(const std::string& data) this->RawReadBuffer += data; if (BufferStrategy) { std::string packet = BufferStrategy->BufferMessage(this->RawReadBuffer); - do { + while (!packet.empty()) { ProcessRequest(packet); packet = BufferStrategy->BufferMessage(this->RawReadBuffer); - } while (!packet.empty()); - + } } else { ProcessRequest(this->RawReadBuffer); this->RawReadBuffer.clear(); diff --git a/Source/cmExtraCodeBlocksGenerator.cxx b/Source/cmExtraCodeBlocksGenerator.cxx index 9c9b75b..76fc8f1 100644 --- a/Source/cmExtraCodeBlocksGenerator.cxx +++ b/Source/cmExtraCodeBlocksGenerator.cxx @@ -345,8 +345,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( all_files_map_t allFiles; std::vector<std::string> cFiles; - std::vector<std::string> const& srcExts = - this->GlobalGenerator->GetCMakeInstance()->GetSourceExtensions(); + auto cm = this->GlobalGenerator->GetCMakeInstance(); for (cmLocalGenerator* lg : lgs) { cmMakefile* makefile = lg->GetMakefile(); @@ -377,12 +376,7 @@ void cmExtraCodeBlocksGenerator::CreateNewProjectFile( std::string lang = s->GetLanguage(); if (lang == "C" || lang == "CXX") { std::string const& srcext = s->GetExtension(); - for (std::string const& ext : srcExts) { - if (srcext == ext) { - isCFile = true; - break; - } - } + isCFile = cm->IsSourceExtension(srcext); } std::string const& fullPath = s->GetFullPath(); diff --git a/Source/cmExtraCodeLiteGenerator.cxx b/Source/cmExtraCodeLiteGenerator.cxx index 5a02d54..383942b 100644 --- a/Source/cmExtraCodeLiteGenerator.cxx +++ b/Source/cmExtraCodeLiteGenerator.cxx @@ -198,8 +198,7 @@ std::string cmExtraCodeLiteGenerator::CollectSourceFiles( std::map<std::string, cmSourceFile*>& cFiles, std::set<std::string>& otherFiles) { - const std::vector<std::string>& srcExts = - this->GlobalGenerator->GetCMakeInstance()->GetSourceExtensions(); + auto cm = this->GlobalGenerator->GetCMakeInstance(); std::string projectType; switch (gt->GetType()) { @@ -233,12 +232,7 @@ std::string cmExtraCodeLiteGenerator::CollectSourceFiles( std::string lang = s->GetLanguage(); if (lang == "C" || lang == "CXX") { std::string const& srcext = s->GetExtension(); - for (std::string const& ext : srcExts) { - if (srcext == ext) { - isCFile = true; - break; - } - } + isCFile = cm->IsSourceExtension(srcext); } // then put it accordingly into one of the two containers diff --git a/Source/cmFSPermissions.cxx b/Source/cmFSPermissions.cxx new file mode 100644 index 0000000..4015a51 --- /dev/null +++ b/Source/cmFSPermissions.cxx @@ -0,0 +1,34 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmFSPermissions.h" + +bool cmFSPermissions::stringToModeT(std::string const& arg, + mode_t& permissions) +{ + if (arg == "OWNER_READ") { + permissions |= mode_owner_read; + } else if (arg == "OWNER_WRITE") { + permissions |= mode_owner_write; + } else if (arg == "OWNER_EXECUTE") { + permissions |= mode_owner_execute; + } else if (arg == "GROUP_READ") { + permissions |= mode_group_read; + } else if (arg == "GROUP_WRITE") { + permissions |= mode_group_write; + } else if (arg == "GROUP_EXECUTE") { + permissions |= mode_group_execute; + } else if (arg == "WORLD_READ") { + permissions |= mode_world_read; + } else if (arg == "WORLD_WRITE") { + permissions |= mode_world_write; + } else if (arg == "WORLD_EXECUTE") { + permissions |= mode_world_execute; + } else if (arg == "SETUID") { + permissions |= mode_setuid; + } else if (arg == "SETGID") { + permissions |= mode_setgid; + } else { + return false; + } + return true; +} diff --git a/Source/cmFSPermissions.h b/Source/cmFSPermissions.h new file mode 100644 index 0000000..7a6e708 --- /dev/null +++ b/Source/cmFSPermissions.h @@ -0,0 +1,45 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmFSPermissions_h +#define cmFSPermissions_h + +#include "cmConfigure.h" // IWYU pragma: keep + +#include "cm_sys_stat.h" + +#include <string> + +namespace cmFSPermissions { + +// Table of permissions flags. +#if defined(_WIN32) && !defined(__CYGWIN__) +static const mode_t mode_owner_read = S_IREAD; +static const mode_t mode_owner_write = S_IWRITE; +static const mode_t mode_owner_execute = S_IEXEC; +static const mode_t mode_group_read = 040; +static const mode_t mode_group_write = 020; +static const mode_t mode_group_execute = 010; +static const mode_t mode_world_read = 04; +static const mode_t mode_world_write = 02; +static const mode_t mode_world_execute = 01; +static const mode_t mode_setuid = 04000; +static const mode_t mode_setgid = 02000; +#else +static const mode_t mode_owner_read = S_IRUSR; +static const mode_t mode_owner_write = S_IWUSR; +static const mode_t mode_owner_execute = S_IXUSR; +static const mode_t mode_group_read = S_IRGRP; +static const mode_t mode_group_write = S_IWGRP; +static const mode_t mode_group_execute = S_IXGRP; +static const mode_t mode_world_read = S_IROTH; +static const mode_t mode_world_write = S_IWOTH; +static const mode_t mode_world_execute = S_IXOTH; +static const mode_t mode_setuid = S_ISUID; +static const mode_t mode_setgid = S_ISGID; +#endif + +bool stringToModeT(std::string const& arg, mode_t& permissions); + +} // ns + +#endif diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 191a666..88185bd 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -20,6 +20,7 @@ #include "cmAlgorithms.h" #include "cmCommandArgumentsHelper.h" #include "cmCryptoHash.h" +#include "cmFSPermissions.h" #include "cmFileLockPool.h" #include "cmFileTimeComparison.h" #include "cmGeneratorExpression.h" @@ -50,32 +51,7 @@ class cmSystemToolsFileTime; -// Table of permissions flags. -#if defined(_WIN32) && !defined(__CYGWIN__) -static mode_t mode_owner_read = S_IREAD; -static mode_t mode_owner_write = S_IWRITE; -static mode_t mode_owner_execute = S_IEXEC; -static mode_t mode_group_read = 040; -static mode_t mode_group_write = 020; -static mode_t mode_group_execute = 010; -static mode_t mode_world_read = 04; -static mode_t mode_world_write = 02; -static mode_t mode_world_execute = 01; -static mode_t mode_setuid = 04000; -static mode_t mode_setgid = 02000; -#else -static mode_t mode_owner_read = S_IRUSR; -static mode_t mode_owner_write = S_IWUSR; -static mode_t mode_owner_execute = S_IXUSR; -static mode_t mode_group_read = S_IRGRP; -static mode_t mode_group_write = S_IWGRP; -static mode_t mode_group_execute = S_IXGRP; -static mode_t mode_world_read = S_IROTH; -static mode_t mode_world_write = S_IWOTH; -static mode_t mode_world_execute = S_IXOTH; -static mode_t mode_setuid = S_ISUID; -static mode_t mode_setgid = S_ISGID; -#endif +using namespace cmFSPermissions; #if defined(_WIN32) // libcurl doesn't support file:// urls for unicode filenames on Windows. @@ -1099,29 +1075,7 @@ protected: // Translate an argument to a permissions bit. bool CheckPermissions(std::string const& arg, mode_t& permissions) { - if (arg == "OWNER_READ") { - permissions |= mode_owner_read; - } else if (arg == "OWNER_WRITE") { - permissions |= mode_owner_write; - } else if (arg == "OWNER_EXECUTE") { - permissions |= mode_owner_execute; - } else if (arg == "GROUP_READ") { - permissions |= mode_group_read; - } else if (arg == "GROUP_WRITE") { - permissions |= mode_group_write; - } else if (arg == "GROUP_EXECUTE") { - permissions |= mode_group_execute; - } else if (arg == "WORLD_READ") { - permissions |= mode_world_read; - } else if (arg == "WORLD_WRITE") { - permissions |= mode_world_write; - } else if (arg == "WORLD_EXECUTE") { - permissions |= mode_world_execute; - } else if (arg == "SETUID") { - permissions |= mode_setuid; - } else if (arg == "SETGID") { - permissions |= mode_setgid; - } else { + if (!cmFSPermissions::stringToModeT(arg, permissions)) { std::ostringstream e; e << this->Name << " given invalid permission \"" << arg << "\"."; this->FileCommand->SetError(e.str()); @@ -2015,9 +1969,30 @@ bool cmFileInstaller::HandleInstallDestination() this->DestDirLength = int(sdestdir.size()); } + // check if default dir creation permissions were set + mode_t default_dir_mode_v = 0; + mode_t* default_dir_mode = nullptr; + const char* default_dir_install_permissions = this->Makefile->GetDefinition( + "CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS"); + if (default_dir_install_permissions && *default_dir_install_permissions) { + std::vector<std::string> items; + cmSystemTools::ExpandListArgument(default_dir_install_permissions, items); + for (const auto& arg : items) { + if (!this->CheckPermissions(arg, default_dir_mode_v)) { + std::ostringstream e; + e << this->FileCommand->GetError() + << " Set with CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS variable."; + this->FileCommand->SetError(e.str()); + return false; + } + } + + default_dir_mode = &default_dir_mode_v; + } + if (this->InstallType != cmInstallType_DIRECTORY) { if (!cmSystemTools::FileExists(destination.c_str())) { - if (!cmSystemTools::MakeDirectory(destination.c_str())) { + if (!cmSystemTools::MakeDirectory(destination, default_dir_mode)) { std::string errstring = "cannot create directory: " + destination + ". Maybe need administrative privileges."; this->FileCommand->SetError(errstring); diff --git a/Source/cmGeneratorExpressionNode.cxx b/Source/cmGeneratorExpressionNode.cxx index 7fe0cbe..3d311d6 100644 --- a/Source/cmGeneratorExpressionNode.cxx +++ b/Source/cmGeneratorExpressionNode.cxx @@ -828,18 +828,21 @@ static const struct CompileLanguageNode : public cmGeneratorExpressionNode } std::string genName = gg->GetName(); if (genName.find("Visual Studio") != std::string::npos) { - reportError(context, content->GetOriginalExpression(), - "$<COMPILE_LANGUAGE:...> may not be used with Visual Studio " - "generators."); - return std::string(); - } - if (genName.find("Xcode") != std::string::npos) { if (dagChecker && (dagChecker->EvaluatingCompileDefinitions() || dagChecker->EvaluatingIncludeDirectories())) { reportError( context, content->GetOriginalExpression(), - "$<COMPILE_LANGUAGE:...> may only be used with COMPILE_OPTIONS " - "with the Xcode generator."); + "$<COMPILE_LANGUAGE:...> may only be used for COMPILE_OPTIONS " + "and file(GENERATE) with the Visual Studio generator."); + return std::string(); + } + } else if (genName.find("Xcode") != std::string::npos) { + if (dagChecker && (dagChecker->EvaluatingCompileDefinitions() || + dagChecker->EvaluatingIncludeDirectories())) { + reportError( + context, content->GetOriginalExpression(), + "$<COMPILE_LANGUAGE:...> may only be used for COMPILE_OPTIONS " + "and file(GENERATE) with the Xcode generator."); return std::string(); } } else { diff --git a/Source/cmGhsMultiTargetGenerator.cxx b/Source/cmGhsMultiTargetGenerator.cxx index a31e415..b3e3393 100644 --- a/Source/cmGhsMultiTargetGenerator.cxx +++ b/Source/cmGhsMultiTargetGenerator.cxx @@ -489,7 +489,7 @@ void cmGhsMultiTargetGenerator::WriteSources( char const* sourceFullPath = (*si)->GetFullPath().c_str(); cmSourceGroup* sourceGroup = this->Makefile->FindSourceGroup(sourceFullPath, sourceGroups); - std::string sgPath(sourceGroup->GetFullName()); + std::string sgPath = sourceGroup->GetFullName(); cmSystemTools::ConvertToUnixSlashes(sgPath); cmGlobalGhsMultiGenerator::AddFilesUpToPath( this->GetFolderBuildStreams(), &this->FolderBuildStreams, @@ -608,7 +608,7 @@ std::string cmGhsMultiTargetGenerator::ComputeLongestObjectDirectory( cmSourceGroup* sourceGroup = localGhsMultiGenerator->GetMakefile()->FindSourceGroup(sourceFullPath, sourceGroups); - std::string const sgPath(sourceGroup->GetFullName()); + std::string const& sgPath = sourceGroup->GetFullName(); dir_max += sgPath; dir_max += "/Objs/libs/"; dir_max += generatorTarget->Target->GetName(); diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index eba95f5..6e903fb 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1314,7 +1314,10 @@ bool cmGlobalGenerator::Compute() #ifdef CMAKE_BUILD_WITH_CMAKE // Iterate through all targets and set up automoc for those which have // the AUTOMOC, AUTOUIC or AUTORCC property set - cmQtAutoGenDigestUPV autogenDigests = this->CreateQtAutoGeneratorsTargets(); + auto autogenInits = this->CreateQtAutoGenInitializers(); + for (auto& autoGen : autogenInits) { + autoGen->InitCustomTargets(); + } #endif // Add generator specific helper commands @@ -1335,10 +1338,11 @@ bool cmGlobalGenerator::Compute() } #ifdef CMAKE_BUILD_WITH_CMAKE - for (cmQtAutoGenDigestUP const& digest : autogenDigests) { - cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget(*digest); + for (auto& autoGen : autogenInits) { + autoGen->SetupCustomTargets(); + autoGen.reset(nullptr); } - autogenDigests.clear(); + autogenInits.clear(); #endif for (cmLocalGenerator* localGen : this->LocalGenerators) { @@ -1469,9 +1473,10 @@ bool cmGlobalGenerator::ComputeTargetDepends() return true; } -cmQtAutoGenDigestUPV cmGlobalGenerator::CreateQtAutoGeneratorsTargets() +std::vector<std::unique_ptr<cmQtAutoGeneratorInitializer>> +cmGlobalGenerator::CreateQtAutoGenInitializers() { - cmQtAutoGenDigestUPV autogenDigests; + std::vector<std::unique_ptr<cmQtAutoGeneratorInitializer>> autogenInits; #ifdef CMAKE_BUILD_WITH_CMAKE for (cmLocalGenerator* localGen : this->LocalGenerators) { @@ -1507,25 +1512,12 @@ cmQtAutoGenDigestUPV cmGlobalGenerator::CreateQtAutoGeneratorsTargets() continue; } - { - cmQtAutoGenDigestUP digest(new cmQtAutoGenDigest(target)); - digest->QtVersionMajor = std::move(qtVersionMajor); - digest->QtVersionMinor = - cmQtAutoGeneratorInitializer::GetQtMinorVersion( - target, digest->QtVersionMajor); - digest->MocEnabled = mocEnabled; - digest->UicEnabled = uicEnabled; - digest->RccEnabled = rccEnabled; - autogenDigests.emplace_back(std::move(digest)); - } + autogenInits.emplace_back(new cmQtAutoGeneratorInitializer( + target, mocEnabled, uicEnabled, rccEnabled, qtVersionMajor)); } } - // Initialize autogen targets - for (const cmQtAutoGenDigestUP& digest : autogenDigests) { - cmQtAutoGeneratorInitializer::InitializeAutogenTarget(*digest); - } #endif - return autogenDigests; + return autogenInits; } cmLinkLineComputer* cmGlobalGenerator::CreateLinkLineComputer( diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 8fcb533..99f33e5 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -15,7 +15,6 @@ #include "cmCustomCommandLines.h" #include "cmExportSetMap.h" -#include "cmQtAutoGenDigest.h" #include "cmStateSnapshot.h" #include "cmSystemTools.h" #include "cmTarget.h" @@ -33,6 +32,7 @@ class cmLinkLineComputer; class cmLocalGenerator; class cmMakefile; class cmOutputConverter; +class cmQtAutoGeneratorInitializer; class cmSourceFile; class cmStateDirectory; class cmake; @@ -433,7 +433,8 @@ protected: virtual bool CheckALLOW_DUPLICATE_CUSTOM_TARGETS() const; // Qt auto generators - cmQtAutoGenDigestUPV CreateQtAutoGeneratorsTargets(); + std::vector<std::unique_ptr<cmQtAutoGeneratorInitializer>> + CreateQtAutoGenInitializers(); std::string SelectMakeProgram(const std::string& makeProgram, const std::string& makeDefault = "") const; diff --git a/Source/cmGlobalVisualStudio8Generator.cxx b/Source/cmGlobalVisualStudio8Generator.cxx index dee874f..1743b18 100644 --- a/Source/cmGlobalVisualStudio8Generator.cxx +++ b/Source/cmGlobalVisualStudio8Generator.cxx @@ -225,9 +225,9 @@ bool cmGlobalVisualStudio8Generator::AddCheckTarget() } cmCustomCommandLines noCommandLines; - cmTarget* tgt = - mf->AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, false, - no_working_directory, no_depends, noCommandLines); + cmTarget* tgt = mf->AddUtilityCommand( + CMAKE_CHECK_BUILD_SYSTEM_TARGET, cmMakefile::TargetOrigin::Generator, + false, no_working_directory, no_depends, noCommandLines); cmGeneratorTarget* gt = new cmGeneratorTarget(tgt, lg); lg->AddGeneratorTarget(gt); diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index 99600df..c89c2c4 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -69,8 +69,8 @@ void cmGlobalVisualStudioGenerator::AddExtraIDETargets() // Use no actual command lines so that the target itself is not // considered always out of date. cmTarget* allBuild = gen[0]->GetMakefile()->AddUtilityCommand( - "ALL_BUILD", true, no_working_dir, no_depends, no_commands, false, - "Build all projects"); + "ALL_BUILD", cmMakefile::TargetOrigin::Generator, true, no_working_dir, + no_depends, no_commands, false, "Build all projects"); cmGeneratorTarget* gt = new cmGeneratorTarget(allBuild, gen[0]); gen[0]->AddGeneratorTarget(gt); diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index a85a700..c376c8d 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -368,14 +368,13 @@ cmLocalGenerator* cmGlobalXCodeGenerator::CreateLocalGenerator(cmMakefile* mf) void cmGlobalXCodeGenerator::AddExtraIDETargets() { - std::map<std::string, std::vector<cmLocalGenerator*>>::iterator it; // make sure extra targets are added before calling // the parent generate which will call trace depends - for (it = this->ProjectMap.begin(); it != this->ProjectMap.end(); ++it) { - cmLocalGenerator* root = it->second[0]; + for (auto keyVal : this->ProjectMap) { + cmLocalGenerator* root = keyVal.second[0]; this->SetGenerationRoot(root); // add ALL_BUILD, INSTALL, etc - this->AddExtraTargets(root, it->second); + this->AddExtraTargets(root, keyVal.second); } } @@ -385,9 +384,8 @@ void cmGlobalXCodeGenerator::Generate() if (cmSystemTools::GetErrorOccuredFlag()) { return; } - std::map<std::string, std::vector<cmLocalGenerator*>>::iterator it; - for (it = this->ProjectMap.begin(); it != this->ProjectMap.end(); ++it) { - cmLocalGenerator* root = it->second[0]; + for (auto keyVal : this->ProjectMap) { + cmLocalGenerator* root = keyVal.second[0]; bool generateTopLevelProjectOnly = root->GetMakefile()->IsOn("CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY"); @@ -401,7 +399,7 @@ void cmGlobalXCodeGenerator::Generate() this->SetGenerationRoot(root); // now create the project - this->OutputXCodeProject(root, it->second); + this->OutputXCodeProject(root, keyVal.second); } } @@ -442,9 +440,9 @@ void cmGlobalXCodeGenerator::AddExtraTargets( // Add ALL_BUILD const char* no_working_directory = nullptr; std::vector<std::string> no_depends; - cmTarget* allbuild = - mf->AddUtilityCommand("ALL_BUILD", true, no_depends, no_working_directory, - "echo", "Build all projects"); + cmTarget* allbuild = mf->AddUtilityCommand( + "ALL_BUILD", cmMakefile::TargetOrigin::Generator, true, no_depends, + no_working_directory, "echo", "Build all projects"); cmGeneratorTarget* allBuildGt = new cmGeneratorTarget(allbuild, root); root->AddGeneratorTarget(allBuildGt); @@ -466,9 +464,9 @@ void cmGlobalXCodeGenerator::AddExtraTargets( std::string file = this->ConvertToRelativeForMake(this->CurrentReRunCMakeMakefile.c_str()); cmSystemTools::ReplaceString(file, "\\ ", " "); - cmTarget* check = - mf->AddUtilityCommand(CMAKE_CHECK_BUILD_SYSTEM_TARGET, true, no_depends, - no_working_directory, "make", "-f", file.c_str()); + cmTarget* check = mf->AddUtilityCommand( + CMAKE_CHECK_BUILD_SYSTEM_TARGET, cmMakefile::TargetOrigin::Generator, + true, no_depends, no_working_directory, "make", "-f", file.c_str()); cmGeneratorTarget* checkGt = new cmGeneratorTarget(check, root); root->AddGeneratorTarget(checkGt); @@ -481,8 +479,7 @@ void cmGlobalXCodeGenerator::AddExtraTargets( continue; } - const std::vector<cmGeneratorTarget*>& tgts = gen->GetGeneratorTargets(); - for (auto target : tgts) { + for (auto target : gen->GetGeneratorTargets()) { if (target->GetType() == cmStateEnums::GLOBAL_TARGET) { continue; } @@ -549,10 +546,9 @@ void cmGlobalXCodeGenerator::CreateReRunCMakeFile( makefileStream << "space:= $(empty) $(empty)\n"; makefileStream << "spaceplus:= $(empty)\\ $(empty)\n\n"; - for (std::vector<std::string>::const_iterator i = lfiles.begin(); - i != lfiles.end(); ++i) { + for (const auto& lfile : lfiles) { makefileStream << "TARGETS += $(subst $(space),$(spaceplus),$(wildcard " - << this->ConvertToRelativeForMake(i->c_str()) << "))\n"; + << this->ConvertToRelativeForMake(lfile.c_str()) << "))\n"; } std::string checkCache = root->GetBinaryDirectory(); @@ -761,9 +757,8 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateXCodeSourceFile( cmSystemTools::ExpandListArgument(extraFileAttributes, attributes); // Store the attributes. - for (std::vector<std::string>::const_iterator ai = attributes.begin(); - ai != attributes.end(); ++ai) { - attrs->AddObject(this->CreateString(*ai)); + for (const auto& attribute : attributes) { + attrs->AddObject(this->CreateString(attribute)); } } @@ -958,12 +953,10 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets( cmLocalGenerator* gen, std::vector<cmXCodeObject*>& targets) { this->SetCurrentLocalGenerator(gen); - const std::vector<cmGeneratorTarget*>& tgts = - this->CurrentLocalGenerator->GetGeneratorTargets(); typedef std::map<std::string, cmGeneratorTarget*, cmCompareTargets> cmSortedTargets; cmSortedTargets sortedTargets; - for (auto tgt : tgts) { + for (auto tgt : this->CurrentLocalGenerator->GetGeneratorTargets()) { sortedTargets[tgt->GetName()] = tgt; } for (auto& sortedTarget : sortedTargets) { @@ -1010,21 +1003,20 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets( std::vector<cmXCodeObject*> headerFiles; std::vector<cmXCodeObject*> resourceFiles; std::vector<cmXCodeObject*> sourceFiles; - for (std::vector<cmSourceFile*>::const_iterator i = classes.begin(); - i != classes.end(); ++i) { - cmXCodeObject* xsf = - this->CreateXCodeSourceFile(this->CurrentLocalGenerator, *i, gtgt); + for (auto sourceFile : classes) { + cmXCodeObject* xsf = this->CreateXCodeSourceFile( + this->CurrentLocalGenerator, sourceFile, gtgt); cmXCodeObject* fr = xsf->GetObject("fileRef"); cmXCodeObject* filetype = fr->GetObject()->GetObject("explicitFileType"); cmGeneratorTarget::SourceFileFlags tsFlags = - gtgt->GetTargetSourceFileFlags(*i); + gtgt->GetTargetSourceFileFlags(sourceFile); if (filetype && filetype->GetString() == "compiled.mach-o.objfile") { - if ((*i)->GetObjectLibrary().empty()) { + if (sourceFile->GetObjectLibrary().empty()) { externalObjFiles.push_back(xsf); } - } else if (this->IsHeaderFile(*i) || + } else if (this->IsHeaderFile(sourceFile) || (tsFlags.Type == cmGeneratorTarget::SourceFileTypePrivateHeader) || (tsFlags.Type == @@ -1032,12 +1024,13 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets( headerFiles.push_back(xsf); } else if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeResource) { resourceFiles.push_back(xsf); - } else if (!(*i)->GetPropertyAsBool("HEADER_FILE_ONLY")) { + } else if (!sourceFile->GetPropertyAsBool("HEADER_FILE_ONLY")) { // Include this file in the build if it has a known language // and has not been listed as an ignored extension for this // generator. - if (!this->CurrentLocalGenerator->GetSourceFileLanguage(**i).empty() && - !this->IgnoreFile((*i)->GetExtension().c_str())) { + if (!this->CurrentLocalGenerator->GetSourceFileLanguage(*sourceFile) + .empty() && + !this->IgnoreFile(sourceFile->GetExtension().c_str())) { sourceFiles.push_back(xsf); } } @@ -1049,12 +1042,11 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets( // within the target.) std::vector<cmSourceFile const*> objs; gtgt->GetExternalObjects(objs, ""); - for (std::vector<cmSourceFile const*>::const_iterator oi = objs.begin(); - oi != objs.end(); ++oi) { - if ((*oi)->GetObjectLibrary().empty()) { + for (auto sourceFile : objs) { + if (sourceFile->GetObjectLibrary().empty()) { continue; } - std::string const& obj = (*oi)->GetFullPath(); + std::string const& obj = sourceFile->GetFullPath(); cmXCodeObject* xsf = this->CreateXCodeSourceFileFromPath(obj, gtgt, "", nullptr); externalObjFiles.push_back(xsf); @@ -1127,16 +1119,14 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets( typedef std::map<std::string, std::vector<cmSourceFile*>> mapOfVectorOfSourceFiles; mapOfVectorOfSourceFiles bundleFiles; - for (std::vector<cmSourceFile*>::const_iterator i = classes.begin(); - i != classes.end(); ++i) { + for (auto sourceFile : classes) { cmGeneratorTarget::SourceFileFlags tsFlags = - gtgt->GetTargetSourceFileFlags(*i); + gtgt->GetTargetSourceFileFlags(sourceFile); if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeMacContent) { - bundleFiles[tsFlags.MacFolder].push_back(*i); + bundleFiles[tsFlags.MacFolder].push_back(sourceFile); } } - mapOfVectorOfSourceFiles::iterator mit; - for (mit = bundleFiles.begin(); mit != bundleFiles.end(); ++mit) { + for (auto keySources : bundleFiles) { cmXCodeObject* copyFilesBuildPhase = this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase); copyFilesBuildPhase->SetComment("Copy files"); @@ -1147,13 +1137,13 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets( std::ostringstream ostr; if (gtgt->IsFrameworkOnApple()) { // dstPath in frameworks is relative to Versions/<version> - ostr << mit->first; - } else if (mit->first != "MacOS") { + ostr << keySources.first; + } else if (keySources.first != "MacOS") { if (gtgt->Target->GetMakefile()->PlatformIsAppleIos()) { - ostr << mit->first; + ostr << keySources.first; } else { // dstPath in bundles is relative to Contents/MacOS - ostr << "../" << mit->first; + ostr << "../" << keySources.first; } } copyFilesBuildPhase->AddAttribute("dstPath", @@ -1162,10 +1152,9 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets( this->CreateString("0")); buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); copyFilesBuildPhase->AddAttribute("files", buildFiles); - std::vector<cmSourceFile*>::iterator sfIt; - for (sfIt = mit->second.begin(); sfIt != mit->second.end(); ++sfIt) { + for (auto sourceFile : keySources.second) { cmXCodeObject* xsf = this->CreateXCodeSourceFile( - this->CurrentLocalGenerator, *sfIt, gtgt); + this->CurrentLocalGenerator, sourceFile, gtgt); buildFiles->AddObject(xsf); } contentBuildPhases.push_back(copyFilesBuildPhase); @@ -1178,16 +1167,14 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets( typedef std::map<std::string, std::vector<cmSourceFile*>> mapOfVectorOfSourceFiles; mapOfVectorOfSourceFiles bundleFiles; - for (std::vector<cmSourceFile*>::const_iterator i = classes.begin(); - i != classes.end(); ++i) { + for (auto sourceFile : classes) { cmGeneratorTarget::SourceFileFlags tsFlags = - gtgt->GetTargetSourceFileFlags(*i); + gtgt->GetTargetSourceFileFlags(sourceFile); if (tsFlags.Type == cmGeneratorTarget::SourceFileTypeDeepResource) { - bundleFiles[tsFlags.MacFolder].push_back(*i); + bundleFiles[tsFlags.MacFolder].push_back(sourceFile); } } - mapOfVectorOfSourceFiles::iterator mit; - for (mit = bundleFiles.begin(); mit != bundleFiles.end(); ++mit) { + for (auto keySources : bundleFiles) { cmXCodeObject* copyFilesBuildPhase = this->CreateObject(cmXCodeObject::PBXCopyFilesBuildPhase); copyFilesBuildPhase->SetComment("Copy files"); @@ -1195,16 +1182,15 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets( this->CreateString("2147483647")); copyFilesBuildPhase->AddAttribute("dstSubfolderSpec", this->CreateString("7")); - copyFilesBuildPhase->AddAttribute("dstPath", - this->CreateString(mit->first)); + copyFilesBuildPhase->AddAttribute( + "dstPath", this->CreateString(keySources.first)); copyFilesBuildPhase->AddAttribute("runOnlyForDeploymentPostprocessing", this->CreateString("0")); buildFiles = this->CreateObject(cmXCodeObject::OBJECT_LIST); copyFilesBuildPhase->AddAttribute("files", buildFiles); - std::vector<cmSourceFile*>::iterator sfIt; - for (sfIt = mit->second.begin(); sfIt != mit->second.end(); ++sfIt) { + for (auto sourceFile : keySources.second) { cmXCodeObject* xsf = this->CreateXCodeSourceFile( - this->CurrentLocalGenerator, *sfIt, gtgt); + this->CurrentLocalGenerator, sourceFile, gtgt); buildFiles->AddObject(xsf); } contentBuildPhases.push_back(copyFilesBuildPhase); @@ -1243,11 +1229,9 @@ bool cmGlobalXCodeGenerator::CreateXCodeTargets( void cmGlobalXCodeGenerator::ForceLinkerLanguages() { - for (auto& localGenerator : this->LocalGenerators) { - const std::vector<cmGeneratorTarget*>& tgts = - localGenerator->GetGeneratorTargets(); + for (auto localGenerator : this->LocalGenerators) { // All targets depend on the build-system check target. - for (auto tgt : tgts) { + for (auto tgt : localGenerator->GetGeneratorTargets()) { // This makes sure all targets link using the proper language. this->ForceLinkerLanguage(tgt); } @@ -1269,8 +1253,8 @@ void cmGlobalXCodeGenerator::ForceLinkerLanguage(cmGeneratorTarget* gtgt) } // If the language is compiled as a source trust Xcode to link with it. - cmLinkImplementation const* impl = gtgt->GetLinkImplementation("NOCONFIG"); - for (auto const& Language : impl->Languages) { + for (auto const& Language : + gtgt->GetLinkImplementation("NOCONFIG")->Languages) { if (Language == llang) { return; } @@ -1370,10 +1354,9 @@ void cmGlobalXCodeGenerator::CreateCustomCommands( } // add all the sources std::vector<cmCustomCommand> commands; - for (std::vector<cmSourceFile*>::const_iterator i = classes.begin(); - i != classes.end(); ++i) { - if ((*i)->GetCustomCommand()) { - commands.push_back(*(*i)->GetCustomCommand()); + for (auto sourceFile : classes) { + if (sourceFile->GetCustomCommand()) { + commands.push_back(*sourceFile->GetCustomCommand()); } } // create prebuild phase @@ -1405,10 +1388,8 @@ void cmGlobalXCodeGenerator::CreateCustomCommands( if (resourceBuildPhase) { buildPhases->AddObject(resourceBuildPhase); } - std::vector<cmXCodeObject*>::iterator cit; - for (cit = contentBuildPhases.begin(); cit != contentBuildPhases.end(); - ++cit) { - buildPhases->AddObject(*cit); + for (auto obj : contentBuildPhases) { + buildPhases->AddObject(obj); } if (sourceBuildPhase) { buildPhases->AddObject(sourceBuildPhase); @@ -1531,12 +1512,9 @@ void cmGlobalXCodeGenerator::AddCommandsToBuildPhase( makefile += name; makefile += ".make"; - for (std::vector<std::string>::const_iterator currentConfig = - this->CurrentConfigurationTypes.begin(); - currentConfig != this->CurrentConfigurationTypes.end(); - currentConfig++) { + for (const auto& currentConfig : this->CurrentConfigurationTypes) { this->CreateCustomRulesMakefile(makefile.c_str(), target, commands, - *currentConfig); + currentConfig); } std::string cdir = this->CurrentLocalGenerator->GetCurrentBinaryDirectory(); @@ -2016,8 +1994,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, } // Add framework search paths needed for linking. if (cmComputeLinkInformation* cli = gtgt->GetLinkInformation(configName)) { - std::vector<std::string> const& fwDirs = cli->GetFrameworkPaths(); - for (auto const& fwDir : fwDirs) { + for (auto const& fwDir : cli->GetFrameworkPaths()) { if (emitted.insert(fwDir).second) { std::string incpath = this->XCodeEscapePath(fwDir); if (emitSystemIncludes && @@ -2182,9 +2159,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, // runpath dirs needs to be unique to prevent corruption std::set<std::string> unique_dirs; - for (std::vector<std::string>::const_iterator i = runtimeDirs.begin(); - i != runtimeDirs.end(); ++i) { - std::string runpath = *i; + for (auto runpath : runtimeDirs) { runpath = this->ExpandCFGIntDir(runpath, configName); if (unique_dirs.find(runpath) == unique_dirs.end()) { @@ -2244,8 +2219,7 @@ void cmGlobalXCodeGenerator::CreateBuildSettings(cmGeneratorTarget* gtgt, // put this last so it can override existing settings // Convert "XCODE_ATTRIBUTE_*" properties directly. { - std::vector<std::string> const& props = gtgt->GetPropertyKeys(); - for (auto const& prop : props) { + for (auto const& prop : gtgt->GetPropertyKeys()) { if (prop.find("XCODE_ATTRIBUTE_") == 0) { std::string attribute = prop.substr(16); this->FilterConfigurationAttribute(configName, attribute); @@ -2312,10 +2286,9 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateUtilityTarget( listfile += "/CMakeLists.txt"; sources.push_back(gtgt->Makefile->GetOrCreateSource(listfile)); - for (std::vector<cmSourceFile*>::const_iterator i = sources.begin(); - i != sources.end(); ++i) { - if (!(*i)->GetPropertyAsBool("GENERATED")) { - this->CreateXCodeFileReference(*i, gtgt); + for (auto sourceFile : sources) { + if (!sourceFile->GetPropertyAsBool("GENERATED")) { + this->CreateXCodeFileReference(sourceFile, gtgt); } } } @@ -2584,17 +2557,10 @@ void cmGlobalXCodeGenerator::AppendBuildSettingAttribute( target->GetObject("buildConfigurationList")->GetObject(); cmXCodeObject* buildConfigs = configurationList->GetObject("buildConfigurations"); - std::vector<cmXCodeObject*> list = buildConfigs->GetObjectList(); - // each configuration and the target itself has a buildSettings in it - // list.push_back(target); - for (auto& i : list) { - if (!configName.empty()) { - if (i->GetObject("name")->GetString() == configName) { - cmXCodeObject* settings = i->GetObject("buildSettings"); - this->AppendOrAddBuildSetting(settings, attribute, value); - } - } else { - cmXCodeObject* settings = i->GetObject("buildSettings"); + for (auto obj : buildConfigs->GetObjectList()) { + if (configName.empty() || + obj->GetObject("name")->GetString() == configName) { + cmXCodeObject* settings = obj->GetObject("buildSettings"); this->AppendOrAddBuildSetting(settings, attribute, value); } } @@ -2612,8 +2578,7 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) } // Add dependencies on other CMake targets. - TargetDependSet const& deps = this->GetTargetDirectDepends(gt); - for (auto dep : deps) { + for (const auto& dep : this->GetTargetDirectDepends(gt)) { if (cmXCodeObject* dptarget = this->FindXCodeTarget(dep)) { this->AddDependTarget(target, dptarget); } @@ -2628,14 +2593,13 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) const char* sep = ""; std::vector<cmSourceFile const*> objs; gt->GetExternalObjects(objs, configName); - for (std::vector<cmSourceFile const*>::const_iterator oi = objs.begin(); - oi != objs.end(); ++oi) { - if ((*oi)->GetObjectLibrary().empty()) { + for (auto sourceFile : objs) { + if (sourceFile->GetObjectLibrary().empty()) { continue; } linkObjs += sep; sep = " "; - linkObjs += this->XCodeEscapePath((*oi)->GetFullPath()); + linkObjs += this->XCodeEscapePath(sourceFile->GetFullPath()); } this->AppendBuildSettingAttribute( target, this->GetTargetLinkFlagsVar(gt), linkObjs.c_str(), configName); @@ -2655,18 +2619,14 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) cmComputeLinkInformation& cli = *pcli; // Add dependencies directly on library files. - { - std::vector<std::string> const& libDeps = cli.GetDepends(); - for (auto const& libDep : libDeps) { - target->AddDependLibrary(configName, libDep); - } + for (auto const& libDep : cli.GetDepends()) { + target->AddDependLibrary(configName, libDep); } // add the library search paths { - std::vector<std::string> const& libDirs = cli.GetDirectories(); std::string linkDirs; - for (auto const& libDir : libDirs) { + for (auto const& libDir : cli.GetDirectories()) { if (!libDir.empty() && libDir != "/usr/lib") { // Now add the same one but append // $(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) to it: @@ -2685,9 +2645,7 @@ void cmGlobalXCodeGenerator::AddDependAndLinkInformation(cmXCodeObject* target) { std::string linkLibs; const char* sep = ""; - typedef cmComputeLinkInformation::ItemVector ItemVector; - ItemVector const& libNames = cli.GetItems(); - for (auto const& libName : libNames) { + for (auto const& libName : cli.GetItems()) { linkLibs += sep; sep = " "; if (libName.IsPath) { @@ -2713,9 +2671,7 @@ bool cmGlobalXCodeGenerator::CreateGroups( for (auto& generator : generators) { cmMakefile* mf = generator->GetMakefile(); std::vector<cmSourceGroup> sourceGroups = mf->GetSourceGroups(); - const std::vector<cmGeneratorTarget*>& tgts = - generator->GetGeneratorTargets(); - for (auto gtgt : tgts) { + for (auto gtgt : generator->GetGeneratorTargets()) { // Same skipping logic here as in CreateXCodeTargets so that we do not // end up with (empty anyhow) ZERO_CHECK, install, or test source // groups: @@ -2738,11 +2694,8 @@ bool cmGlobalXCodeGenerator::CreateGroups( gtgt->AddSource(plist); } - std::vector<cmGeneratorTarget::AllConfigSource> const& sources = - gtgt->GetAllConfigSources(); - // Put cmSourceFile instances in proper groups: - for (auto const& si : sources) { + for (auto const& si : gtgt->GetAllConfigSources()) { cmSourceFile const* sf = si.Source; if (this->XcodeVersion >= 50 && !sf->GetObjectLibrary().empty()) { // Object library files go on the link line instead. @@ -2844,18 +2797,17 @@ cmXCodeObject* cmGlobalXCodeGenerator::CreateOrGetPBXGroup( // If it's the default source group (empty name) then put the source file // directly in the tgroup... // - if (std::string(sg->GetFullName()).empty()) { + if (sg->GetFullName().empty()) { this->GroupNameMap[s] = tgroup; return tgroup; } // It's a recursive folder structure, let's find the real parent group - if (std::string(sg->GetFullName()) != std::string(sg->GetName())) { - std::vector<std::string> folders = - cmSystemTools::tokenize(sg->GetFullName(), "\\"); + if (sg->GetFullName() != sg->GetName()) { std::string curr_folder = target; curr_folder += "/"; - for (auto const& folder : folders) { + for (auto const& folder : + cmSystemTools::tokenize(sg->GetFullName(), "\\")) { curr_folder += folder; std::map<std::string, cmXCodeObject*>::iterator i_folder = this->GroupNameMap.find(curr_folder); @@ -2960,10 +2912,9 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( this->CreateObject(cmXCodeObject::OBJECT_LIST); typedef std::vector<std::pair<std::string, cmXCodeObject*>> Configs; Configs configs; - const char* defaultConfigName = "Debug"; - for (unsigned int i = 0; i < this->CurrentConfigurationTypes.size(); ++i) { - const char* name = this->CurrentConfigurationTypes[i].c_str(); - if (0 == i) { + std::string defaultConfigName; + for (const auto& name : this->CurrentConfigurationTypes) { + if (defaultConfigName.empty()) { defaultConfigName = name; } cmXCodeObject* config = @@ -2971,6 +2922,9 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( config->AddAttribute("name", this->CreateString(name)); configs.push_back(std::make_pair(name, config)); } + if (defaultConfigName.empty()) { + defaultConfigName = "Debug"; + } for (auto& config : configs) { buildConfigurations->AddObject(config.second); } @@ -3035,16 +2989,14 @@ bool cmGlobalXCodeGenerator::CreateXCodeObjects( // Put this last so it can override existing settings // Convert "CMAKE_XCODE_ATTRIBUTE_*" variables directly. - std::vector<std::string> vars = this->CurrentMakefile->GetDefinitions(); - for (std::vector<std::string>::const_iterator d = vars.begin(); - d != vars.end(); ++d) { - if (d->find("CMAKE_XCODE_ATTRIBUTE_") == 0) { - std::string attribute = d->substr(22); + for (const auto& var : this->CurrentMakefile->GetDefinitions()) { + if (var.find("CMAKE_XCODE_ATTRIBUTE_") == 0) { + std::string attribute = var.substr(22); this->FilterConfigurationAttribute(config.first, attribute); if (!attribute.empty()) { cmGeneratorExpression ge; std::string processed = - ge.Parse(this->CurrentMakefile->GetDefinition(*d)) + ge.Parse(this->CurrentMakefile->GetDefinition(var)) ->Evaluate(this->CurrentLocalGenerator, config.first); buildSettingsForCfg->AddAttribute(attribute, this->CreateString(processed)); @@ -3160,10 +3112,7 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( "# link. This forces Xcode to relink the targets from scratch. It\n" "# does not seem to check these dependencies itself.\n"; /* clang-format on */ - for (std::vector<std::string>::const_iterator ct = - this->CurrentConfigurationTypes.begin(); - ct != this->CurrentConfigurationTypes.end(); ++ct) { - std::string configName = *ct; + for (const auto& configName : this->CurrentConfigurationTypes) { for (auto target : targets) { cmGeneratorTarget* gt = target->GetTarget(); @@ -3173,7 +3122,7 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( gt->GetType() == cmStateEnums::SHARED_LIBRARY || gt->GetType() == cmStateEnums::MODULE_LIBRARY) { // Declare an entry point for the target post-build phase. - makefileStream << this->PostBuildMakeTarget(gt->GetName(), *ct) + makefileStream << this->PostBuildMakeTarget(gt->GetName(), configName) << ":\n"; } @@ -3186,21 +3135,19 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( // Add this target to the post-build phases of its dependencies. std::map<std::string, cmXCodeObject::StringVec>::const_iterator y = - target->GetDependTargets().find(*ct); + target->GetDependTargets().find(configName); if (y != target->GetDependTargets().end()) { - std::vector<std::string> const& deptgts = y->second; - for (auto const& deptgt : deptgts) { - makefileStream << this->PostBuildMakeTarget(deptgt, *ct) << ": " - << trel << "\n"; + for (auto const& deptgt : y->second) { + makefileStream << this->PostBuildMakeTarget(deptgt, configName) + << ": " << trel << "\n"; } } std::vector<cmGeneratorTarget*> objlibs; gt->GetObjectLibrariesCMP0026(objlibs); - for (std::vector<cmGeneratorTarget*>::const_iterator it = - objlibs.begin(); - it != objlibs.end(); ++it) { - makefileStream << this->PostBuildMakeTarget((*it)->GetName(), *ct) + for (auto objLib : objlibs) { + makefileStream << this->PostBuildMakeTarget(objLib->GetName(), + configName) << ": " << trel << "\n"; } @@ -3209,23 +3156,20 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( // List dependencies if any exist. std::map<std::string, cmXCodeObject::StringVec>::const_iterator x = - target->GetDependLibraries().find(*ct); + target->GetDependLibraries().find(configName); if (x != target->GetDependLibraries().end()) { - std::vector<std::string> const& deplibs = x->second; - for (auto const& deplib : deplibs) { + for (auto const& deplib : x->second) { std::string file = this->ConvertToRelativeForMake(deplib.c_str()); makefileStream << "\\\n\t" << file; dummyRules.insert(file); } } - for (std::vector<cmGeneratorTarget*>::const_iterator it = - objlibs.begin(); - it != objlibs.end(); ++it) { + for (auto objLib : objlibs) { - const std::string objLibName = (*it)->GetName(); + const std::string objLibName = objLib->GetName(); std::string d = this->GetObjectsNormalDirectory(this->CurrentProject, - configName, *it); + configName, objLib); d += "lib"; d += objLibName; d += ".a"; @@ -3245,7 +3189,7 @@ void cmGlobalXCodeGenerator::CreateXCodeDependHackTarget( if (this->Architectures.size() > 1) { std::string universal = this->GetObjectsNormalDirectory( this->CurrentProject, configName, gt); - for (auto& architecture : this->Architectures) { + for (const auto& architecture : this->Architectures) { std::string universalFile = universal; universalFile += architecture; universalFile += "/"; @@ -3276,7 +3220,7 @@ void cmGlobalXCodeGenerator::OutputXCodeProject( return; } // Skip local generators that are excluded from this project. - for (auto& generator : generators) { + for (auto generator : generators) { if (this->IsExcluded(root, generator)) { continue; } @@ -3298,9 +3242,9 @@ void cmGlobalXCodeGenerator::OutputXCodeProject( } this->WriteXCodePBXProj(fout, root, generators); - // Since the lowest available Xcode version for testing was 7.0, + // Since the lowest available Xcode version for testing was 6.4, // I'm setting this as a limit then - if (this->XcodeVersion >= 70) { + if (this->XcodeVersion >= 64) { if (root->GetMakefile()->GetCMakeInstance()->GetIsInTryCompile() || root->GetMakefile()->IsOn("CMAKE_XCODE_GENERATE_SCHEME")) { this->OutputXCodeSharedSchemes(xcodeDir); @@ -3322,10 +3266,7 @@ void cmGlobalXCodeGenerator::OutputXCodeSharedSchemes( // collect all tests for the targets std::map<std::string, cmXCodeScheme::TestObjects> testables; - for (std::vector<cmXCodeObject*>::const_iterator i = - this->XCodeObjects.begin(); - i != this->XCodeObjects.end(); ++i) { - cmXCodeObject* obj = *i; + for (auto obj : this->XCodeObjects) { if (obj->GetType() != cmXCodeObject::OBJECT || obj->GetIsA() != cmXCodeObject::PBXNativeTarget) { continue; @@ -3344,10 +3285,7 @@ void cmGlobalXCodeGenerator::OutputXCodeSharedSchemes( } // generate scheme - for (std::vector<cmXCodeObject*>::const_iterator i = - this->XCodeObjects.begin(); - i != this->XCodeObjects.end(); ++i) { - cmXCodeObject* obj = *i; + for (auto obj : this->XCodeObjects) { if (obj->GetType() == cmXCodeObject::OBJECT && (obj->GetIsA() == cmXCodeObject::PBXNativeTarget || obj->GetIsA() == cmXCodeObject::PBXAggregateTarget)) { @@ -3576,17 +3514,17 @@ void cmGlobalXCodeGenerator::AppendFlag(std::string& flags, } // Flag value with escaped quotes and backslashes. - for (const char* c = flag.c_str(); *c; ++c) { - if (*c == '\'') { + for (auto c : flag) { + if (c == '\'') { if (this->XcodeVersion >= 40) { flags += "'\\''"; } else { flags += "\\'"; } - } else if (*c == '\\') { + } else if (c == '\\') { flags += "\\\\"; } else { - flags += *c; + flags += c; } } diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 55952ef..c8d94c0 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -487,6 +487,20 @@ void cmLocalGenerator::GenerateInstallRules() /* clang-format on */ } + // Write default directory permissions. + if (const char* defaultDirPermissions = this->Makefile->GetDefinition( + "CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS")) { + /* clang-format off */ + fout << + "# Set default install directory permissions.\n" + "if(NOT DEFINED CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS)\n" + " set(CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS \"" + << defaultDirPermissions << "\")\n" + "endif()\n" + "\n"; + /* clang-format on */ + } + // Ask each install generator to write its code. std::vector<cmInstallGenerator*> const& installers = this->Makefile->GetInstallGenerators(); diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index beb80f2..f01ed7a 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -1600,7 +1600,7 @@ bool cmLocalVisualStudio7Generator::WriteGroup( } // If the group has a name, write the header. - std::string name = sg->GetName(); + std::string const& name = sg->GetName(); if (!name.empty()) { this->WriteVCProjBeginGroup(fout, name.c_str(), ""); } diff --git a/Source/cmLocalXCodeGenerator.cxx b/Source/cmLocalXCodeGenerator.cxx index 853e66c..457d1fd 100644 --- a/Source/cmLocalXCodeGenerator.cxx +++ b/Source/cmLocalXCodeGenerator.cxx @@ -42,8 +42,7 @@ void cmLocalXCodeGenerator::Generate() { cmLocalGenerator::Generate(); - const std::vector<cmGeneratorTarget*>& targets = this->GetGeneratorTargets(); - for (auto target : targets) { + for (auto target : this->GetGeneratorTargets()) { target->HasMacOSXRpathInstallNameDir(""); } } @@ -52,8 +51,7 @@ void cmLocalXCodeGenerator::GenerateInstallRules() { cmLocalGenerator::GenerateInstallRules(); - const std::vector<cmGeneratorTarget*>& targets = this->GetGeneratorTargets(); - for (auto target : targets) { + for (auto target : this->GetGeneratorTargets()) { target->HasMacOSXRpathInstallNameDir(""); } } diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 4109b90..a9de3f5 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -1007,7 +1007,7 @@ void cmMakefile::AddCustomCommandOldStyle( } cmTarget* cmMakefile::AddUtilityCommand( - const std::string& utilityName, bool excludeFromAll, + const std::string& utilityName, TargetOrigin origin, bool excludeFromAll, const std::vector<std::string>& depends, const char* workingDirectory, const char* command, const char* arg1, const char* arg2, const char* arg3, const char* arg4) @@ -1031,25 +1031,25 @@ cmTarget* cmMakefile::AddUtilityCommand( commandLines.push_back(commandLine); // Call the real signature of this method. - return this->AddUtilityCommand(utilityName, excludeFromAll, workingDirectory, - depends, commandLines); + return this->AddUtilityCommand(utilityName, origin, excludeFromAll, + workingDirectory, depends, commandLines); } cmTarget* cmMakefile::AddUtilityCommand( - const std::string& utilityName, bool excludeFromAll, + const std::string& utilityName, TargetOrigin origin, bool excludeFromAll, const char* workingDirectory, const std::vector<std::string>& depends, const cmCustomCommandLines& commandLines, bool escapeOldStyle, const char* comment, bool uses_terminal, bool command_expand_lists) { std::vector<std::string> no_byproducts; - return this->AddUtilityCommand(utilityName, excludeFromAll, workingDirectory, - no_byproducts, depends, commandLines, - escapeOldStyle, comment, uses_terminal, - command_expand_lists); + return this->AddUtilityCommand(utilityName, origin, excludeFromAll, + workingDirectory, no_byproducts, depends, + commandLines, escapeOldStyle, comment, + uses_terminal, command_expand_lists); } cmTarget* cmMakefile::AddUtilityCommand( - const std::string& utilityName, bool excludeFromAll, + const std::string& utilityName, TargetOrigin origin, bool excludeFromAll, const char* workingDirectory, const std::vector<std::string>& byproducts, const std::vector<std::string>& depends, const cmCustomCommandLines& commandLines, bool escapeOldStyle, @@ -1057,6 +1057,7 @@ cmTarget* cmMakefile::AddUtilityCommand( { // Create a target instance for this utility. cmTarget* target = this->AddNewTarget(cmStateEnums::UTILITY, utilityName); + target->SetIsGeneratorProvided(origin == TargetOrigin::Generator); if (excludeFromAll) { target->SetProperty("EXCLUDE_FROM_ALL", "TRUE"); } @@ -1950,7 +1951,7 @@ cmSourceGroup* cmMakefile::GetSourceGroup( // first look for source group starting with the same as the one we want for (cmSourceGroup const& srcGroup : this->SourceGroups) { - std::string sgName = srcGroup.GetName(); + std::string const& sgName = srcGroup.GetName(); if (sgName == name[0]) { sg = const_cast<cmSourceGroup*>(&srcGroup); break; @@ -2014,7 +2015,8 @@ void cmMakefile::AddSourceGroup(const std::vector<std::string>& name, } // build the whole source group path for (++i; i <= lastElement; ++i) { - sg->AddChild(cmSourceGroup(name[i].c_str(), nullptr, sg->GetFullName())); + sg->AddChild( + cmSourceGroup(name[i].c_str(), nullptr, sg->GetFullName().c_str())); sg = sg->LookupChild(name[i].c_str()); } @@ -3120,9 +3122,16 @@ void cmMakefile::SetArgcArgv(const std::vector<std::string>& args) cmSourceFile* cmMakefile::GetSource(const std::string& sourceName) const { cmSourceFileLocation sfl(this, sourceName); - for (cmSourceFile* sf : this->SourceFiles) { - if (sf->Matches(sfl)) { - return sf; + auto name = this->GetCMakeInstance()->StripExtension(sfl.GetName()); +#if defined(_WIN32) || defined(__APPLE__) + name = cmSystemTools::LowerCase(name); +#endif + auto sfsi = this->SourceFileSearchIndex.find(name); + if (sfsi != this->SourceFileSearchIndex.end()) { + for (auto sf : sfsi->second) { + if (sf->Matches(sfl)) { + return sf; + } } } return nullptr; @@ -3136,6 +3145,14 @@ cmSourceFile* cmMakefile::CreateSource(const std::string& sourceName, sf->SetProperty("GENERATED", "1"); } this->SourceFiles.push_back(sf); + + auto name = + this->GetCMakeInstance()->StripExtension(sf->GetLocation().GetName()); +#if defined(_WIN32) || defined(__APPLE__) + name = cmSystemTools::LowerCase(name); +#endif + this->SourceFileSearchIndex[name].push_back(sf); + return sf; } @@ -3319,13 +3336,6 @@ cmGlobalGenerator* cmMakefile::GetGlobalGenerator() const return this->GlobalGenerator; } -void cmMakefile::GetTestNames(std::vector<std::string>& testNames) -{ - for (const auto& iter : Tests) { - testNames.push_back(iter.first); - } -} - #ifdef CMAKE_BUILD_WITH_CMAKE cmVariableWatch* cmMakefile::GetVariableWatch() const { @@ -3661,6 +3671,16 @@ cmTest* cmMakefile::GetTest(const std::string& testName) const return nullptr; } +void cmMakefile::GetTests(const std::string& config, + std::vector<cmTest*>& tests) +{ + for (auto generator : this->GetTestGenerators()) { + if (generator->TestsForConfig(config)) { + tests.push_back(generator->GetTest()); + } + } +} + void cmMakefile::AddCMakeDependFilesFromUser() { std::vector<std::string> deps; diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 6867c02..737cab9 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -183,12 +183,19 @@ public: const std::vector<std::string>& srcs, bool excludeFromAll = false); + /** Where the target originated from. */ + enum class TargetOrigin + { + Project, + Generator + }; + /** * Add a utility to the build. A utiltity target is a command that * is run every time the target is built. */ cmTarget* AddUtilityCommand(const std::string& utilityName, - bool excludeFromAll, + TargetOrigin origin, bool excludeFromAll, const std::vector<std::string>& depends, const char* workingDirectory, const char* command, const char* arg1 = nullptr, @@ -196,13 +203,13 @@ public: const char* arg3 = nullptr, const char* arg4 = nullptr); cmTarget* AddUtilityCommand( - const std::string& utilityName, bool excludeFromAll, + const std::string& utilityName, TargetOrigin origin, bool excludeFromAll, const char* workingDirectory, const std::vector<std::string>& depends, const cmCustomCommandLines& commandLines, bool escapeOldStyle = true, const char* comment = nullptr, bool uses_terminal = false, bool command_expand_lists = false); cmTarget* AddUtilityCommand( - const std::string& utilityName, bool excludeFromAll, + const std::string& utilityName, TargetOrigin origin, bool excludeFromAll, const char* workingDirectory, const std::vector<std::string>& byproducts, const std::vector<std::string>& depends, const cmCustomCommandLines& commandLines, bool escapeOldStyle = true, @@ -617,11 +624,6 @@ public: cmGlobalGenerator* GetGlobalGenerator() const; /** - * Get all the test names this makefile knows about - */ - void GetTestNames(std::vector<std::string>& testNames); - - /** * Get all the source files this makefile knows about */ const std::vector<cmSourceFile*>& GetSourceFiles() const @@ -644,6 +646,11 @@ public: cmTest* GetTest(const std::string& testName) const; /** + * Get all tests that run under the given configuration. + */ + void GetTests(const std::string& config, std::vector<cmTest*>& tests); + + /** * Return a location of a file in cmake or custom modules directory */ std::string GetModulesFile(const char* name) const; @@ -821,7 +828,18 @@ protected: // libraries, classes, and executables mutable cmTargets Targets; std::map<std::string, std::string> AliasTargets; - std::vector<cmSourceFile*> SourceFiles; + + typedef std::vector<cmSourceFile*> SourceFileVec; + SourceFileVec SourceFiles; + + // Because cmSourceFile names are compared in a fuzzy way (see + // cmSourceFileLocation::Match()) we can't have a straight mapping from + // filename to cmSourceFile. To make lookups more efficient we store the + // Name portion of the cmSourceFileLocation and then compare on the list of + // cmSourceFiles that might match that name. Note that on platforms which + // have a case-insensitive filesystem we store the key in all lowercase. + typedef std::unordered_map<std::string, SourceFileVec> SourceFileMap; + SourceFileMap SourceFileSearchIndex; // Tests std::map<std::string, cmTest*> Tests; diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 7db010c..dd8a373 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -657,8 +657,8 @@ void cmMakefileTargetGenerator::WriteObjectBuildFile( } // Maybe insert a compiler launcher like ccache or distcc - if (!compileCommands.empty() && - (lang == "C" || lang == "CXX" || lang == "CUDA")) { + if (!compileCommands.empty() && (lang == "C" || lang == "CXX" || + lang == "Fortran" || lang == "CUDA")) { std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER"; const char* clauncher = this->GeneratorTarget->GetProperty(clauncher_prop); diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 5805259..0262b3c 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -647,7 +647,7 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang) // Maybe insert a compiler launcher like ccache or distcc if (!compileCmds.empty() && - (lang == "C" || lang == "CXX" || lang == "CUDA")) { + (lang == "C" || lang == "CXX" || lang == "Fortran" || lang == "CUDA")) { std::string const clauncher_prop = lang + "_COMPILER_LAUNCHER"; const char* clauncher = this->GeneratorTarget->GetProperty(clauncher_prop); if (clauncher && *clauncher) { diff --git a/Source/cmPolicies.h b/Source/cmPolicies.h index f614dca..c39f927 100644 --- a/Source/cmPolicies.h +++ b/Source/cmPolicies.h @@ -211,7 +211,10 @@ class cmMakefile; "Define file(GENERATE) behavior for relative paths.", 3, 10, 0, \ cmPolicies::WARN) \ SELECT(POLICY, CMP0071, "Let AUTOMOC and AUTOUIC process GENERATED files.", \ - 3, 10, 0, cmPolicies::WARN) + 3, 10, 0, cmPolicies::WARN) \ + SELECT(POLICY, CMP0072, \ + "FindOpenGL prefers GLVND by default when available.", 3, 11, 0, \ + cmPolicies::WARN) #define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1) #define CM_FOR_EACH_POLICY_ID(POLICY) \ diff --git a/Source/cmQtAutoGen.cxx b/Source/cmQtAutoGen.cxx index 9dc77ac..b9dd392 100644 --- a/Source/cmQtAutoGen.cxx +++ b/Source/cmQtAutoGen.cxx @@ -80,16 +80,6 @@ void MergeOptions(std::vector<std::string>& baseOpts, baseOpts.insert(baseOpts.end(), extraOpts.begin(), extraOpts.end()); } -static std::string utilStripCR(std::string const& line) -{ - // Strip CR characters rcc may have printed (possibly more than one!). - std::string::size_type cr = line.find('\r'); - if (cr != std::string::npos) { - return line.substr(0, cr); - } - return line; -} - /// @brief Reads the resource files list from from a .qrc file - Qt4 version /// @return True if the .qrc file was successfully parsed static bool RccListInputsQt4(std::string const& fileName, @@ -107,10 +97,10 @@ static bool RccListInputsQt4(std::string const& fileName, qrcContents = osst.str(); } else { if (errorMessage != nullptr) { - std::ostringstream ost; - ost << "rcc file not readable:\n" - << " " << cmQtAutoGen::Quoted(fileName) << "\n"; - *errorMessage = ost.str(); + std::string& err = *errorMessage; + err = "rcc file not readable:\n "; + err += cmQtAutoGen::Quoted(fileName); + err += "\n"; } allGood = false; } @@ -146,6 +136,7 @@ static bool RccListInputsQt4(std::string const& fileName, /// @brief Reads the resource files list from from a .qrc file - Qt5 version /// @return True if the .qrc file was successfully parsed static bool RccListInputsQt5(std::string const& rccCommand, + std::vector<std::string> const& rccListOptions, std::string const& fileName, std::vector<std::string>& files, std::string* errorMessage) @@ -155,24 +146,6 @@ static bool RccListInputsQt5(std::string const& rccCommand, return false; } - // Read rcc features - bool hasDashDashList = false; - { - std::vector<std::string> command; - command.push_back(rccCommand); - command.push_back("--help"); - std::string rccStdOut; - std::string rccStdErr; - int retVal = 0; - bool result = cmSystemTools::RunSingleCommand( - command, &rccStdOut, &rccStdErr, &retVal, nullptr, - cmSystemTools::OUTPUT_NONE, 0.0, cmProcessOutput::Auto); - if (result && retVal == 0 && - rccStdOut.find("--list") != std::string::npos) { - hasDashDashList = true; - } - } - std::string const fileDir = cmSystemTools::GetFilenamePath(fileName); std::string const fileNameName = cmSystemTools::GetFilenameName(fileName); @@ -184,7 +157,8 @@ static bool RccListInputsQt5(std::string const& rccCommand, { std::vector<std::string> command; command.push_back(rccCommand); - command.push_back(hasDashDashList ? "--list" : "-list"); + command.insert(command.end(), rccListOptions.begin(), + rccListOptions.end()); command.push_back(fileNameName); result = cmSystemTools::RunSingleCommand( command, &rccStdOut, &rccStdErr, &retVal, fileDir.c_str(), @@ -192,22 +166,32 @@ static bool RccListInputsQt5(std::string const& rccCommand, } if (!result || retVal) { if (errorMessage != nullptr) { - std::ostringstream ost; - ost << "rcc list process failed for\n " << cmQtAutoGen::Quoted(fileName) - << "\n" - << rccStdOut << "\n" - << rccStdErr << "\n"; - *errorMessage = ost.str(); + std::string& err = *errorMessage; + err = "rcc list process failed for:\n "; + err += cmQtAutoGen::Quoted(fileName); + err += "\n"; + err += rccStdOut; + err += "\n"; + err += rccStdErr; + err += "\n"; } return false; } + // Lambda to strip CR characters + auto StripCR = [](std::string& line) { + std::string::size_type cr = line.find('\r'); + if (cr != std::string::npos) { + line = line.substr(0, cr); + } + }; + // Parse rcc std output { std::istringstream ostr(rccStdOut); std::string oline; while (std::getline(ostr, oline)) { - oline = utilStripCR(oline); + StripCR(oline); if (!oline.empty()) { files.push_back(oline); } @@ -218,17 +202,17 @@ static bool RccListInputsQt5(std::string const& rccCommand, std::istringstream estr(rccStdErr); std::string eline; while (std::getline(estr, eline)) { - eline = utilStripCR(eline); + StripCR(eline); if (cmHasLiteralPrefix(eline, "RCC: Error in")) { static std::string searchString = "Cannot find file '"; std::string::size_type pos = eline.find(searchString); if (pos == std::string::npos) { if (errorMessage != nullptr) { - std::ostringstream ost; - ost << "rcc lists unparsable output:\n" - << cmQtAutoGen::Quoted(eline) << "\n"; - *errorMessage = ost.str(); + std::string& err = *errorMessage; + err = "rcc lists unparsable output:\n"; + err += cmQtAutoGen::Quoted(eline); + err += "\n"; } return false; } @@ -349,25 +333,26 @@ void cmQtAutoGen::RccMergeOptions(std::vector<std::string>& baseOpts, MergeOptions(baseOpts, newOpts, valueOpts, isQt5); } -bool cmQtAutoGen::RccListInputs(std::string const& qtMajorVersion, - std::string const& rccCommand, +bool cmQtAutoGen::RccListInputs(std::string const& rccCommand, + std::vector<std::string> const& rccListOptions, std::string const& fileName, std::vector<std::string>& files, std::string* errorMessage) { bool allGood = false; if (cmSystemTools::FileExists(fileName.c_str())) { - if (qtMajorVersion == "4") { + if (rccListOptions.empty()) { allGood = RccListInputsQt4(fileName, files, errorMessage); } else { - allGood = RccListInputsQt5(rccCommand, fileName, files, errorMessage); + allGood = RccListInputsQt5(rccCommand, rccListOptions, fileName, files, + errorMessage); } } else { if (errorMessage != nullptr) { - std::ostringstream ost; - ost << "rcc file does not exist:\n" - << " " << cmQtAutoGen::Quoted(fileName) << "\n"; - *errorMessage = ost.str(); + std::string& err = *errorMessage; + err = "rcc resource file does not exist:\n "; + err += cmQtAutoGen::Quoted(fileName); + err += "\n"; } } return allGood; diff --git a/Source/cmQtAutoGen.h b/Source/cmQtAutoGen.h index acc092f..e769e93 100644 --- a/Source/cmQtAutoGen.h +++ b/Source/cmQtAutoGen.h @@ -61,9 +61,9 @@ public: /// @brief Reads the resource files list from from a .qrc file /// @arg fileName Must be the absolute path of the .qrc file - /// @return True if the rcc file was successfully parsed - static bool RccListInputs(std::string const& qtMajorVersion, - std::string const& rccCommand, + /// @return True if the rcc file was successfully read + static bool RccListInputs(std::string const& rccCommand, + std::vector<std::string> const& rccListOptions, std::string const& fileName, std::vector<std::string>& files, std::string* errorMessage = nullptr); diff --git a/Source/cmQtAutoGenDigest.h b/Source/cmQtAutoGenDigest.h deleted file mode 100644 index 677c397..0000000 --- a/Source/cmQtAutoGenDigest.h +++ /dev/null @@ -1,64 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmQtAutoGenDigest_h -#define cmQtAutoGenDigest_h - -#include "cmConfigure.h" // IWYU pragma: keep - -#include <memory> -#include <string> -#include <vector> - -class cmGeneratorTarget; - -class cmQtAutoGenDigestQrc -{ -public: - cmQtAutoGenDigestQrc() - : Generated(false) - , Unique(false) - { - } - -public: - std::string QrcFile; - std::string QrcName; - std::string PathChecksum; - std::string RccFile; - bool Generated; - bool Unique; - std::vector<std::string> Options; - std::vector<std::string> Resources; -}; - -/** \class cmQtAutoGenDigest - * \brief Filtered set of QtAutogen variables for a specific target - */ -class cmQtAutoGenDigest -{ -public: - cmQtAutoGenDigest(cmGeneratorTarget* target) - : Target(target) - , MocEnabled(false) - , UicEnabled(false) - , RccEnabled(false) - { - } - -public: - cmGeneratorTarget* Target; - std::string QtVersionMajor; - std::string QtVersionMinor; - bool MocEnabled; - bool UicEnabled; - bool RccEnabled; - std::vector<std::string> Headers; - std::vector<std::string> Sources; - std::vector<cmQtAutoGenDigestQrc> Qrcs; -}; - -// Utility types -typedef std::unique_ptr<cmQtAutoGenDigest> cmQtAutoGenDigestUP; -typedef std::vector<cmQtAutoGenDigestUP> cmQtAutoGenDigestUPV; - -#endif diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx new file mode 100644 index 0000000..52193af --- /dev/null +++ b/Source/cmQtAutoGenerator.cxx @@ -0,0 +1,320 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmQtAutoGen.h" +#include "cmQtAutoGenerator.h" + +#include "cmsys/FStream.hxx" +#include "cmsys/Terminal.h" + +#include "cmAlgorithms.h" +#include "cmGlobalGenerator.h" +#include "cmMakefile.h" +#include "cmStateDirectory.h" +#include "cmStateSnapshot.h" +#include "cmSystemTools.h" +#include "cmake.h" + +// -- Static functions + +static std::string HeadLine(std::string const& title) +{ + std::string head = title; + head += '\n'; + head.append(head.size() - 1, '-'); + head += '\n'; + return head; +} + +static std::string QuotedCommand(std::vector<std::string> const& command) +{ + std::string res; + for (std::string const& item : command) { + if (!res.empty()) { + res.push_back(' '); + } + std::string const cesc = cmQtAutoGen::Quoted(item); + if (item.empty() || (cesc.size() > (item.size() + 2)) || + (cesc.find(' ') != std::string::npos)) { + res += cesc; + } else { + res += item; + } + } + return res; +} + +// -- Class methods + +cmQtAutoGenerator::cmQtAutoGenerator() + : Verbose(cmSystemTools::HasEnv("VERBOSE")) + , ColorOutput(true) +{ + { + std::string colorEnv; + cmSystemTools::GetEnv("COLOR", colorEnv); + if (!colorEnv.empty()) { + this->ColorOutput = cmSystemTools::IsOn(colorEnv.c_str()); + } + } +} + +bool cmQtAutoGenerator::Run(std::string const& infoFile, + std::string const& config) +{ + // Info settings + this->InfoFile = infoFile; + cmSystemTools::ConvertToUnixSlashes(this->InfoFile); + this->InfoDir = cmSystemTools::GetFilenamePath(infoFile); + this->InfoConfig = config; + + cmake cm(cmake::RoleScript); + cm.SetHomeOutputDirectory(this->InfoDir); + cm.SetHomeDirectory(this->InfoDir); + cm.GetCurrentSnapshot().SetDefaultDefinitions(); + cmGlobalGenerator gg(&cm); + + cmStateSnapshot snapshot = cm.GetCurrentSnapshot(); + snapshot.GetDirectory().SetCurrentBinary(this->InfoDir); + snapshot.GetDirectory().SetCurrentSource(this->InfoDir); + + auto makefile = cm::make_unique<cmMakefile>(&gg, snapshot); + gg.SetCurrentMakefile(makefile.get()); + + return this->Process(makefile.get()); +} + +void cmQtAutoGenerator::LogBold(std::string const& message) const +{ + cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue | + cmsysTerminal_Color_ForegroundBold, + message.c_str(), true, this->ColorOutput); +} + +void cmQtAutoGenerator::LogInfo(cmQtAutoGen::Generator genType, + std::string const& message) const +{ + std::string msg = cmQtAutoGen::GeneratorName(genType); + msg += ": "; + msg += message; + if (msg.back() != '\n') { + msg.push_back('\n'); + } + cmSystemTools::Stdout(msg.c_str(), msg.size()); +} + +void cmQtAutoGenerator::LogWarning(cmQtAutoGen::Generator genType, + std::string const& message) const +{ + std::string msg = cmQtAutoGen::GeneratorName(genType); + msg += " warning:"; + if (message.find('\n') == std::string::npos) { + // Single line message + msg.push_back(' '); + } else { + // Multi line message + msg.push_back('\n'); + } + // Message + msg += message; + if (msg.back() != '\n') { + msg.push_back('\n'); + } + msg.push_back('\n'); + cmSystemTools::Stdout(msg.c_str(), msg.size()); +} + +void cmQtAutoGenerator::LogFileWarning(cmQtAutoGen::Generator genType, + std::string const& filename, + std::string const& message) const +{ + std::string msg = " "; + msg += cmQtAutoGen::Quoted(filename); + msg.push_back('\n'); + // Message + msg += message; + this->LogWarning(genType, msg); +} + +void cmQtAutoGenerator::LogError(cmQtAutoGen::Generator genType, + std::string const& message) const +{ + std::string msg; + msg.push_back('\n'); + msg += HeadLine(cmQtAutoGen::GeneratorName(genType) + " error"); + // Message + msg += message; + if (msg.back() != '\n') { + msg.push_back('\n'); + } + msg.push_back('\n'); + cmSystemTools::Stderr(msg.c_str(), msg.size()); +} + +void cmQtAutoGenerator::LogFileError(cmQtAutoGen::Generator genType, + std::string const& filename, + std::string const& message) const +{ + std::string emsg = " "; + emsg += cmQtAutoGen::Quoted(filename); + emsg += '\n'; + // Message + emsg += message; + this->LogError(genType, emsg); +} + +void cmQtAutoGenerator::LogCommandError( + cmQtAutoGen::Generator genType, std::string const& message, + std::vector<std::string> const& command, std::string const& output) const +{ + std::string msg; + msg.push_back('\n'); + msg += HeadLine(cmQtAutoGen::GeneratorName(genType) + " subprocess error"); + msg += message; + if (msg.back() != '\n') { + msg.push_back('\n'); + } + msg.push_back('\n'); + msg += HeadLine("Command"); + msg += QuotedCommand(command); + if (msg.back() != '\n') { + msg.push_back('\n'); + } + msg.push_back('\n'); + msg += HeadLine("Output"); + msg += output; + if (msg.back() != '\n') { + msg.push_back('\n'); + } + msg.push_back('\n'); + cmSystemTools::Stderr(msg.c_str(), msg.size()); +} + +/** + * @brief Generates the parent directory of the given file on demand + * @return True on success + */ +bool cmQtAutoGenerator::MakeParentDirectory(cmQtAutoGen::Generator genType, + std::string const& filename) const +{ + bool success = true; + std::string const dirName = cmSystemTools::GetFilenamePath(filename); + if (!dirName.empty()) { + if (!cmSystemTools::MakeDirectory(dirName)) { + this->LogFileError(genType, filename, + "Could not create parent directory"); + success = false; + } + } + return success; +} + +/** + * @brief Tests if buildFile is older than sourceFile + * @return True if buildFile is older than sourceFile. + * False may indicate an error. + */ +bool cmQtAutoGenerator::FileIsOlderThan(std::string const& buildFile, + std::string const& sourceFile, + std::string* error) +{ + int result = 0; + if (cmSystemTools::FileTimeCompare(buildFile, sourceFile, &result)) { + return (result < 0); + } + if (error != nullptr) { + error->append( + "File modification time comparison failed for the files\n "); + error->append(cmQtAutoGen::Quoted(buildFile)); + error->append("\nand\n "); + error->append(cmQtAutoGen::Quoted(sourceFile)); + } + return false; +} + +bool cmQtAutoGenerator::FileRead(std::string& content, + std::string const& filename, + std::string* error) +{ + bool success = false; + if (cmSystemTools::FileExists(filename)) { + std::size_t const length = cmSystemTools::FileLength(filename); + cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary)); + if (ifs) { + content.resize(length); + ifs.read(&content.front(), content.size()); + if (ifs) { + success = true; + } else { + content.clear(); + if (error != nullptr) { + error->append("Reading from the file failed."); + } + } + } else if (error != nullptr) { + error->append("Opening the file for reading failed."); + } + } else if (error != nullptr) { + error->append("The file does not exist."); + } + return success; +} + +bool cmQtAutoGenerator::FileWrite(cmQtAutoGen::Generator genType, + std::string const& filename, + std::string const& content) +{ + std::string error; + // Make sure the parent directory exists + if (this->MakeParentDirectory(genType, filename)) { + cmsys::ofstream outfile; + outfile.open(filename.c_str(), + (std::ios::out | std::ios::binary | std::ios::trunc)); + if (outfile) { + outfile << content; + // Check for write errors + if (!outfile.good()) { + error = "File writing failed"; + } + } else { + error = "Opening file for writing failed"; + } + } + if (!error.empty()) { + this->LogFileError(genType, filename, error); + return false; + } + return true; +} + +bool cmQtAutoGenerator::FileDiffers(std::string const& filename, + std::string const& content) +{ + bool differs = true; + { + std::string oldContents; + if (this->FileRead(oldContents, filename)) { + differs = (oldContents != content); + } + } + return differs; +} + +/** + * @brief Runs a command and returns true on success + * @return True on success + */ +bool cmQtAutoGenerator::RunCommand(std::vector<std::string> const& command, + std::string& output) const +{ + // Log command + if (this->Verbose) { + std::string qcmd = QuotedCommand(command); + qcmd.push_back('\n'); + cmSystemTools::Stdout(qcmd.c_str(), qcmd.size()); + } + // Execute command + int retVal = 0; + bool res = cmSystemTools::RunSingleCommand( + command, &output, &output, &retVal, nullptr, cmSystemTools::OUTPUT_NONE); + return (res && (retVal == 0)); +} diff --git a/Source/cmQtAutoGenerator.h b/Source/cmQtAutoGenerator.h new file mode 100644 index 0000000..285340d --- /dev/null +++ b/Source/cmQtAutoGenerator.h @@ -0,0 +1,76 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmQtAutoGenerator_h +#define cmQtAutoGenerator_h + +#include "cmConfigure.h" // IWYU pragma: keep + +#include "cmQtAutoGen.h" + +#include <string> +#include <vector> + +class cmMakefile; + +class cmQtAutoGenerator +{ + CM_DISABLE_COPY(cmQtAutoGenerator) +public: + cmQtAutoGenerator(); + virtual ~cmQtAutoGenerator() = default; + bool Run(std::string const& infoFile, std::string const& config); + + std::string const& GetInfoFile() const { return InfoFile; } + std::string const& GetInfoDir() const { return InfoDir; } + std::string const& GetInfoConfig() const { return InfoConfig; } + bool GetVerbose() const { return Verbose; } + +protected: + // -- Central processing + virtual bool Process(cmMakefile* makefile) = 0; + + // -- Log info + void LogBold(std::string const& message) const; + void LogInfo(cmQtAutoGen::Generator genType, + std::string const& message) const; + // -- Log warning + void LogWarning(cmQtAutoGen::Generator genType, + std::string const& message) const; + void LogFileWarning(cmQtAutoGen::Generator genType, + std::string const& filename, + std::string const& message) const; + // -- Log error + void LogError(cmQtAutoGen::Generator genType, + std::string const& message) const; + void LogFileError(cmQtAutoGen::Generator genType, + std::string const& filename, + std::string const& message) const; + void LogCommandError(cmQtAutoGen::Generator genType, + std::string const& message, + std::vector<std::string> const& command, + std::string const& output) const; + // -- Utility + bool MakeParentDirectory(cmQtAutoGen::Generator genType, + std::string const& filename) const; + bool FileIsOlderThan(std::string const& buildFile, + std::string const& sourceFile, + std::string* error = nullptr); + bool FileRead(std::string& content, std::string const& filename, + std::string* error = nullptr); + bool FileWrite(cmQtAutoGen::Generator genType, std::string const& filename, + std::string const& content); + bool FileDiffers(std::string const& filename, std::string const& content); + bool RunCommand(std::vector<std::string> const& command, + std::string& output) const; + +private: + // -- Info settings + std::string InfoFile; + std::string InfoDir; + std::string InfoConfig; + // -- Settings + bool Verbose; + bool ColorOutput; +}; + +#endif diff --git a/Source/cmQtAutoGeneratorInitializer.cxx b/Source/cmQtAutoGeneratorInitializer.cxx index c7550e6..bd692a2 100644 --- a/Source/cmQtAutoGeneratorInitializer.cxx +++ b/Source/cmQtAutoGeneratorInitializer.cxx @@ -14,6 +14,7 @@ #include "cmMakefile.h" #include "cmOutputConverter.h" #include "cmPolicies.h" +#include "cmProcessOutput.h" #include "cmSourceFile.h" #include "cmSourceGroup.h" #include "cmState.h" @@ -51,118 +52,6 @@ inline static std::string GetSafeProperty(cmSourceFile const* sf, return std::string(SafeString(sf->GetProperty(key))); } -static cmQtAutoGen::MultiConfig AutogenMultiConfig( - cmGlobalGenerator* globalGen) -{ - if (!globalGen->IsMultiConfig()) { - return cmQtAutoGen::SINGLE; - } - - // FIXME: Xcode does not support per-config sources, yet. - // (EXCLUDED_SOURCE_FILE_NAMES) - // if (globalGen->GetName().find("Xcode") != std::string::npos) { - // return cmQtAutoGen::FULL; - //} - - // FIXME: Visual Studio does not support per-config sources, yet. - // (EXCLUDED_SOURCE_FILE_NAMES) - // if (globalGen->GetName().find("Visual Studio") != std::string::npos) { - // return cmQtAutoGen::FULL; - //} - - return cmQtAutoGen::WRAP; -} - -static std::string GetAutogenTargetName(cmGeneratorTarget const* target) -{ - std::string autogenTargetName = target->GetName(); - autogenTargetName += "_autogen"; - return autogenTargetName; -} - -static std::string GetAutogenTargetFilesDir(cmGeneratorTarget const* target) -{ - cmMakefile* makefile = target->Target->GetMakefile(); - std::string targetDir = makefile->GetCurrentBinaryDirectory(); - targetDir += makefile->GetCMakeInstance()->GetCMakeFilesDirectory(); - targetDir += "/"; - targetDir += GetAutogenTargetName(target); - targetDir += ".dir"; - return targetDir; -} - -static std::string GetAutogenTargetBuildDir(cmGeneratorTarget const* target) -{ - std::string targetDir = GetSafeProperty(target, "AUTOGEN_BUILD_DIR"); - if (targetDir.empty()) { - cmMakefile* makefile = target->Target->GetMakefile(); - targetDir = makefile->GetCurrentBinaryDirectory(); - targetDir += "/"; - targetDir += GetAutogenTargetName(target); - } - return targetDir; -} - -std::string cmQtAutoGeneratorInitializer::GetQtMajorVersion( - cmGeneratorTarget const* target) -{ - cmMakefile* makefile = target->Target->GetMakefile(); - std::string qtMajor = makefile->GetSafeDefinition("QT_VERSION_MAJOR"); - if (qtMajor.empty()) { - qtMajor = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR"); - } - const char* targetQtVersion = - target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", ""); - if (targetQtVersion != nullptr) { - qtMajor = targetQtVersion; - } - return qtMajor; -} - -std::string cmQtAutoGeneratorInitializer::GetQtMinorVersion( - cmGeneratorTarget const* target, std::string const& qtVersionMajor) -{ - cmMakefile* makefile = target->Target->GetMakefile(); - std::string qtMinor; - if (qtVersionMajor == "5") { - qtMinor = makefile->GetSafeDefinition("Qt5Core_VERSION_MINOR"); - } - if (qtMinor.empty()) { - qtMinor = makefile->GetSafeDefinition("QT_VERSION_MINOR"); - } - - const char* targetQtVersion = - target->GetLinkInterfaceDependentStringProperty("QT_MINOR_VERSION", ""); - if (targetQtVersion != nullptr) { - qtMinor = targetQtVersion; - } - return qtMinor; -} - -static bool QtVersionGreaterOrEqual(std::string const& major, - std::string const& minor, - unsigned long requestMajor, - unsigned long requestMinor) -{ - unsigned long majorUL(0); - unsigned long minorUL(0); - if (cmSystemTools::StringToULong(major.c_str(), &majorUL) && - cmSystemTools::StringToULong(minor.c_str(), &minorUL)) { - return (majorUL > requestMajor) || - (majorUL == requestMajor && minorUL >= requestMinor); - } - return false; -} - -static void GetConfigs(cmMakefile* makefile, std::string& configDefault, - std::vector<std::string>& configsList) -{ - configDefault = makefile->GetConfigurations(configsList); - if (configsList.empty()) { - configsList.push_back(configDefault); - } -} - static void AddDefinitionEscaped(cmMakefile* makefile, const char* key, std::string const& value) { @@ -258,48 +147,24 @@ static void AddCleanFile(cmMakefile* makefile, std::string const& fileName) false); } -static std::vector<std::string> AddGeneratedSource( - cmGeneratorTarget* target, std::string const& filename, - cmQtAutoGen::MultiConfig multiConfig, - const std::vector<std::string>& configsList, cmQtAutoGen::Generator genType) +static std::string FileProjectRelativePath(cmMakefile* makefile, + std::string const& fileName) { - std::vector<std::string> genFiles; - // Register source file in makefile and source group - if (multiConfig != cmQtAutoGen::FULL) { - genFiles.push_back(filename); - } else { - for (std::string const& cfg : configsList) { - genFiles.push_back( - cmQtAutoGen::AppendFilenameSuffix(filename, "_" + cfg)); - } - } + std::string res; { - cmMakefile* makefile = target->Target->GetMakefile(); - for (std::string const& genFile : genFiles) { - { - cmSourceFile* gFile = makefile->GetOrCreateSource(genFile, true); - gFile->SetProperty("GENERATED", "1"); - gFile->SetProperty("SKIP_AUTOGEN", "On"); - } - AddToSourceGroup(makefile, genFile, genType); - } - } - - // Add source file to target - if (multiConfig != cmQtAutoGen::FULL) { - target->AddSource(filename); - } else { - for (std::string const& cfg : configsList) { - std::string src = "$<$<CONFIG:"; - src += cfg; - src += ">:"; - src += cmQtAutoGen::AppendFilenameSuffix(filename, "_" + cfg); - src += ">"; - target->AddSource(src); + std::string pSource = cmSystemTools::RelativePath( + makefile->GetCurrentSourceDirectory(), fileName.c_str()); + std::string pBinary = cmSystemTools::RelativePath( + makefile->GetCurrentBinaryDirectory(), fileName.c_str()); + if (pSource.size() < pBinary.size()) { + res = std::move(pSource); + } else if (pBinary.size() < fileName.size()) { + res = std::move(pBinary); + } else { + res = fileName; } } - - return genFiles; + return res; } /* @brief Tests if targetDepend is a STATIC_LIBRARY and if any of its @@ -346,350 +211,123 @@ static bool StaticLibraryCycle(cmGeneratorTarget const* targetOrigin, return cycle; } -struct cmQtAutoGenSetup -{ - std::set<std::string> MocSkip; - std::set<std::string> UicSkip; - - std::map<std::string, std::string> ConfigMocIncludes; - std::map<std::string, std::string> ConfigMocDefines; - std::map<std::string, std::string> ConfigUicOptions; -}; - -static void SetupAcquireSkipFiles(cmQtAutoGenDigest const& digest, - cmQtAutoGenSetup& setup) +cmQtAutoGeneratorInitializer::cmQtAutoGeneratorInitializer( + cmGeneratorTarget* target, bool mocEnabled, bool uicEnabled, bool rccEnabled, + std::string const& qtVersionMajor) + : Target(target) + , MocEnabled(mocEnabled) + , UicEnabled(uicEnabled) + , RccEnabled(rccEnabled) + , QtVersionMajor(qtVersionMajor) + , MultiConfig(cmQtAutoGen::WRAP) { - // Read skip files from makefile sources - { - const std::vector<cmSourceFile*>& allSources = - digest.Target->Makefile->GetSourceFiles(); - for (cmSourceFile* sf : allSources) { - // sf->GetExtension() is only valid after sf->GetFullPath() ... - std::string const& fPath = sf->GetFullPath(); - cmSystemTools::FileFormat const fileType = - cmSystemTools::GetFileFormat(sf->GetExtension().c_str()); - if (!(fileType == cmSystemTools::CXX_FILE_FORMAT) && - !(fileType == cmSystemTools::HEADER_FILE_FORMAT)) { - continue; - } - const bool skipAll = sf->GetPropertyAsBool("SKIP_AUTOGEN"); - const bool mocSkip = digest.MocEnabled && - (skipAll || sf->GetPropertyAsBool("SKIP_AUTOMOC")); - const bool uicSkip = digest.UicEnabled && - (skipAll || sf->GetPropertyAsBool("SKIP_AUTOUIC")); - if (mocSkip || uicSkip) { - std::string const absFile = cmSystemTools::GetRealPath(fPath); - if (mocSkip) { - setup.MocSkip.insert(absFile); - } - if (uicSkip) { - setup.UicSkip.insert(absFile); - } - } - } - } + this->QtVersionMinor = cmQtAutoGeneratorInitializer::GetQtMinorVersion( + target, this->QtVersionMajor); } -static void SetupAutoTargetMoc(cmQtAutoGenDigest const& digest, - std::string const& configDefault, - std::vector<std::string> const& configsList, - cmQtAutoGenSetup& setup) +void cmQtAutoGeneratorInitializer::InitCustomTargets() { - cmGeneratorTarget const* target = digest.Target; - cmLocalGenerator* localGen = target->GetLocalGenerator(); - cmMakefile* makefile = target->Target->GetMakefile(); - - AddDefinitionEscaped(makefile, "_moc_skip", setup.MocSkip); - AddDefinitionEscaped(makefile, "_moc_options", - GetSafeProperty(target, "AUTOMOC_MOC_OPTIONS")); - AddDefinitionEscaped(makefile, "_moc_relaxed_mode", - makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE") ? "TRUE" - : "FALSE"); - AddDefinitionEscaped(makefile, "_moc_macro_names", - GetSafeProperty(target, "AUTOMOC_MACRO_NAMES")); - AddDefinitionEscaped(makefile, "_moc_depend_filters", - GetSafeProperty(target, "AUTOMOC_DEPEND_FILTERS")); - - // Compiler predefines - if (target->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES")) { - if (QtVersionGreaterOrEqual(digest.QtVersionMajor, digest.QtVersionMinor, - 5, 8)) { - AddDefinitionEscaped( - makefile, "_moc_predefs_cmd", - makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND")); - } - } - // Moc includes and compile definitions - { - auto GetIncludeDirs = [target, - localGen](std::string const& cfg) -> std::string { - // Get the include dirs for this target, without stripping the implicit - // include dirs off, see - // https://gitlab.kitware.com/cmake/cmake/issues/13667 - std::vector<std::string> includeDirs; - localGen->GetIncludeDirectories(includeDirs, target, "CXX", cfg, false); - return cmJoin(includeDirs, ";"); - }; - auto GetCompileDefinitions = - [target, localGen](std::string const& cfg) -> std::string { - std::set<std::string> defines; - localGen->AddCompileDefinitions(defines, target, cfg, "CXX"); - return cmJoin(defines, ";"); - }; + cmMakefile* makefile = this->Target->Target->GetMakefile(); + cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); + cmGlobalGenerator* globalGen = localGen->GetGlobalGenerator(); - // Default configuration settings - std::string const includeDirs = GetIncludeDirs(configDefault); - std::string const compileDefs = GetCompileDefinitions(configDefault); - // Other configuration settings - for (std::string const& cfg : configsList) { - { - std::string const configIncludeDirs = GetIncludeDirs(cfg); - if (configIncludeDirs != includeDirs) { - setup.ConfigMocIncludes[cfg] = configIncludeDirs; - } - } - { - std::string const configCompileDefs = GetCompileDefinitions(cfg); - if (configCompileDefs != compileDefs) { - setup.ConfigMocDefines[cfg] = configCompileDefs; - } - } - } - AddDefinitionEscaped(makefile, "_moc_include_dirs", includeDirs); - AddDefinitionEscaped(makefile, "_moc_compile_defs", compileDefs); + // Configurations + this->ConfigDefault = makefile->GetConfigurations(this->ConfigsList); + if (this->ConfigsList.empty()) { + this->ConfigsList.push_back(this->ConfigDefault); } - // Moc executable + // Multi configuration { - std::string mocExec; - std::string err; - - if (digest.QtVersionMajor == "5") { - cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::moc"); - if (tgt != nullptr) { - mocExec = SafeString(tgt->ImportedGetLocation("")); - } else { - err = "AUTOMOC: Qt5::moc target not found"; - } - } else if (digest.QtVersionMajor == "4") { - cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::moc"); - if (tgt != nullptr) { - mocExec = SafeString(tgt->ImportedGetLocation("")); - } else { - err = "AUTOMOC: Qt4::moc target not found"; - } - } else { - err = "The AUTOMOC feature supports only Qt 4 and Qt 5"; + if (!globalGen->IsMultiConfig()) { + this->MultiConfig = cmQtAutoGen::SINGLE; } - if (err.empty()) { - AddDefinitionEscaped(makefile, "_qt_moc_executable", mocExec); - } else { - err += " (" + target->GetName() + ")"; - cmSystemTools::Error(err.c_str()); - } + // FIXME: Xcode does not support per-config sources, yet. + // (EXCLUDED_SOURCE_FILE_NAMES) + // if (globalGen->GetName().find("Xcode") != std::string::npos) { + // return cmQtAutoGen::FULL; + //} + + // FIXME: Visual Studio does not support per-config sources, yet. + // (EXCLUDED_SOURCE_FILE_NAMES) + // if (globalGen->GetName().find("Visual Studio") != std::string::npos) { + // return cmQtAutoGen::FULL; + //} } -} -static void SetupAutoTargetUic(cmQtAutoGenDigest const& digest, - std::string const& config, - std::vector<std::string> const& configs, - cmQtAutoGenSetup& setup) -{ - cmGeneratorTarget const* target = digest.Target; - cmMakefile* makefile = target->Target->GetMakefile(); + // Autogen target name + this->AutogenTargetName = this->Target->GetName(); + this->AutogenTargetName += "_autogen"; - // Uic search paths + // Autogen directories { - std::vector<std::string> uicSearchPaths; - { - std::string const usp = GetSafeProperty(target, "AUTOUIC_SEARCH_PATHS"); - if (!usp.empty()) { - cmSystemTools::ExpandListArgument(usp, uicSearchPaths); - std::string const srcDir = makefile->GetCurrentSourceDirectory(); - for (std::string& path : uicSearchPaths) { - path = cmSystemTools::CollapseFullPath(path, srcDir); - } - } + // Collapsed current binary directory + std::string const cbd = cmSystemTools::CollapseFullPath( + "", makefile->GetCurrentBinaryDirectory()); + + // Autogen info dir + this->DirInfo = cbd; + this->DirInfo += makefile->GetCMakeInstance()->GetCMakeFilesDirectory(); + this->DirInfo += "/"; + this->DirInfo += this->AutogenTargetName; + this->DirInfo += ".dir"; + cmSystemTools::ConvertToUnixSlashes(this->DirInfo); + + // Autogen build dir + this->DirBuild = GetSafeProperty(this->Target, "AUTOGEN_BUILD_DIR"); + if (this->DirBuild.empty()) { + this->DirBuild = cbd; + this->DirBuild += "/"; + this->DirBuild += this->AutogenTargetName; } - AddDefinitionEscaped(makefile, "_uic_search_paths", uicSearchPaths); - } - // Uic target options - { - auto UicGetOpts = [target](std::string const& cfg) -> std::string { - std::vector<std::string> opts; - target->GetAutoUicOptions(opts, cfg); - return cmJoin(opts, ";"); - }; + cmSystemTools::ConvertToUnixSlashes(this->DirBuild); - // Default settings - std::string const uicOpts = UicGetOpts(config); - AddDefinitionEscaped(makefile, "_uic_target_options", uicOpts); - - // Configuration specific settings - for (std::string const& cfg : configs) { - std::string const configUicOpts = UicGetOpts(cfg); - if (configUicOpts != uicOpts) { - setup.ConfigUicOptions[cfg] = configUicOpts; - } - } - } - // .ui files skip and options - { - std::vector<std::string> uiFileFiles; - std::vector<std::vector<std::string>> uiFileOptions; - { - std::string const uiExt = "ui"; - for (cmSourceFile* sf : makefile->GetSourceFiles()) { - // sf->GetExtension() is only valid after sf->GetFullPath() ... - std::string const& fPath = sf->GetFullPath(); - if (sf->GetExtension() == uiExt) { - std::string const absFile = cmSystemTools::GetRealPath(fPath); - // Check if the file should be skipped - if (sf->GetPropertyAsBool("SKIP_AUTOUIC") || - sf->GetPropertyAsBool("SKIP_AUTOGEN")) { - setup.UicSkip.insert(absFile); - } - // Check if the files has uic options - std::string const uicOpts = GetSafeProperty(sf, "AUTOUIC_OPTIONS"); - if (!uicOpts.empty()) { - // Check if file isn't skipped - if (setup.UicSkip.count(absFile) == 0) { - uiFileFiles.push_back(absFile); - std::vector<std::string> optsVec; - cmSystemTools::ExpandListArgument(uicOpts, optsVec); - uiFileOptions.push_back(std::move(optsVec)); - } - } - } - } - } - AddDefinitionEscaped(makefile, "_qt_uic_options_files", uiFileFiles); - AddDefinitionEscaped(makefile, "_qt_uic_options_options", uiFileOptions); + // Working directory + this->DirWork = cbd; + cmSystemTools::ConvertToUnixSlashes(this->DirWork); } - AddDefinitionEscaped(makefile, "_uic_skip", setup.UicSkip); - - // Uic executable + // Autogen files { - std::string err; - std::string uicExec; + this->AutogenInfoFile = this->DirInfo; + this->AutogenInfoFile += "/AutogenInfo.cmake"; - cmLocalGenerator* localGen = target->GetLocalGenerator(); - if (digest.QtVersionMajor == "5") { - cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::uic"); - if (tgt != nullptr) { - uicExec = SafeString(tgt->ImportedGetLocation("")); - } else { - // Project does not use Qt5Widgets, but has AUTOUIC ON anyway - } - } else if (digest.QtVersionMajor == "4") { - cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::uic"); - if (tgt != nullptr) { - uicExec = SafeString(tgt->ImportedGetLocation("")); - } else { - err = "AUTOUIC: Qt4::uic target not found"; - } - } else { - err = "The AUTOUIC feature supports only Qt 4 and Qt 5"; - } - - if (err.empty()) { - AddDefinitionEscaped(makefile, "_qt_uic_executable", uicExec); - } else { - err += " (" + target->GetName() + ")"; - cmSystemTools::Error(err.c_str()); - } + this->AutogenSettingsFile = this->DirInfo; + this->AutogenSettingsFile += "/AutogenOldSettings.cmake"; } -} -static std::string RccGetExecutable(cmGeneratorTarget const* target, - std::string const& qtMajorVersion) -{ - std::string rccExec; - std::string err; - - cmLocalGenerator* localGen = target->GetLocalGenerator(); - if (qtMajorVersion == "5") { - cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::rcc"); - if (tgt != nullptr) { - rccExec = SafeString(tgt->ImportedGetLocation("")); - } else { - err = "AUTORCC: Qt5::rcc target not found"; + // Autogen target FOLDER property + { + const char* folder = + makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER"); + if (folder == nullptr) { + folder = + makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER"); } - } else if (qtMajorVersion == "4") { - cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::rcc"); - if (tgt != nullptr) { - rccExec = SafeString(tgt->ImportedGetLocation("")); - } else { - err = "AUTORCC: Qt4::rcc target not found"; + // Inherit FOLDER property from target (#13688) + if (folder == nullptr) { + folder = SafeString(this->Target->Target->GetProperty("FOLDER")); + } + if (folder != nullptr) { + this->AutogenFolder = folder; } - } else { - err = "The AUTORCC feature supports only Qt 4 and Qt 5"; - } - - if (!err.empty()) { - err += " (" + target->GetName() + ")"; - cmSystemTools::Error(err.c_str()); - } - return rccExec; -} - -static void SetupAutoTargetRcc(cmQtAutoGenDigest const& digest) -{ - std::vector<std::string> rccFiles; - std::vector<std::string> rccBuilds; - std::vector<std::vector<std::string>> rccOptions; - std::vector<std::vector<std::string>> rccInputs; - - for (cmQtAutoGenDigestQrc const& qrcDigest : digest.Qrcs) { - rccFiles.push_back(qrcDigest.QrcFile); - rccBuilds.push_back(qrcDigest.RccFile); - rccOptions.push_back(qrcDigest.Options); - rccInputs.push_back(qrcDigest.Resources); } - cmMakefile* makefile = digest.Target->Target->GetMakefile(); - AddDefinitionEscaped(makefile, "_qt_rcc_executable", - RccGetExecutable(digest.Target, digest.QtVersionMajor)); - AddDefinitionEscaped(makefile, "_rcc_files", rccFiles); - AddDefinitionEscaped(makefile, "_rcc_builds", rccBuilds); - AddDefinitionEscaped(makefile, "_rcc_options", rccOptions); - AddDefinitionEscaped(makefile, "_rcc_inputs", rccInputs); -} - -void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( - cmQtAutoGenDigest& digest) -{ - cmGeneratorTarget* target = digest.Target; - cmMakefile* makefile = target->Target->GetMakefile(); - cmLocalGenerator* localGen = target->GetLocalGenerator(); - cmGlobalGenerator* globalGen = localGen->GetGlobalGenerator(); - - std::string const autogenTargetName = GetAutogenTargetName(target); - std::string const autogenInfoDir = GetAutogenTargetFilesDir(target); - std::string const autogenBuildDir = GetAutogenTargetBuildDir(target); - std::string const workingDirectory = - cmSystemTools::CollapseFullPath("", makefile->GetCurrentBinaryDirectory()); - - cmQtAutoGen::MultiConfig const multiConfig = AutogenMultiConfig(globalGen); - std::string configDefault; - std::vector<std::string> configsList; - GetConfigs(makefile, configDefault, configsList); - std::set<std::string> autogenDependFiles; std::set<cmTarget*> autogenDependTargets; std::vector<std::string> autogenProvides; // Remove build directories on cleanup - AddCleanFile(makefile, autogenBuildDir); + AddCleanFile(makefile, this->DirBuild); // Remove old settings on cleanup { - std::string base = autogenInfoDir + "/AutogenOldSettings"; - if (multiConfig == cmQtAutoGen::SINGLE) { + std::string base = this->DirInfo; + base += "/AutogenOldSettings"; + if (this->MultiConfig == cmQtAutoGen::SINGLE) { AddCleanFile(makefile, base.append(".cmake")); } else { - for (std::string const& cfg : configsList) { + for (std::string const& cfg : this->ConfigsList) { std::string filename = base; filename += "_"; filename += cfg; @@ -699,62 +337,72 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( } } - // Compose command lines - cmCustomCommandLines commandLines; - { - cmCustomCommandLine currentLine; - currentLine.push_back(cmSystemTools::GetCMakeCommand()); - currentLine.push_back("-E"); - currentLine.push_back("cmake_autogen"); - currentLine.push_back(autogenInfoDir); - currentLine.push_back("$<CONFIGURATION>"); - commandLines.push_back(currentLine); - } - - // Compose target comment - std::string autogenComment; - { - std::vector<std::string> toolNames; - if (digest.MocEnabled) { - toolNames.emplace_back("MOC"); - } - if (digest.UicEnabled) { - toolNames.emplace_back("UIC"); - } - if (digest.RccEnabled) { - toolNames.emplace_back("RCC"); - } - - std::string tools = toolNames.front(); - toolNames.erase(toolNames.begin()); - if (!toolNames.empty()) { - while (toolNames.size() > 1) { - tools += ", "; - tools += toolNames.front(); - toolNames.erase(toolNames.begin()); - } - tools += " and " + toolNames.front(); - } - autogenComment = "Automatic " + tools + " for target " + target->GetName(); - } - // Add moc compilation to generated files list - if (digest.MocEnabled) { - std::string const mocsComp = autogenBuildDir + "/mocs_compilation.cpp"; - auto files = AddGeneratedSource(target, mocsComp, multiConfig, configsList, - cmQtAutoGen::MOC); + if (this->MocEnabled) { + std::string const mocsComp = this->DirBuild + "/mocs_compilation.cpp"; + auto files = this->AddGeneratedSource(mocsComp, cmQtAutoGen::MOC); for (std::string& file : files) { autogenProvides.push_back(std::move(file)); } } // Add autogen includes directory to the origin target INCLUDE_DIRECTORIES - if (digest.MocEnabled || digest.UicEnabled) { - std::string includeDir = autogenBuildDir + "/include"; - if (multiConfig != cmQtAutoGen::SINGLE) { + if (this->MocEnabled || this->UicEnabled) { + std::string includeDir = this->DirBuild + "/include"; + if (this->MultiConfig != cmQtAutoGen::SINGLE) { includeDir += "_$<CONFIG>"; } - target->AddIncludeDirectory(includeDir, true); + this->Target->AddIncludeDirectory(includeDir, true); + } + + // Acquire rcc executable and features + if (this->RccEnabled) { + { + std::string err; + if (this->QtVersionMajor == "5") { + cmGeneratorTarget* tgt = + localGen->FindGeneratorTargetToUse("Qt5::rcc"); + if (tgt != nullptr) { + this->RccExecutable = SafeString(tgt->ImportedGetLocation("")); + } else { + err = "AUTORCC: Qt5::rcc target not found"; + } + } else if (QtVersionMajor == "4") { + cmGeneratorTarget* tgt = + localGen->FindGeneratorTargetToUse("Qt4::rcc"); + if (tgt != nullptr) { + this->RccExecutable = SafeString(tgt->ImportedGetLocation("")); + } else { + err = "AUTORCC: Qt4::rcc target not found"; + } + } else { + err = "The AUTORCC feature supports only Qt 4 and Qt 5"; + } + if (!err.empty()) { + err += " ("; + err += this->Target->GetName(); + err += ")"; + cmSystemTools::Error(err.c_str()); + } + } + // Detect if rcc supports (-)-list + if (!this->RccExecutable.empty() && (this->QtVersionMajor == "5")) { + std::vector<std::string> command; + command.push_back(this->RccExecutable); + command.push_back("--help"); + std::string rccStdOut; + std::string rccStdErr; + int retVal = 0; + bool result = cmSystemTools::RunSingleCommand( + command, &rccStdOut, &rccStdErr, &retVal, nullptr, + cmSystemTools::OUTPUT_NONE, 0.0, cmProcessOutput::Auto); + if (result && retVal == 0 && + rccStdOut.find("--list") != std::string::npos) { + this->RccListOptions.push_back("--list"); + } else { + this->RccListOptions.push_back("-list"); + } + } } // Extract relevant source files @@ -763,7 +411,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( { std::string const qrcExt = "qrc"; std::vector<cmSourceFile*> srcFiles; - target->GetConfigCommonSourceFiles(srcFiles); + this->Target->GetConfigCommonSourceFiles(srcFiles); for (cmSourceFile* sf : srcFiles) { if (sf->GetPropertyAsBool("SKIP_AUTOGEN")) { continue; @@ -772,50 +420,50 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( std::string const& fPath = sf->GetFullPath(); std::string const& ext = sf->GetExtension(); // Register generated files that will be scanned by moc or uic - if (digest.MocEnabled || digest.UicEnabled) { + if (this->MocEnabled || this->UicEnabled) { cmSystemTools::FileFormat const fileType = cmSystemTools::GetFileFormat(ext.c_str()); if ((fileType == cmSystemTools::CXX_FILE_FORMAT) || (fileType == cmSystemTools::HEADER_FILE_FORMAT)) { std::string const absPath = cmSystemTools::GetRealPath(fPath); - if ((digest.MocEnabled && !sf->GetPropertyAsBool("SKIP_AUTOMOC")) || - (digest.UicEnabled && !sf->GetPropertyAsBool("SKIP_AUTOUIC"))) { + if ((this->MocEnabled && !sf->GetPropertyAsBool("SKIP_AUTOMOC")) || + (this->UicEnabled && !sf->GetPropertyAsBool("SKIP_AUTOUIC"))) { // Register source const bool generated = sf->GetPropertyAsBool("GENERATED"); if (fileType == cmSystemTools::HEADER_FILE_FORMAT) { if (generated) { generatedHeaders.push_back(absPath); } else { - digest.Headers.push_back(absPath); + this->Headers.push_back(absPath); } } else { if (generated) { generatedSources.push_back(absPath); } else { - digest.Sources.push_back(absPath); + this->Sources.push_back(absPath); } } } } } // Register rcc enabled files - if (digest.RccEnabled && (ext == qrcExt) && + if (this->RccEnabled && (ext == qrcExt) && !sf->GetPropertyAsBool("SKIP_AUTORCC")) { // Register qrc file { - cmQtAutoGenDigestQrc qrcDigest; - qrcDigest.QrcFile = cmSystemTools::GetRealPath(fPath); - qrcDigest.QrcName = - cmSystemTools::GetFilenameWithoutLastExtension(qrcDigest.QrcFile); - qrcDigest.Generated = sf->GetPropertyAsBool("GENERATED"); + Qrc qrc; + qrc.QrcFile = cmSystemTools::GetRealPath(fPath); + qrc.QrcName = + cmSystemTools::GetFilenameWithoutLastExtension(qrc.QrcFile); + qrc.Generated = sf->GetPropertyAsBool("GENERATED"); // RCC options { std::string const opts = GetSafeProperty(sf, "AUTORCC_OPTIONS"); if (!opts.empty()) { - cmSystemTools::ExpandListArgument(opts, qrcDigest.Options); + cmSystemTools::ExpandListArgument(opts, qrc.Options); } } - digest.Qrcs.push_back(std::move(qrcDigest)); + this->Qrcs.push_back(std::move(qrc)); } } } @@ -823,7 +471,35 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( // sources meta data cache. Clear it so that OBJECT library targets that // are AUTOGEN initialized after this target get their added // mocs_compilation.cpp source acknowledged by this target. - target->ClearSourcesCache(); + this->Target->ClearSourcesCache(); + } + // Read skip files from makefile sources + if (this->MocEnabled || this->UicEnabled) { + const std::vector<cmSourceFile*>& allSources = makefile->GetSourceFiles(); + for (cmSourceFile* sf : allSources) { + // sf->GetExtension() is only valid after sf->GetFullPath() ... + std::string const& fPath = sf->GetFullPath(); + cmSystemTools::FileFormat const fileType = + cmSystemTools::GetFileFormat(sf->GetExtension().c_str()); + if (!(fileType == cmSystemTools::CXX_FILE_FORMAT) && + !(fileType == cmSystemTools::HEADER_FILE_FORMAT)) { + continue; + } + const bool skipAll = sf->GetPropertyAsBool("SKIP_AUTOGEN"); + const bool mocSkip = + this->MocEnabled && (skipAll || sf->GetPropertyAsBool("SKIP_AUTOMOC")); + const bool uicSkip = + this->UicEnabled && (skipAll || sf->GetPropertyAsBool("SKIP_AUTOUIC")); + if (mocSkip || uicSkip) { + std::string const absFile = cmSystemTools::GetRealPath(fPath); + if (mocSkip) { + this->MocSkip.insert(absFile); + } + if (uicSkip) { + this->UicSkip.insert(absFile); + } + } + } } // Process GENERATED sources and headers @@ -832,7 +508,7 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( bool policyAccept = false; bool policyWarn = false; cmPolicies::PolicyStatus const CMP0071_status = - target->Makefile->GetPolicyStatus(cmPolicies::CMP0071); + makefile->GetPolicyStatus(cmPolicies::CMP0071); switch (CMP0071_status) { case cmPolicies::WARN: policyWarn = true; @@ -851,11 +527,11 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( if (policyAccept) { // Accept GENERATED sources for (std::string const& absFile : generatedHeaders) { - digest.Headers.push_back(absFile); + this->Headers.push_back(absFile); autogenDependFiles.insert(absFile); } for (std::string const& absFile : generatedSources) { - digest.Sources.push_back(absFile); + this->Sources.push_back(absFile); autogenDependFiles.insert(absFile); } } else { @@ -865,13 +541,13 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( msg += "\n"; std::string tools; std::string property; - if (digest.MocEnabled && digest.UicEnabled) { + if (this->MocEnabled && this->UicEnabled) { tools = "AUTOMOC and AUTOUIC"; property = "SKIP_AUTOGEN"; - } else if (digest.MocEnabled) { + } else if (this->MocEnabled) { tools = "AUTOMOC"; property = "SKIP_AUTOMOC"; - } else if (digest.UicEnabled) { + } else if (this->UicEnabled) { tools = "AUTOUIC"; property = "SKIP_AUTOUIC"; } @@ -896,57 +572,74 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( makefile->IssueMessage(cmake::AUTHOR_WARNING, msg); } } + // Clear lists + generatedSources.clear(); + generatedHeaders.clear(); } // Sort headers and sources - std::sort(digest.Headers.begin(), digest.Headers.end()); - std::sort(digest.Sources.begin(), digest.Sources.end()); + if (this->MocEnabled || this->UicEnabled) { + std::sort(this->Headers.begin(), this->Headers.end()); + std::sort(this->Sources.begin(), this->Sources.end()); + } // Process qrc files - if (!digest.Qrcs.empty()) { - const bool QtV5 = (digest.QtVersionMajor == "5"); - std::string const rcc = RccGetExecutable(target, digest.QtVersionMajor); + if (!this->Qrcs.empty()) { + const bool QtV5 = (this->QtVersionMajor == "5"); // Target rcc options std::vector<std::string> optionsTarget; cmSystemTools::ExpandListArgument( - GetSafeProperty(target, "AUTORCC_OPTIONS"), optionsTarget); + GetSafeProperty(this->Target, "AUTORCC_OPTIONS"), optionsTarget); // Check if file name is unique - for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) { - qrcDigest.Unique = true; - for (cmQtAutoGenDigestQrc const& qrcDig2 : digest.Qrcs) { - if ((&qrcDigest != &qrcDig2) && - (qrcDigest.QrcName == qrcDig2.QrcName)) { - qrcDigest.Unique = false; + for (Qrc& qrc : this->Qrcs) { + qrc.Unique = true; + for (Qrc const& qrc2 : this->Qrcs) { + if ((&qrc != &qrc2) && (qrc.QrcName == qrc2.QrcName)) { + qrc.Unique = false; break; } } } - // Path checksum + // Path checksum and file names { cmFilePathChecksum const fpathCheckSum(makefile); - for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) { - qrcDigest.PathChecksum = fpathCheckSum.getPart(qrcDigest.QrcFile); + for (Qrc& qrc : this->Qrcs) { + qrc.PathChecksum = fpathCheckSum.getPart(qrc.QrcFile); // RCC output file name - std::string rccFile = autogenBuildDir + "/"; - rccFile += qrcDigest.PathChecksum; - rccFile += "/qrc_"; - rccFile += qrcDigest.QrcName; - rccFile += ".cpp"; - qrcDigest.RccFile = std::move(rccFile); + { + std::string rccFile = this->DirBuild + "/"; + rccFile += qrc.PathChecksum; + rccFile += "/qrc_"; + rccFile += qrc.QrcName; + rccFile += ".cpp"; + qrc.RccFile = std::move(rccFile); + } + { + std::string base = this->DirInfo; + base += "/RCC"; + base += qrc.QrcName; + if (!qrc.Unique) { + base += qrc.PathChecksum; + } + qrc.InfoFile = base; + qrc.InfoFile += "Info.cmake"; + qrc.SettingsFile = base; + qrc.SettingsFile += "Settings.cmake"; + } } } // RCC options - for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) { + for (Qrc& qrc : this->Qrcs) { // Target options std::vector<std::string> opts = optionsTarget; // Merge computed "-name XYZ" option { - std::string name = qrcDigest.QrcName; + std::string name = qrc.QrcName; // Replace '-' with '_'. The former is not valid for symbol names. std::replace(name.begin(), name.end(), '-', '_'); - if (!qrcDigest.Unique) { + if (!qrc.Unique) { name += "_"; - name += qrcDigest.PathChecksum; + name += qrc.PathChecksum; } std::vector<std::string> nameOpts; nameOpts.emplace_back("-name"); @@ -954,254 +647,325 @@ void cmQtAutoGeneratorInitializer::InitializeAutogenTarget( cmQtAutoGen::RccMergeOptions(opts, nameOpts, QtV5); } // Merge file option - cmQtAutoGen::RccMergeOptions(opts, qrcDigest.Options, QtV5); - qrcDigest.Options = std::move(opts); + cmQtAutoGen::RccMergeOptions(opts, qrc.Options, QtV5); + qrc.Options = std::move(opts); } - for (cmQtAutoGenDigestQrc& qrcDigest : digest.Qrcs) { + for (Qrc& qrc : this->Qrcs) { // Register file at target + std::vector<std::string> const ccOutput = + this->AddGeneratedSource(qrc.RccFile, cmQtAutoGen::RCC); + + cmCustomCommandLines commandLines; { - auto files = AddGeneratedSource(target, qrcDigest.RccFile, multiConfig, - configsList, cmQtAutoGen::RCC); - for (std::string& file : files) { - autogenProvides.push_back(std::move(file)); - } + cmCustomCommandLine currentLine; + currentLine.push_back(cmSystemTools::GetCMakeCommand()); + currentLine.push_back("-E"); + currentLine.push_back("cmake_autorcc"); + currentLine.push_back(qrc.InfoFile); + currentLine.push_back("$<CONFIGURATION>"); + commandLines.push_back(std::move(currentLine)); } - // Dependencies - if (qrcDigest.Generated) { - // Add the GENERATED .qrc file to the dependencies - autogenDependFiles.insert(qrcDigest.QrcFile); + std::string ccComment = "Automatic RCC for "; + ccComment += FileProjectRelativePath(makefile, qrc.QrcFile); + + if (qrc.Generated) { + // Create custom rcc target + std::string ccName; + { + ccName = this->Target->GetName(); + ccName += "_arcc_"; + ccName += qrc.QrcName; + if (!qrc.Unique) { + ccName += "_"; + ccName += qrc.PathChecksum; + } + std::vector<std::string> ccDepends; + // Add the .qrc file to the custom target dependencies + ccDepends.push_back(qrc.QrcFile); + + cmTarget* autoRccTarget = makefile->AddUtilityCommand( + ccName, cmMakefile::TargetOrigin::Generator, true, + this->DirWork.c_str(), ccOutput, ccDepends, commandLines, false, + ccComment.c_str()); + // Create autogen generator target + localGen->AddGeneratorTarget( + new cmGeneratorTarget(autoRccTarget, localGen)); + + // Set FOLDER property in autogen target + if (!this->AutogenFolder.empty()) { + autoRccTarget->SetProperty("FOLDER", this->AutogenFolder.c_str()); + } + } + // Add autogen target to the origin target dependencies + this->Target->Target->AddUtility(ccName, makefile); } else { - // Add the resource files to the dependencies + // Create custom rcc command { - std::string error; - if (cmQtAutoGen::RccListInputs(digest.QtVersionMajor, rcc, - qrcDigest.QrcFile, - qrcDigest.Resources, &error)) { - for (std::string const& fileName : qrcDigest.Resources) { - autogenDependFiles.insert(fileName); + std::vector<std::string> ccByproducts; + std::vector<std::string> ccDepends; + // Add the .qrc file to the custom command dependencies + ccDepends.push_back(qrc.QrcFile); + + // Add the resource files to the dependencies + { + std::string error; + if (cmQtAutoGen::RccListInputs(this->RccExecutable, + this->RccListOptions, qrc.QrcFile, + qrc.Resources, &error)) { + for (std::string const& fileName : qrc.Resources) { + // Add resource file to the custom command dependencies + ccDepends.push_back(fileName); + } + } else { + cmSystemTools::Error(error.c_str()); } - } else { - cmSystemTools::Error(error.c_str()); } + makefile->AddCustomCommandToOutput(ccOutput, ccByproducts, ccDepends, + /*main_dependency*/ std::string(), + commandLines, ccComment.c_str(), + this->DirWork.c_str()); } - // Run cmake again when .qrc file changes - makefile->AddCMakeDependFile(qrcDigest.QrcFile); + // Reconfigure when .qrc file changes + makefile->AddCMakeDependFile(qrc.QrcFile); } } } - // Add user defined autogen target dependencies - { - std::string const deps = GetSafeProperty(target, "AUTOGEN_TARGET_DEPENDS"); - if (!deps.empty()) { - std::vector<std::string> extraDeps; - cmSystemTools::ExpandListArgument(deps, extraDeps); - for (std::string const& depName : extraDeps) { - // Allow target and file dependencies - auto* depTarget = makefile->FindTargetToUse(depName); - if (depTarget != nullptr) { - autogenDependTargets.insert(depTarget); - } else { - autogenDependFiles.insert(depName); + // Create _autogen target + if (this->MocEnabled || this->UicEnabled) { + // Add user defined autogen target dependencies + { + std::string const deps = + GetSafeProperty(this->Target, "AUTOGEN_TARGET_DEPENDS"); + if (!deps.empty()) { + std::vector<std::string> extraDeps; + cmSystemTools::ExpandListArgument(deps, extraDeps); + for (std::string const& depName : extraDeps) { + // Allow target and file dependencies + auto* depTarget = makefile->FindTargetToUse(depName); + if (depTarget != nullptr) { + autogenDependTargets.insert(depTarget); + } else { + autogenDependFiles.insert(depName); + } } } } - } - // Use PRE_BUILD on demand - bool usePRE_BUILD = false; - if (globalGen->GetName().find("Visual Studio") != std::string::npos) { - // Under VS 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 = true; - } - // Disable PRE_BUILD in some cases - if (usePRE_BUILD) { - // Cannot use PRE_BUILD with file depends - if (!autogenDependFiles.empty()) { - usePRE_BUILD = false; + // Compose target comment + std::string autogenComment; + { + std::string tools; + if (this->MocEnabled) { + tools += "MOC"; + } + if (this->UicEnabled) { + if (!tools.empty()) { + tools += " and "; + } + tools += "UIC"; + } + autogenComment = "Automatic "; + autogenComment += tools; + autogenComment += " for target "; + autogenComment += this->Target->GetName(); } - } - // Create the autogen target/command - if (usePRE_BUILD) { - // Add additional autogen target dependencies to origin target - for (cmTarget* depTarget : autogenDependTargets) { - target->Target->AddUtility(depTarget->GetName(), makefile); + + // Compose command lines + cmCustomCommandLines commandLines; + { + cmCustomCommandLine currentLine; + currentLine.push_back(cmSystemTools::GetCMakeCommand()); + currentLine.push_back("-E"); + currentLine.push_back("cmake_autogen"); + currentLine.push_back(this->AutogenInfoFile); + currentLine.push_back("$<CONFIGURATION>"); + commandLines.push_back(std::move(currentLine)); } - // Add the pre-build command directly to bypass the OBJECT_LIBRARY - // rejection in cmMakefile::AddCustomCommandToTarget because we know - // PRE_BUILD will work for an OBJECT_LIBRARY in this specific case. - // - // PRE_BUILD does not support file dependencies! - const std::vector<std::string> no_output; - const std::vector<std::string> no_deps; - cmCustomCommand cc(makefile, no_output, autogenProvides, no_deps, - commandLines, autogenComment.c_str(), - workingDirectory.c_str()); - cc.SetEscapeOldStyle(false); - cc.SetEscapeAllowMakeVars(true); - target->Target->AddPreBuildCommand(cc); - } else { + // Use PRE_BUILD on demand + bool usePRE_BUILD = false; + if (globalGen->GetName().find("Visual Studio") != std::string::npos) { + // Under VS 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 = true; + } + // Disable PRE_BUILD in some cases + if (usePRE_BUILD) { + // Cannot use PRE_BUILD with file depends + if (!autogenDependFiles.empty()) { + usePRE_BUILD = false; + } + } + // Create the autogen target/command + if (usePRE_BUILD) { + // Add additional autogen target dependencies to origin target + for (cmTarget* depTarget : autogenDependTargets) { + this->Target->Target->AddUtility(depTarget->GetName(), makefile); + } - // Convert file dependencies std::set to std::vector - std::vector<std::string> autogenDepends(autogenDependFiles.begin(), - autogenDependFiles.end()); + // Add the pre-build command directly to bypass the OBJECT_LIBRARY + // rejection in cmMakefile::AddCustomCommandToTarget because we know + // PRE_BUILD will work for an OBJECT_LIBRARY in this specific case. + // + // PRE_BUILD does not support file dependencies! + const std::vector<std::string> no_output; + const std::vector<std::string> no_deps; + cmCustomCommand cc(makefile, no_output, autogenProvides, no_deps, + commandLines, autogenComment.c_str(), + this->DirWork.c_str()); + cc.SetEscapeOldStyle(false); + cc.SetEscapeAllowMakeVars(true); + this->Target->Target->AddPreBuildCommand(cc); + } else { - // Add link library target dependencies to the autogen target dependencies - for (std::string const& config : configsList) { - cmLinkImplementationLibraries const* libs = - target->GetLinkImplementationLibraries(config); - if (libs != nullptr) { - for (cmLinkItem const& item : libs->Libraries) { - cmGeneratorTarget const* libTarget = item.Target; - if ((libTarget != nullptr) && - !StaticLibraryCycle(target, libTarget, config)) { - std::string util; - if (configsList.size() > 1) { - util += "$<$<CONFIG:"; - util += config; - util += ">:"; - } - util += libTarget->GetName(); - if (configsList.size() > 1) { - util += ">"; + // Convert file dependencies std::set to std::vector + std::vector<std::string> autogenDepends(autogenDependFiles.begin(), + autogenDependFiles.end()); + + // Add link library target dependencies to the autogen target + // dependencies + for (std::string const& config : this->ConfigsList) { + cmLinkImplementationLibraries const* libs = + this->Target->GetLinkImplementationLibraries(config); + if (libs != nullptr) { + for (cmLinkItem const& item : libs->Libraries) { + cmGeneratorTarget const* libTarget = item.Target; + if ((libTarget != nullptr) && + !StaticLibraryCycle(this->Target, libTarget, config)) { + std::string util; + if (this->ConfigsList.size() > 1) { + util += "$<$<CONFIG:"; + util += config; + util += ">:"; + } + util += libTarget->GetName(); + if (this->ConfigsList.size() > 1) { + util += ">"; + } + autogenDepends.push_back(util); } - autogenDepends.push_back(util); } } } - } - // Create autogen target - cmTarget* autogenTarget = makefile->AddUtilityCommand( - autogenTargetName, true, workingDirectory.c_str(), - /*byproducts=*/autogenProvides, autogenDepends, commandLines, false, - autogenComment.c_str()); - // Create autogen generator target - localGen->AddGeneratorTarget( - new cmGeneratorTarget(autogenTarget, localGen)); - - // Forward origin utilities to autogen target - for (std::string const& depName : target->Target->GetUtilities()) { - autogenTarget->AddUtility(depName, makefile); - } - // Add additional autogen target dependencies to autogen target - for (cmTarget* depTarget : autogenDependTargets) { - autogenTarget->AddUtility(depTarget->GetName(), makefile); - } - - // Set FOLDER property in autogen target - { - const char* autogenFolder = - makefile->GetState()->GetGlobalProperty("AUTOMOC_TARGETS_FOLDER"); - if (autogenFolder == nullptr) { - autogenFolder = - makefile->GetState()->GetGlobalProperty("AUTOGEN_TARGETS_FOLDER"); + // Create autogen target + cmTarget* autogenTarget = makefile->AddUtilityCommand( + this->AutogenTargetName, cmMakefile::TargetOrigin::Generator, true, + this->DirWork.c_str(), /*byproducts=*/autogenProvides, autogenDepends, + commandLines, false, autogenComment.c_str()); + // Create autogen generator target + localGen->AddGeneratorTarget( + new cmGeneratorTarget(autogenTarget, localGen)); + + // Forward origin utilities to autogen target + for (std::string const& depName : this->Target->Target->GetUtilities()) { + autogenTarget->AddUtility(depName, makefile); } - // Inherit FOLDER property from target (#13688) - if (autogenFolder == nullptr) { - autogenFolder = SafeString(target->Target->GetProperty("FOLDER")); + // Add additional autogen target dependencies to autogen target + for (cmTarget* depTarget : autogenDependTargets) { + autogenTarget->AddUtility(depTarget->GetName(), makefile); } - if ((autogenFolder != nullptr) && (*autogenFolder != '\0')) { - autogenTarget->SetProperty("FOLDER", autogenFolder); + + // Set FOLDER property in autogen target + if (!this->AutogenFolder.empty()) { + autogenTarget->SetProperty("FOLDER", this->AutogenFolder.c_str()); } - } - // Add autogen target to the origin target dependencies - target->Target->AddUtility(autogenTargetName, makefile); + // Add autogen target to the origin target dependencies + this->Target->Target->AddUtility(this->AutogenTargetName, makefile); + } } } -void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( - cmQtAutoGenDigest const& digest) +void cmQtAutoGeneratorInitializer::SetupCustomTargets() { - cmGeneratorTarget const* target = digest.Target; - cmMakefile* makefile = target->Target->GetMakefile(); - cmQtAutoGen::MultiConfig const multiConfig = - AutogenMultiConfig(target->GetGlobalGenerator()); + cmMakefile* makefile = this->Target->Target->GetMakefile(); // forget the variables added here afterwards again: cmMakefile::ScopePushPop varScope(makefile); static_cast<void>(varScope); - // Configurations - std::string configDefault; - std::vector<std::string> configsList; + // Configuration suffixes std::map<std::string, std::string> configSuffixes; - { - configDefault = makefile->GetConfigurations(configsList); - if (configsList.empty()) { - configsList.push_back(""); - } + for (std::string const& cfg : this->ConfigsList) { + std::string& suffix = configSuffixes[cfg]; + suffix = "_"; + suffix += cfg; } - for (std::string const& cfg : configsList) { - configSuffixes[cfg] = "_" + cfg; - } - - // Configurations settings buffers - cmQtAutoGenSetup setup; // Basic setup AddDefinitionEscaped(makefile, "_multi_config", - cmQtAutoGen::MultiConfigName(multiConfig)); - AddDefinitionEscaped(makefile, "_build_dir", - GetAutogenTargetBuildDir(target)); - AddDefinitionEscaped(makefile, "_sources", digest.Sources); - AddDefinitionEscaped(makefile, "_headers", digest.Headers); - AddDefinitionEscaped(makefile, "_qt_version_major", digest.QtVersionMajor); - AddDefinitionEscaped(makefile, "_qt_version_minor", digest.QtVersionMinor); - { - if (digest.MocEnabled || digest.UicEnabled) { - SetupAcquireSkipFiles(digest, setup); - if (digest.MocEnabled) { - SetupAutoTargetMoc(digest, configDefault, configsList, setup); - } - if (digest.UicEnabled) { - SetupAutoTargetUic(digest, configDefault, configsList, setup); - } + cmQtAutoGen::MultiConfigName(this->MultiConfig)); + AddDefinitionEscaped(makefile, "_build_dir", this->DirBuild); + + if (this->MocEnabled || this->UicEnabled) { + AddDefinitionEscaped(makefile, "_qt_version_major", this->QtVersionMajor); + AddDefinitionEscaped(makefile, "_settings_file", + this->AutogenSettingsFile); + AddDefinitionEscaped(makefile, "_sources", this->Sources); + AddDefinitionEscaped(makefile, "_headers", this->Headers); + + if (this->MocEnabled) { + this->SetupCustomTargetsMoc(); } - if (digest.RccEnabled) { - SetupAutoTargetRcc(digest); + if (this->UicEnabled) { + this->SetupCustomTargetsUic(); } } + if (this->RccEnabled) { + AddDefinitionEscaped(makefile, "_qt_rcc_executable", this->RccExecutable); + AddDefinitionEscaped(makefile, "_qt_rcc_list_options", + this->RccListOptions); + } - // Generate info file - { - std::string const infoDir = GetAutogenTargetFilesDir(target); - if (!cmSystemTools::MakeDirectory(infoDir)) { - std::string emsg = ("Could not create directory: "); - emsg += cmQtAutoGen::Quoted(infoDir); - cmSystemTools::Error(emsg.c_str()); - } - std::string const infoFile = infoDir + "/AutogenInfo.cmake"; - { - std::string infoFileIn = cmSystemTools::GetCMakeRoot(); - infoFileIn += "/Modules/AutogenInfo.cmake.in"; - makefile->ConfigureFile(infoFileIn.c_str(), infoFile.c_str(), false, - true, false); - } - - // Append custom definitions to info file - // -------------------------------------- + // Create info directory on demand + if (!cmSystemTools::MakeDirectory(this->DirInfo)) { + std::string emsg = ("Could not create directory: "); + emsg += cmQtAutoGen::Quoted(this->DirInfo); + cmSystemTools::Error(emsg.c_str()); + } - // Ensure we have write permission in case .in was read-only. + auto ReOpenInfoFile = [](cmsys::ofstream& ofs, + std::string const& fileName) -> bool { + // Ensure we have write permission mode_t perm = 0; #if defined(_WIN32) && !defined(__CYGWIN__) mode_t mode_write = S_IWRITE; #else mode_t mode_write = S_IWUSR; #endif - cmSystemTools::GetPermissions(infoFile, perm); + cmSystemTools::GetPermissions(fileName, perm); if (!(perm & mode_write)) { - cmSystemTools::SetPermissions(infoFile, perm | mode_write); + cmSystemTools::SetPermissions(fileName, perm | mode_write); } - // Open and write file - cmsys::ofstream ofs(infoFile.c_str(), std::ios::app); - if (ofs) { + ofs.open(fileName.c_str(), std::ios::app); + if (!ofs) { + // File open error + std::string error = "Internal CMake error when trying to open file: "; + error += cmQtAutoGen::Quoted(fileName); + error += " for writing."; + cmSystemTools::Error(error.c_str()); + } + return static_cast<bool>(ofs); + }; + + // Generate autogen target info file + if (this->MocEnabled || this->UicEnabled) { + { + std::string infoFileIn = cmSystemTools::GetCMakeRoot(); + infoFileIn += "/Modules/AutogenInfo.cmake.in"; + makefile->ConfigureFile( + infoFileIn.c_str(), this->AutogenInfoFile.c_str(), false, true, false); + } + + // Append custom definitions to info file + // -------------------------------------- + cmsys::ofstream ofs; + if (ReOpenInfoFile(ofs, this->AutogenInfoFile)) { auto OfsWriteMap = [&ofs]( const char* key, std::map<std::string, std::string> const& map) { for (auto const& item : map) { @@ -1211,15 +975,372 @@ void cmQtAutoGeneratorInitializer::SetupAutoGenerateTarget( }; ofs << "# Configurations options\n"; OfsWriteMap("AM_CONFIG_SUFFIX", configSuffixes); - OfsWriteMap("AM_MOC_DEFINITIONS", setup.ConfigMocDefines); - OfsWriteMap("AM_MOC_INCLUDES", setup.ConfigMocIncludes); - OfsWriteMap("AM_UIC_TARGET_OPTIONS", setup.ConfigUicOptions); + OfsWriteMap("AM_MOC_DEFINITIONS", this->ConfigMocDefines); + OfsWriteMap("AM_MOC_INCLUDES", this->ConfigMocIncludes); + OfsWriteMap("AM_UIC_TARGET_OPTIONS", this->ConfigUicOptions); + // Settings files (only require for multi configuration generators) + if (this->MultiConfig != cmQtAutoGen::SINGLE) { + std::map<std::string, std::string> settingsFiles; + for (std::string const& cfg : this->ConfigsList) { + settingsFiles[cfg] = cmQtAutoGen::AppendFilenameSuffix( + this->AutogenSettingsFile, "_" + cfg); + } + OfsWriteMap("AM_SETTINGS_FILE", settingsFiles); + } + } + } + + // Generate auto RCC info files + if (this->RccEnabled) { + std::string infoFileIn = cmSystemTools::GetCMakeRoot(); + infoFileIn += "/Modules/AutoRccInfo.cmake.in"; + for (Qrc const& qrc : this->Qrcs) { + // Configure info file + makefile->ConfigureFile(infoFileIn.c_str(), qrc.InfoFile.c_str(), false, + true, false); + + // Append custom definitions to info file + // -------------------------------------- + cmsys::ofstream ofs; + if (ReOpenInfoFile(ofs, qrc.InfoFile)) { + { + ofs << "# Job\n"; + auto OfsWrite = [&ofs](const char* key, std::string const& value) { + ofs << "set(" << key << " " + << cmOutputConverter::EscapeForCMake(value) << ")\n"; + + }; + OfsWrite("ARCC_SETTINGS_FILE", qrc.SettingsFile); + OfsWrite("ARCC_SOURCE", qrc.QrcFile); + OfsWrite("ARCC_OUTPUT", qrc.RccFile); + OfsWrite("ARCC_OPTIONS", cmJoin(qrc.Options, ";")); + OfsWrite("ARCC_INPUTS", cmJoin(qrc.Resources, ";")); + } + { + ofs << "# Configurations options\n"; + auto OfsWriteMap = [&ofs]( + const char* key, std::map<std::string, std::string> const& map) { + for (auto const& item : map) { + ofs << "set(" << key << "_" << item.first << " " + << cmOutputConverter::EscapeForCMake(item.second) << ")\n"; + } + }; + OfsWriteMap("ARCC_CONFIG_SUFFIX", configSuffixes); + + // Settings files (only require for multi configuration generators) + if (this->MultiConfig != cmQtAutoGen::SINGLE) { + std::map<std::string, std::string> settingsFiles; + for (std::string const& cfg : this->ConfigsList) { + settingsFiles[cfg] = + cmQtAutoGen::AppendFilenameSuffix(qrc.SettingsFile, "_" + cfg); + } + OfsWriteMap("ARCC_SETTINGS_FILE", settingsFiles); + } + } + } else { + break; + } + } + } +} + +void cmQtAutoGeneratorInitializer::SetupCustomTargetsMoc() +{ + cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); + cmMakefile* makefile = this->Target->Target->GetMakefile(); + + AddDefinitionEscaped(makefile, "_moc_skip", this->MocSkip); + AddDefinitionEscaped(makefile, "_moc_options", + GetSafeProperty(this->Target, "AUTOMOC_MOC_OPTIONS")); + AddDefinitionEscaped(makefile, "_moc_relaxed_mode", + makefile->IsOn("CMAKE_AUTOMOC_RELAXED_MODE") ? "TRUE" + : "FALSE"); + AddDefinitionEscaped(makefile, "_moc_macro_names", + GetSafeProperty(this->Target, "AUTOMOC_MACRO_NAMES")); + AddDefinitionEscaped( + makefile, "_moc_depend_filters", + GetSafeProperty(this->Target, "AUTOMOC_DEPEND_FILTERS")); + + // Compiler predefines + if (this->Target->GetPropertyAsBool("AUTOMOC_COMPILER_PREDEFINES") && + this->QtVersionGreaterOrEqual(5, 8)) { + AddDefinitionEscaped( + makefile, "_moc_predefs_cmd", + makefile->GetSafeDefinition("CMAKE_CXX_COMPILER_PREDEFINES_COMMAND")); + } + // Moc includes and compile definitions + { + auto GetIncludeDirs = [this, + localGen](std::string const& cfg) -> std::string { + // Get the include dirs for this target, without stripping the implicit + // include dirs off, see + // https://gitlab.kitware.com/cmake/cmake/issues/13667 + std::vector<std::string> includeDirs; + localGen->GetIncludeDirectories(includeDirs, this->Target, "CXX", cfg, + false); + return cmJoin(includeDirs, ";"); + }; + auto GetCompileDefinitions = + [this, localGen](std::string const& cfg) -> std::string { + std::set<std::string> defines; + localGen->AddCompileDefinitions(defines, this->Target, cfg, "CXX"); + return cmJoin(defines, ";"); + }; + + // Default configuration settings + std::string const includeDirs = GetIncludeDirs(this->ConfigDefault); + std::string const compileDefs = GetCompileDefinitions(this->ConfigDefault); + // Other configuration settings + for (std::string const& cfg : this->ConfigsList) { + { + std::string const configIncludeDirs = GetIncludeDirs(cfg); + if (configIncludeDirs != includeDirs) { + this->ConfigMocIncludes[cfg] = configIncludeDirs; + } + } + { + std::string const configCompileDefs = GetCompileDefinitions(cfg); + if (configCompileDefs != compileDefs) { + this->ConfigMocDefines[cfg] = configCompileDefs; + } + } + } + AddDefinitionEscaped(makefile, "_moc_include_dirs", includeDirs); + AddDefinitionEscaped(makefile, "_moc_compile_defs", compileDefs); + } + + // Moc executable + { + std::string mocExec; + std::string err; + + if (this->QtVersionMajor == "5") { + cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::moc"); + if (tgt != nullptr) { + mocExec = SafeString(tgt->ImportedGetLocation("")); + } else { + err = "AUTOMOC: Qt5::moc target not found"; + } + } else if (this->QtVersionMajor == "4") { + cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::moc"); + if (tgt != nullptr) { + mocExec = SafeString(tgt->ImportedGetLocation("")); + } else { + err = "AUTOMOC: Qt4::moc target not found"; + } } else { - // File open error - std::string error = "Internal CMake error when trying to open file: "; - error += cmQtAutoGen::Quoted(infoFile); - error += " for writing."; - cmSystemTools::Error(error.c_str()); + err = "The AUTOMOC feature supports only Qt 4 and Qt 5"; + } + + if (err.empty()) { + AddDefinitionEscaped(makefile, "_qt_moc_executable", mocExec); + } else { + err += " ("; + err += this->Target->GetName(); + err += ")"; + cmSystemTools::Error(err.c_str()); } } } + +void cmQtAutoGeneratorInitializer::SetupCustomTargetsUic() +{ + cmMakefile* makefile = this->Target->Target->GetMakefile(); + + // Uic search paths + { + std::vector<std::string> uicSearchPaths; + { + std::string const usp = + GetSafeProperty(this->Target, "AUTOUIC_SEARCH_PATHS"); + if (!usp.empty()) { + cmSystemTools::ExpandListArgument(usp, uicSearchPaths); + std::string const srcDir = makefile->GetCurrentSourceDirectory(); + for (std::string& path : uicSearchPaths) { + path = cmSystemTools::CollapseFullPath(path, srcDir); + } + } + } + AddDefinitionEscaped(makefile, "_uic_search_paths", uicSearchPaths); + } + // Uic target options + { + auto UicGetOpts = [this](std::string const& cfg) -> std::string { + std::vector<std::string> opts; + this->Target->GetAutoUicOptions(opts, cfg); + return cmJoin(opts, ";"); + }; + + // Default settings + std::string const uicOpts = UicGetOpts(this->ConfigDefault); + AddDefinitionEscaped(makefile, "_uic_target_options", uicOpts); + + // Configuration specific settings + for (std::string const& cfg : this->ConfigsList) { + std::string const configUicOpts = UicGetOpts(cfg); + if (configUicOpts != uicOpts) { + this->ConfigUicOptions[cfg] = configUicOpts; + } + } + } + // .ui files skip and options + { + std::vector<std::string> uiFileFiles; + std::vector<std::vector<std::string>> uiFileOptions; + { + std::string const uiExt = "ui"; + for (cmSourceFile* sf : makefile->GetSourceFiles()) { + // sf->GetExtension() is only valid after sf->GetFullPath() ... + std::string const& fPath = sf->GetFullPath(); + if (sf->GetExtension() == uiExt) { + std::string const absFile = cmSystemTools::GetRealPath(fPath); + // Check if the .ui file should be skipped + if (sf->GetPropertyAsBool("SKIP_AUTOUIC") || + sf->GetPropertyAsBool("SKIP_AUTOGEN")) { + this->UicSkip.insert(absFile); + } + // Check if the .ui file has uic options + std::string const uicOpts = GetSafeProperty(sf, "AUTOUIC_OPTIONS"); + if (!uicOpts.empty()) { + // Check if file isn't skipped + if (this->UicSkip.count(absFile) == 0) { + uiFileFiles.push_back(absFile); + std::vector<std::string> optsVec; + cmSystemTools::ExpandListArgument(uicOpts, optsVec); + uiFileOptions.push_back(std::move(optsVec)); + } + } + } + } + } + AddDefinitionEscaped(makefile, "_qt_uic_options_files", uiFileFiles); + AddDefinitionEscaped(makefile, "_qt_uic_options_options", uiFileOptions); + } + + AddDefinitionEscaped(makefile, "_uic_skip", this->UicSkip); + + // Uic executable + { + std::string err; + std::string uicExec; + + cmLocalGenerator* localGen = this->Target->GetLocalGenerator(); + if (this->QtVersionMajor == "5") { + cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt5::uic"); + if (tgt != nullptr) { + uicExec = SafeString(tgt->ImportedGetLocation("")); + } else { + // Project does not use Qt5Widgets, but has AUTOUIC ON anyway + } + } else if (this->QtVersionMajor == "4") { + cmGeneratorTarget* tgt = localGen->FindGeneratorTargetToUse("Qt4::uic"); + if (tgt != nullptr) { + uicExec = SafeString(tgt->ImportedGetLocation("")); + } else { + err = "AUTOUIC: Qt4::uic target not found"; + } + } else { + err = "The AUTOUIC feature supports only Qt 4 and Qt 5"; + } + + if (err.empty()) { + AddDefinitionEscaped(makefile, "_qt_uic_executable", uicExec); + } else { + err += " ("; + err += this->Target->GetName(); + err += ")"; + cmSystemTools::Error(err.c_str()); + } + } +} + +std::vector<std::string> cmQtAutoGeneratorInitializer::AddGeneratedSource( + std::string const& filename, cmQtAutoGen::Generator genType) +{ + std::vector<std::string> genFiles; + // Register source file in makefile and source group + if (this->MultiConfig != cmQtAutoGen::FULL) { + genFiles.push_back(filename); + } else { + for (std::string const& cfg : this->ConfigsList) { + genFiles.push_back( + cmQtAutoGen::AppendFilenameSuffix(filename, "_" + cfg)); + } + } + { + cmMakefile* makefile = this->Target->Target->GetMakefile(); + for (std::string const& genFile : genFiles) { + { + cmSourceFile* gFile = makefile->GetOrCreateSource(genFile, true); + gFile->SetProperty("GENERATED", "1"); + gFile->SetProperty("SKIP_AUTOGEN", "On"); + } + AddToSourceGroup(makefile, genFile, genType); + } + } + + // Add source file to target + if (this->MultiConfig != cmQtAutoGen::FULL) { + this->Target->AddSource(filename); + } else { + for (std::string const& cfg : this->ConfigsList) { + std::string src = "$<$<CONFIG:"; + src += cfg; + src += ">:"; + src += cmQtAutoGen::AppendFilenameSuffix(filename, "_" + cfg); + src += ">"; + this->Target->AddSource(src); + } + } + + return genFiles; +} + +std::string cmQtAutoGeneratorInitializer::GetQtMajorVersion( + cmGeneratorTarget const* target) +{ + cmMakefile* makefile = target->Target->GetMakefile(); + std::string qtMajor = makefile->GetSafeDefinition("QT_VERSION_MAJOR"); + if (qtMajor.empty()) { + qtMajor = makefile->GetSafeDefinition("Qt5Core_VERSION_MAJOR"); + } + const char* targetQtVersion = + target->GetLinkInterfaceDependentStringProperty("QT_MAJOR_VERSION", ""); + if (targetQtVersion != nullptr) { + qtMajor = targetQtVersion; + } + return qtMajor; +} + +std::string cmQtAutoGeneratorInitializer::GetQtMinorVersion( + cmGeneratorTarget const* target, std::string const& qtVersionMajor) +{ + cmMakefile* makefile = target->Target->GetMakefile(); + std::string qtMinor; + if (qtVersionMajor == "5") { + qtMinor = makefile->GetSafeDefinition("Qt5Core_VERSION_MINOR"); + } + if (qtMinor.empty()) { + qtMinor = makefile->GetSafeDefinition("QT_VERSION_MINOR"); + } + + const char* targetQtVersion = + target->GetLinkInterfaceDependentStringProperty("QT_MINOR_VERSION", ""); + if (targetQtVersion != nullptr) { + qtMinor = targetQtVersion; + } + return qtMinor; +} + +bool cmQtAutoGeneratorInitializer::QtVersionGreaterOrEqual( + unsigned long requestMajor, unsigned long requestMinor) const +{ + unsigned long majorUL(0); + unsigned long minorUL(0); + if (cmSystemTools::StringToULong(this->QtVersionMajor.c_str(), &majorUL) && + cmSystemTools::StringToULong(this->QtVersionMinor.c_str(), &minorUL)) { + return (majorUL > requestMajor) || + (majorUL == requestMajor && minorUL >= requestMinor); + } + return false; +} diff --git a/Source/cmQtAutoGeneratorInitializer.h b/Source/cmQtAutoGeneratorInitializer.h index b8a5ae4..e06e1c4 100644 --- a/Source/cmQtAutoGeneratorInitializer.h +++ b/Source/cmQtAutoGeneratorInitializer.h @@ -4,9 +4,12 @@ #define cmQtAutoGeneratorInitializer_h #include "cmConfigure.h" // IWYU pragma: keep -#include "cmQtAutoGenDigest.h" +#include "cmQtAutoGen.h" +#include <map> +#include <set> #include <string> +#include <vector> class cmGeneratorTarget; @@ -17,8 +20,78 @@ public: static std::string GetQtMinorVersion(cmGeneratorTarget const* target, std::string const& qtVersionMajor); - static void InitializeAutogenTarget(cmQtAutoGenDigest& digest); - static void SetupAutoGenerateTarget(cmQtAutoGenDigest const& digest); + class Qrc + { + public: + Qrc() + : Generated(false) + , Unique(false) + { + } + + public: + std::string QrcFile; + std::string QrcName; + std::string PathChecksum; + std::string InfoFile; + std::string SettingsFile; + std::string RccFile; + bool Generated; + bool Unique; + std::vector<std::string> Options; + std::vector<std::string> Resources; + }; + +public: + cmQtAutoGeneratorInitializer(cmGeneratorTarget* target, bool mocEnabled, + bool uicEnabled, bool rccEnabled, + std::string const& qtVersionMajor); + + void InitCustomTargets(); + void SetupCustomTargets(); + +private: + void SetupCustomTargetsMoc(); + void SetupCustomTargetsUic(); + + std::vector<std::string> AddGeneratedSource(std::string const& filename, + cmQtAutoGen::Generator genType); + + bool QtVersionGreaterOrEqual(unsigned long requestMajor, + unsigned long requestMinor) const; + +private: + cmGeneratorTarget* Target; + bool MocEnabled; + bool UicEnabled; + bool RccEnabled; + // Qt + std::string QtVersionMajor; + std::string QtVersionMinor; + std::string RccExecutable; + std::vector<std::string> RccListOptions; + // Configurations + std::string ConfigDefault; + std::vector<std::string> ConfigsList; + cmQtAutoGen::MultiConfig MultiConfig; + // Names + std::string AutogenTargetName; + std::string AutogenFolder; + std::string AutogenInfoFile; + std::string AutogenSettingsFile; + // Directories + std::string DirInfo; + std::string DirBuild; + std::string DirWork; + // Sources + std::vector<std::string> Headers; + std::vector<std::string> Sources; + std::set<std::string> MocSkip; + std::set<std::string> UicSkip; + std::map<std::string, std::string> ConfigMocIncludes; + std::map<std::string, std::string> ConfigMocDefines; + std::map<std::string, std::string> ConfigUicOptions; + std::vector<Qrc> Qrcs; }; #endif diff --git a/Source/cmQtAutoGenerators.cxx b/Source/cmQtAutoGeneratorMocUic.cxx index 28a8df1..0de02b5 100644 --- a/Source/cmQtAutoGenerators.cxx +++ b/Source/cmQtAutoGeneratorMocUic.cxx @@ -1,10 +1,8 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmQtAutoGen.h" -#include "cmQtAutoGenerators.h" +#include "cmQtAutoGeneratorMocUic.h" -#include "cmsys/FStream.hxx" -#include "cmsys/Terminal.h" #include <algorithm> #include <array> #include <list> @@ -15,12 +13,8 @@ #include "cmAlgorithms.h" #include "cmCryptoHash.h" -#include "cmFilePathChecksum.h" -#include "cmGlobalGenerator.h" #include "cmMakefile.h" #include "cmOutputConverter.h" -#include "cmStateDirectory.h" -#include "cmStateSnapshot.h" #include "cmSystemTools.h" #include "cmake.h" @@ -32,37 +26,9 @@ static const char* SettingsKeyMoc = "AM_MOC_SETTINGS_HASH"; static const char* SettingsKeyUic = "AM_UIC_SETTINGS_HASH"; -static const char* SettingsKeyRcc = "AM_RCC_SETTINGS_HASH"; // -- Static functions -static std::string HeadLine(std::string const& title) -{ - std::string head = title; - head += '\n'; - head.append(head.size() - 1, '-'); - head += '\n'; - return head; -} - -static std::string QuotedCommand(std::vector<std::string> const& command) -{ - std::string res; - for (std::string const& item : command) { - if (!res.empty()) { - res.push_back(' '); - } - std::string const cesc = cmQtAutoGen::Quoted(item); - if (item.empty() || (cesc.size() > (item.size() + 2)) || - (cesc.find(' ') != std::string::npos)) { - res += cesc; - } else { - res += item; - } - } - return res; -} - static std::string SubDirPrefix(std::string const& fileName) { std::string res(cmSystemTools::GetFilenamePath(fileName)); @@ -72,56 +38,6 @@ static std::string SubDirPrefix(std::string const& fileName) return res; } -static bool ReadFile(std::string& content, std::string const& filename, - std::string* error = nullptr) -{ - bool success = false; - if (cmSystemTools::FileExists(filename)) { - std::size_t const length = cmSystemTools::FileLength(filename); - cmsys::ifstream ifs(filename.c_str(), (std::ios::in | std::ios::binary)); - if (ifs) { - content.resize(length); - ifs.read(&content.front(), content.size()); - if (ifs) { - success = true; - } else { - content.clear(); - if (error != nullptr) { - error->append("Reading from the file failed."); - } - } - } else if (error != nullptr) { - error->append("Opening the file for reading failed."); - } - } else if (error != nullptr) { - error->append("The file does not exist."); - } - return success; -} - -/** - * @brief Tests if buildFile is older than sourceFile - * @return True if buildFile is older than sourceFile. - * False may indicate an error. - */ -static bool FileIsOlderThan(std::string const& buildFile, - std::string const& sourceFile, - std::string* error = nullptr) -{ - int result = 0; - if (cmSystemTools::FileTimeCompare(buildFile, sourceFile, &result)) { - return (result < 0); - } - if (error != nullptr) { - error->append( - "File modification time comparison failed for the files\n "); - error->append(cmQtAutoGen::Quoted(buildFile)); - error->append("\nand\n "); - error->append(cmQtAutoGen::Quoted(sourceFile)); - } - return false; -} - static bool ListContains(std::vector<std::string> const& list, std::string const& entry) { @@ -130,25 +46,15 @@ static bool ListContains(std::vector<std::string> const& list, // -- Class methods -cmQtAutoGenerators::cmQtAutoGenerators() +cmQtAutoGeneratorMocUic::cmQtAutoGeneratorMocUic() : MultiConfig(cmQtAutoGen::WRAP) , IncludeProjectDirsBefore(false) - , Verbose(cmSystemTools::HasEnv("VERBOSE")) - , ColorOutput(true) + , QtVersionMajor(4) , MocSettingsChanged(false) , MocPredefsChanged(false) , MocRelaxedMode(false) , UicSettingsChanged(false) - , RccSettingsChanged(false) { - { - std::string colorEnv; - cmSystemTools::GetEnv("COLOR", colorEnv); - if (!colorEnv.empty()) { - this->ColorOutput = cmSystemTools::IsOn(colorEnv.c_str()); - } - } - // Precompile regular expressions this->MocRegExpInclude.compile( "[\n][ \t]*#[ \t]*include[ \t]+" @@ -157,39 +63,7 @@ cmQtAutoGenerators::cmQtAutoGenerators() "[\"<](([^ \">]+/)?ui_[^ \">/]+\\.h)[\">]"); } -bool cmQtAutoGenerators::Run(std::string const& targetDirectory, - std::string const& config) -{ - cmake cm(cmake::RoleScript); - cm.SetHomeOutputDirectory(targetDirectory); - cm.SetHomeDirectory(targetDirectory); - cm.GetCurrentSnapshot().SetDefaultDefinitions(); - cmGlobalGenerator gg(&cm); - - cmStateSnapshot snapshot = cm.GetCurrentSnapshot(); - snapshot.GetDirectory().SetCurrentBinary(targetDirectory); - snapshot.GetDirectory().SetCurrentSource(targetDirectory); - - auto makefile = cm::make_unique<cmMakefile>(&gg, snapshot); - gg.SetCurrentMakefile(makefile.get()); - - bool success = false; - if (this->InitInfoFile(makefile.get(), targetDirectory, config)) { - // Read latest settings - this->SettingsFileRead(makefile.get()); - if (this->Process()) { - // Write current settings - if (this->SettingsFileWrite()) { - success = true; - } - } - } - return success; -} - -bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile, - std::string const& targetDirectory, - std::string const& config) +bool cmQtAutoGeneratorMocUic::InitInfoFile(cmMakefile* makefile) { // -- Meta this->HeaderExtensions = makefile->GetCMakeInstance()->GetHeaderExtensions(); @@ -233,12 +107,12 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile, } return lists; }; - auto InfoGetConfig = [makefile, &config](const char* key) -> std::string { + auto InfoGetConfig = [makefile, this](const char* key) -> std::string { const char* valueConf = nullptr; { std::string keyConf = key; keyConf += '_'; - keyConf += config; + keyConf += this->GetInfoConfig(); valueConf = makefile->GetDefinition(keyConf); } if (valueConf == nullptr) { @@ -254,11 +128,8 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile, }; // -- Read info file - this->InfoFile = cmSystemTools::CollapseFullPath(targetDirectory); - cmSystemTools::ConvertToUnixSlashes(this->InfoFile); - this->InfoFile += "/AutogenInfo.cmake"; - if (!makefile->ReadListFile(this->InfoFile.c_str())) { - this->LogFileError(cmQtAutoGen::GEN, this->InfoFile, + if (!makefile->ReadListFile(this->GetInfoFile().c_str())) { + this->LogFileError(cmQtAutoGen::GEN, this->GetInfoFile(), "File processing failed"); return false; } @@ -268,7 +139,14 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile, this->ConfigSuffix = InfoGetConfig("AM_CONFIG_SUFFIX"); if (this->ConfigSuffix.empty()) { this->ConfigSuffix = "_"; - this->ConfigSuffix += config; + this->ConfigSuffix += this->GetInfoConfig(); + } + + this->SettingsFile = InfoGetConfig("AM_SETTINGS_FILE"); + if (this->SettingsFile.empty()) { + this->LogFileError(cmQtAutoGen::GEN, this->GetInfoFile(), + "Settings file name missing"); + return false; } // - Files and directories @@ -280,25 +158,18 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile, InfoGetBool("AM_CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE"); this->AutogenBuildDir = InfoGet("AM_BUILD_DIR"); if (this->AutogenBuildDir.empty()) { - this->LogFileError(cmQtAutoGen::GEN, this->InfoFile, + this->LogFileError(cmQtAutoGen::GEN, this->GetInfoFile(), "Autogen build directory missing"); return false; } // - Qt environment - this->QtMajorVersion = InfoGet("AM_QT_VERSION_MAJOR"); - this->QtMinorVersion = InfoGet("AM_QT_VERSION_MINOR"); + if (!cmSystemTools::StringToULong(InfoGet("AM_QT_VERSION_MAJOR"), + &this->QtVersionMajor)) { + this->QtVersionMajor = 4; + } this->MocExecutable = InfoGet("AM_QT_MOC_EXECUTABLE"); this->UicExecutable = InfoGet("AM_QT_UIC_EXECUTABLE"); - this->RccExecutable = InfoGet("AM_QT_RCC_EXECUTABLE"); - - // Check Qt version - if ((this->QtMajorVersion != "4") && (this->QtMajorVersion != "5")) { - this->LogFileError(cmQtAutoGen::GEN, this->InfoFile, - "Unsupported Qt version: " + - cmQtAutoGen::Quoted(this->QtMajorVersion)); - return false; - } // - Moc if (this->MocEnabled()) { @@ -327,7 +198,7 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile, std::vector<std::string> const mocDependFilters = InfoGetList("AM_MOC_DEPEND_FILTERS"); // Insert Q_PLUGIN_METADATA dependency filter - if (this->QtMajorVersion != "4") { + if (this->QtVersionMajor != 4) { this->MocDependFilterPush("Q_PLUGIN_METADATA", "[\n][ \t]*Q_PLUGIN_METADATA[ \t]*\\(" "[^\\)]*FILE[ \t]*\"([^\"]+)\""); @@ -344,7 +215,7 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile, } } else { this->LogFileError( - cmQtAutoGen::MOC, this->InfoFile, + cmQtAutoGen::MOC, this->GetInfoFile(), "AUTOMOC_DEPEND_FILTERS list size is not a multiple of 2"); return false; } @@ -365,7 +236,7 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile, std::ostringstream ost; ost << "files/options lists sizes missmatch (" << sources.size() << "/" << options.size() << ")"; - this->LogFileError(cmQtAutoGen::UIC, this->InfoFile, ost.str()); + this->LogFileError(cmQtAutoGen::UIC, this->GetInfoFile(), ost.str()); return false; } auto fitEnd = sources.cend(); @@ -379,53 +250,6 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile, } } - // - Rcc - if (this->RccEnabled()) { - // File lists - auto sources = InfoGetList("AM_RCC_SOURCES"); - auto builds = InfoGetList("AM_RCC_BUILDS"); - auto options = InfoGetLists("AM_RCC_OPTIONS"); - auto inputs = InfoGetLists("AM_RCC_INPUTS"); - - if (sources.size() != builds.size()) { - std::ostringstream ost; - ost << "sources, builds lists sizes missmatch (" << sources.size() << "/" - << builds.size() << ")"; - this->LogFileError(cmQtAutoGen::RCC, this->InfoFile, ost.str()); - return false; - } - if (sources.size() != options.size()) { - std::ostringstream ost; - ost << "sources, options lists sizes missmatch (" << sources.size() - << "/" << options.size() << ")"; - this->LogFileError(cmQtAutoGen::RCC, this->InfoFile, ost.str()); - return false; - } - if (sources.size() != inputs.size()) { - std::ostringstream ost; - ost << "sources, inputs lists sizes missmatch (" << sources.size() << "/" - << inputs.size() << ")"; - this->LogFileError(cmQtAutoGen::RCC, this->InfoFile, ost.str()); - return false; - } - { - auto srcItEnd = sources.end(); - auto srcIt = sources.begin(); - auto bldIt = builds.begin(); - auto optIt = options.begin(); - auto inpIt = inputs.begin(); - while (srcIt != srcItEnd) { - this->RccJobs.push_back(RccJob{ std::move(*srcIt), std::move(*bldIt), - std::move(*optIt), - std::move(*inpIt) }); - ++srcIt; - ++bldIt; - ++optIt; - ++inpIt; - } - } - } - // Initialize source file jobs { // Utility lambdas @@ -585,21 +409,10 @@ bool cmQtAutoGenerators::InitInfoFile(cmMakefile* makefile, } } - // - Old settings file - { - this->SettingsFile = cmSystemTools::CollapseFullPath(targetDirectory); - cmSystemTools::ConvertToUnixSlashes(this->SettingsFile); - this->SettingsFile += "/AutogenOldSettings"; - if (this->MultiConfig != cmQtAutoGen::SINGLE) { - this->SettingsFile += this->ConfigSuffix; - } - this->SettingsFile += ".cmake"; - } - return true; } -void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile) +void cmQtAutoGeneratorMocUic::SettingsFileRead(cmMakefile* makefile) { // Compose current settings strings { @@ -631,20 +444,6 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile) str += sep; this->SettingsStringUic = crypt.HashString(str); } - if (this->RccEnabled()) { - std::string str; - str += this->RccExecutable; - for (const RccJob& rccJob : this->RccJobs) { - str += sep; - str += rccJob.QrcFile; - str += sep; - str += rccJob.RccFile; - str += sep; - str += cmJoin(rccJob.Options, ";"); - } - str += sep; - this->SettingsStringRcc = crypt.HashString(str); - } } // Read old settings @@ -659,9 +458,6 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile) if (!SMatch(SettingsKeyUic, this->SettingsStringUic)) { this->UicSettingsChanged = true; } - if (!SMatch(SettingsKeyRcc, this->SettingsStringRcc)) { - this->RccSettingsChanged = true; - } } // In case any setting changed remove the old settings file. // This triggers a full rebuild on the next run if the current @@ -673,16 +469,15 @@ void cmQtAutoGenerators::SettingsFileRead(cmMakefile* makefile) // If the file could not be read re-generate everythiung. this->MocSettingsChanged = true; this->UicSettingsChanged = true; - this->RccSettingsChanged = true; } } -bool cmQtAutoGenerators::SettingsFileWrite() +bool cmQtAutoGeneratorMocUic::SettingsFileWrite() { bool success = true; // Only write if any setting changed if (this->SettingsChanged()) { - if (this->Verbose) { + if (this->GetVerbose()) { this->LogInfo(cmQtAutoGen::GEN, "Writing settings file " + cmQtAutoGen::Quoted(this->SettingsFile)); } @@ -699,7 +494,6 @@ bool cmQtAutoGenerators::SettingsFileWrite() }; SettingAppend(SettingsKeyMoc, this->SettingsStringMoc); SettingAppend(SettingsKeyUic, this->SettingsStringUic); - SettingAppend(SettingsKeyRcc, this->SettingsStringRcc); } // Write settings file if (!this->FileWrite(cmQtAutoGen::GEN, this->SettingsFile, settings)) { @@ -713,7 +507,7 @@ bool cmQtAutoGenerators::SettingsFileWrite() return success; } -bool cmQtAutoGenerators::Process() +bool cmQtAutoGeneratorMocUic::Process(cmMakefile* makefile) { // the program goes through all .cpp files to see which moc files are // included. It is not really interesting how the moc file is named, but @@ -723,6 +517,12 @@ bool cmQtAutoGenerators::Process() // moc file is included anywhere a moc_<filename>.cpp file is created and // included in the mocs_compilation.cpp file. + if (!this->InitInfoFile(makefile)) { + return false; + } + // Read latest settings + this->SettingsFileRead(makefile); + // Create AUTOGEN include directory { std::string const incDirAbs = cmSystemTools::CollapseCombinedPath( @@ -758,7 +558,8 @@ bool cmQtAutoGenerators::Process() if (!this->UicGenerateAll()) { return false; } - if (!this->RccGenerateAll()) { + + if (!this->SettingsFileWrite()) { return false; } @@ -768,12 +569,12 @@ bool cmQtAutoGenerators::Process() /** * @return True on success */ -bool cmQtAutoGenerators::ParseSourceFile(std::string const& absFilename, - const SourceJob& job) +bool cmQtAutoGeneratorMocUic::ParseSourceFile(std::string const& absFilename, + const SourceJob& job) { std::string contentText; std::string error; - bool success = ReadFile(contentText, absFilename, &error); + bool success = this->FileRead(contentText, absFilename, &error); if (success) { if (!contentText.empty()) { if (job.Moc) { @@ -796,12 +597,12 @@ bool cmQtAutoGenerators::ParseSourceFile(std::string const& absFilename, /** * @return True on success */ -bool cmQtAutoGenerators::ParseHeaderFile(std::string const& absFilename, - const SourceJob& job) +bool cmQtAutoGeneratorMocUic::ParseHeaderFile(std::string const& absFilename, + const SourceJob& job) { std::string contentText; std::string error; - bool success = ReadFile(contentText, absFilename, &error); + bool success = this->FileRead(contentText, absFilename, &error); if (success) { if (!contentText.empty()) { if (job.Moc) { @@ -824,7 +625,7 @@ bool cmQtAutoGenerators::ParseHeaderFile(std::string const& absFilename, /** * @return True on success */ -bool cmQtAutoGenerators::ParsePostprocess() +bool cmQtAutoGeneratorMocUic::ParsePostprocess() { bool success = true; // Read missing dependencies @@ -832,7 +633,7 @@ bool cmQtAutoGenerators::ParsePostprocess() if (!item->DependsValid) { std::string content; std::string error; - if (ReadFile(content, item->SourceFile, &error)) { + if (this->FileRead(content, item->SourceFile, &error)) { this->MocFindDepends(item->SourceFile, content, item->Depends); item->DependsValid = true; } else { @@ -855,7 +656,7 @@ bool cmQtAutoGenerators::ParsePostprocess() * @brief Tests if the file should be ignored for moc scanning * @return True if the file should be ignored */ -bool cmQtAutoGenerators::MocSkip(std::string const& absFilename) const +bool cmQtAutoGeneratorMocUic::MocSkip(std::string const& absFilename) const { if (this->MocEnabled()) { // Test if the file name is on the skip list @@ -870,8 +671,8 @@ bool cmQtAutoGenerators::MocSkip(std::string const& absFilename) const * @brief Tests if the C++ content requires moc processing * @return True if moc is required */ -bool cmQtAutoGenerators::MocRequired(std::string const& contentText, - std::string* macroName) +bool cmQtAutoGeneratorMocUic::MocRequired(std::string const& contentText, + std::string* macroName) { for (KeyRegExp& filter : this->MocMacroFilters) { // Run a simple find string operation before the expensive @@ -889,7 +690,7 @@ bool cmQtAutoGenerators::MocRequired(std::string const& contentText, return false; } -std::string cmQtAutoGenerators::MocStringMacros() const +std::string cmQtAutoGeneratorMocUic::MocStringMacros() const { std::string res; const auto itB = this->MocMacroFilters.cbegin(); @@ -911,7 +712,7 @@ std::string cmQtAutoGenerators::MocStringMacros() const return res; } -std::string cmQtAutoGenerators::MocStringHeaders( +std::string cmQtAutoGeneratorMocUic::MocStringHeaders( std::string const& fileBase) const { std::string res = fileBase; @@ -921,7 +722,7 @@ std::string cmQtAutoGenerators::MocStringHeaders( return res; } -std::string cmQtAutoGenerators::MocFindIncludedHeader( +std::string cmQtAutoGeneratorMocUic::MocFindIncludedHeader( std::string const& sourcePath, std::string const& includeBase) const { std::string header; @@ -944,7 +745,7 @@ std::string cmQtAutoGenerators::MocFindIncludedHeader( return header; } -bool cmQtAutoGenerators::MocFindIncludedFile( +bool cmQtAutoGeneratorMocUic::MocFindIncludedFile( std::string& absFile, std::string const& sourcePath, std::string const& includeString) const { @@ -974,8 +775,8 @@ bool cmQtAutoGenerators::MocFindIncludedFile( return success; } -bool cmQtAutoGenerators::MocDependFilterPush(std::string const& key, - std::string const& regExp) +bool cmQtAutoGeneratorMocUic::MocDependFilterPush(std::string const& key, + std::string const& regExp) { std::string error; if (!key.empty()) { @@ -1009,9 +810,9 @@ bool cmQtAutoGenerators::MocDependFilterPush(std::string const& key, return true; } -void cmQtAutoGenerators::MocFindDepends(std::string const& absFilename, - std::string const& contentText, - std::set<std::string>& depends) +void cmQtAutoGeneratorMocUic::MocFindDepends(std::string const& absFilename, + std::string const& contentText, + std::set<std::string>& depends) { if (this->MocDependFilters.empty() && contentText.empty()) { return; @@ -1040,7 +841,7 @@ void cmQtAutoGenerators::MocFindDepends(std::string const& absFilename, std::string incFile; if (this->MocFindIncludedFile(incFile, sourcePath, match)) { depends.insert(incFile); - if (this->Verbose) { + if (this->GetVerbose()) { this->LogInfo(cmQtAutoGen::MOC, "Found dependency:\n " + cmQtAutoGen::Quoted(absFilename) + "\n " + cmQtAutoGen::Quoted(incFile)); @@ -1057,10 +858,10 @@ void cmQtAutoGenerators::MocFindDepends(std::string const& absFilename, /** * @return True on success */ -bool cmQtAutoGenerators::MocParseSourceContent(std::string const& absFilename, - std::string const& contentText) +bool cmQtAutoGeneratorMocUic::MocParseSourceContent( + std::string const& absFilename, std::string const& contentText) { - if (this->Verbose) { + if (this->GetVerbose()) { this->LogInfo(cmQtAutoGen::MOC, "Checking: " + absFilename); } @@ -1296,10 +1097,10 @@ bool cmQtAutoGenerators::MocParseSourceContent(std::string const& absFilename, return true; } -void cmQtAutoGenerators::MocParseHeaderContent(std::string const& absFilename, - std::string const& contentText) +void cmQtAutoGeneratorMocUic::MocParseHeaderContent( + std::string const& absFilename, std::string const& contentText) { - if (this->Verbose) { + if (this->GetVerbose()) { this->LogInfo(cmQtAutoGen::MOC, "Checking: " + absFilename); } @@ -1329,7 +1130,7 @@ void cmQtAutoGenerators::MocParseHeaderContent(std::string const& absFilename, } } -bool cmQtAutoGenerators::MocGenerateAll() +bool cmQtAutoGeneratorMocUic::MocGenerateAll() { if (!this->MocEnabled()) { return true; @@ -1384,7 +1185,7 @@ bool cmQtAutoGenerators::MocGenerateAll() if (!this->MocPredefsCmd.empty()) { if (this->MocSettingsChanged || !cmSystemTools::FileExists(this->MocPredefsFileAbs)) { - if (this->Verbose) { + if (this->GetVerbose()) { this->LogBold("Generating MOC predefs " + this->MocPredefsFileRel); } @@ -1419,7 +1220,7 @@ bool cmQtAutoGenerators::MocGenerateAll() } } else { // Touch to update the time stamp - if (this->Verbose) { + if (this->GetVerbose()) { this->LogInfo(cmQtAutoGen::MOC, "Touching moc_predefs " + this->MocPredefsFileRel); } @@ -1470,7 +1271,7 @@ bool cmQtAutoGenerators::MocGenerateAll() if (this->FileDiffers(this->MocCompFileAbs, mocs)) { // Actually write mocs compilation file - if (this->Verbose) { + if (this->GetVerbose()) { this->LogBold("Generating MOC compilation " + this->MocCompFileRel); } if (!this->FileWrite(cmQtAutoGen::MOC, this->MocCompFileAbs, mocs)) { @@ -1480,7 +1281,7 @@ bool cmQtAutoGenerators::MocGenerateAll() } } else if (autoNameGenerated) { // Only touch mocs compilation file - if (this->Verbose) { + if (this->GetVerbose()) { this->LogInfo(cmQtAutoGen::MOC, "Touching mocs compilation " + this->MocCompFileRel); } @@ -1494,8 +1295,8 @@ bool cmQtAutoGenerators::MocGenerateAll() /** * @return True on success */ -bool cmQtAutoGenerators::MocGenerateFile(const MocJobAuto& mocJob, - bool* generated) +bool cmQtAutoGeneratorMocUic::MocGenerateFile(const MocJobAuto& mocJob, + bool* generated) { bool success = true; @@ -1505,7 +1306,7 @@ bool cmQtAutoGenerators::MocGenerateFile(const MocJobAuto& mocJob, bool generate = false; std::string generateReason; if (!generate && !cmSystemTools::FileExists(mocFileAbs.c_str())) { - if (this->Verbose) { + if (this->GetVerbose()) { generateReason = "Generating "; generateReason += cmQtAutoGen::Quoted(mocFileAbs); generateReason += " from its source file "; @@ -1515,7 +1316,7 @@ bool cmQtAutoGenerators::MocGenerateFile(const MocJobAuto& mocJob, generate = true; } if (!generate && this->MocSettingsChanged) { - if (this->Verbose) { + if (this->GetVerbose()) { generateReason = "Generating "; generateReason += cmQtAutoGen::Quoted(mocFileAbs); generateReason += " from "; @@ -1525,7 +1326,7 @@ bool cmQtAutoGenerators::MocGenerateFile(const MocJobAuto& mocJob, generate = true; } if (!generate && this->MocPredefsChanged) { - if (this->Verbose) { + if (this->GetVerbose()) { generateReason = "Generating "; generateReason += cmQtAutoGen::Quoted(mocFileAbs); generateReason += " from "; @@ -1537,7 +1338,7 @@ bool cmQtAutoGenerators::MocGenerateFile(const MocJobAuto& mocJob, if (!generate) { std::string error; if (FileIsOlderThan(mocFileAbs, mocJob.SourceFile, &error)) { - if (this->Verbose) { + if (this->GetVerbose()) { generateReason = "Generating "; generateReason += cmQtAutoGen::Quoted(mocFileAbs); generateReason += " because it's older than its source file "; @@ -1556,7 +1357,7 @@ bool cmQtAutoGenerators::MocGenerateFile(const MocJobAuto& mocJob, std::string error; for (std::string const& depFile : mocJob.Depends) { if (FileIsOlderThan(mocFileAbs, depFile, &error)) { - if (this->Verbose) { + if (this->GetVerbose()) { generateReason = "Generating "; generateReason += cmQtAutoGen::Quoted(mocFileAbs); generateReason += " from "; @@ -1577,7 +1378,7 @@ bool cmQtAutoGenerators::MocGenerateFile(const MocJobAuto& mocJob, if (generate) { // Log - if (this->Verbose) { + if (this->GetVerbose()) { this->LogBold("Generating MOC source " + mocJob.BuildFileRel); this->LogInfo(cmQtAutoGen::MOC, generateReason); } @@ -1627,7 +1428,7 @@ bool cmQtAutoGenerators::MocGenerateFile(const MocJobAuto& mocJob, /** * @brief Tests if the file name is in the skip list */ -bool cmQtAutoGenerators::UicSkip(std::string const& absFilename) const +bool cmQtAutoGeneratorMocUic::UicSkip(std::string const& absFilename) const { if (this->UicEnabled()) { // Test if the file name is on the skip list @@ -1638,10 +1439,10 @@ bool cmQtAutoGenerators::UicSkip(std::string const& absFilename) const return true; } -bool cmQtAutoGenerators::UicParseContent(std::string const& absFilename, - std::string const& contentText) +bool cmQtAutoGeneratorMocUic::UicParseContent(std::string const& absFilename, + std::string const& contentText) { - if (this->Verbose) { + if (this->GetVerbose()) { this->LogInfo(cmQtAutoGen::UIC, "Checking: " + absFilename); } @@ -1689,9 +1490,9 @@ bool cmQtAutoGenerators::UicParseContent(std::string const& absFilename, return true; } -bool cmQtAutoGenerators::UicFindIncludedFile(std::string& absFile, - std::string const& sourceFile, - std::string const& includeString) +bool cmQtAutoGeneratorMocUic::UicFindIncludedFile( + std::string& absFile, std::string const& sourceFile, + std::string const& includeString) { bool success = false; std::string searchFile = @@ -1753,7 +1554,7 @@ bool cmQtAutoGenerators::UicFindIncludedFile(std::string& absFile, return success; } -bool cmQtAutoGenerators::UicGenerateAll() +bool cmQtAutoGeneratorMocUic::UicGenerateAll() { if (!this->UicEnabled()) { return true; @@ -1817,7 +1618,7 @@ bool cmQtAutoGenerators::UicGenerateAll() /** * @return True on success */ -bool cmQtAutoGenerators::UicGenerateFile(const UicJob& uicJob) +bool cmQtAutoGeneratorMocUic::UicGenerateFile(const UicJob& uicJob) { bool success = true; @@ -1827,7 +1628,7 @@ bool cmQtAutoGenerators::UicGenerateFile(const UicJob& uicJob) bool generate = false; std::string generateReason; if (!generate && !cmSystemTools::FileExists(uicFileAbs.c_str())) { - if (this->Verbose) { + if (this->GetVerbose()) { generateReason = "Generating "; generateReason += cmQtAutoGen::Quoted(uicFileAbs); generateReason += " from its source file "; @@ -1837,7 +1638,7 @@ bool cmQtAutoGenerators::UicGenerateFile(const UicJob& uicJob) generate = true; } if (!generate && this->UicSettingsChanged) { - if (this->Verbose) { + if (this->GetVerbose()) { generateReason = "Generating "; generateReason += cmQtAutoGen::Quoted(uicFileAbs); generateReason += " from "; @@ -1849,7 +1650,7 @@ bool cmQtAutoGenerators::UicGenerateFile(const UicJob& uicJob) if (!generate) { std::string error; if (FileIsOlderThan(uicFileAbs, uicJob.SourceFile, &error)) { - if (this->Verbose) { + if (this->GetVerbose()) { generateReason = "Generating "; generateReason += cmQtAutoGen::Quoted(uicFileAbs); generateReason += " because it's older than its source file "; @@ -1865,7 +1666,7 @@ bool cmQtAutoGenerators::UicGenerateFile(const UicJob& uicJob) } if (generate) { // Log - if (this->Verbose) { + if (this->GetVerbose()) { this->LogBold("Generating UIC header " + uicJob.BuildFileRel); this->LogInfo(cmQtAutoGen::UIC, generateReason); } @@ -1880,7 +1681,7 @@ bool cmQtAutoGenerators::UicGenerateFile(const UicJob& uicJob) auto optionIt = this->UicOptions.find(uicJob.SourceFile); if (optionIt != this->UicOptions.end()) { cmQtAutoGen::UicMergeOptions(allOpts, optionIt->second, - (this->QtMajorVersion == "5")); + (this->QtVersionMajor == 5)); } cmd.insert(cmd.end(), allOpts.begin(), allOpts.end()); } @@ -1911,413 +1712,13 @@ bool cmQtAutoGenerators::UicGenerateFile(const UicJob& uicJob) return success; } -bool cmQtAutoGenerators::RccGenerateAll() -{ - if (!this->RccEnabled()) { - return true; - } - - // Generate rcc files - for (const RccJob& rccJob : this->RccJobs) { - if (!this->RccGenerateFile(rccJob)) { - return false; - } - } - return true; -} - -/** - * @return True on success - */ -bool cmQtAutoGenerators::RccGenerateFile(const RccJob& rccJob) -{ - bool success = true; - bool rccGenerated = false; - - std::string rccFileAbs; - { - std::string suffix; - switch (this->MultiConfig) { - case cmQtAutoGen::SINGLE: - break; - case cmQtAutoGen::WRAP: - suffix = "_CMAKE"; - suffix += this->ConfigSuffix; - suffix += "_"; - break; - case cmQtAutoGen::FULL: - suffix = this->ConfigSuffix; - break; - } - rccFileAbs = cmQtAutoGen::AppendFilenameSuffix(rccJob.RccFile, suffix); - } - std::string const rccFileRel = cmSystemTools::RelativePath( - this->AutogenBuildDir.c_str(), rccFileAbs.c_str()); - - // Check if regeneration is required - bool generate = false; - std::string generateReason; - if (!cmSystemTools::FileExists(rccJob.QrcFile)) { - { - std::string error = "Could not find the file\n "; - error += cmQtAutoGen::Quoted(rccJob.QrcFile); - this->LogError(cmQtAutoGen::RCC, error); - } - success = false; - } - if (success && !generate && !cmSystemTools::FileExists(rccFileAbs.c_str())) { - if (this->Verbose) { - generateReason = "Generating "; - generateReason += cmQtAutoGen::Quoted(rccFileAbs); - generateReason += " from its source file "; - generateReason += cmQtAutoGen::Quoted(rccJob.QrcFile); - generateReason += " because it doesn't exist"; - } - generate = true; - } - if (success && !generate && this->RccSettingsChanged) { - if (this->Verbose) { - generateReason = "Generating "; - generateReason += cmQtAutoGen::Quoted(rccFileAbs); - generateReason += " from "; - generateReason += cmQtAutoGen::Quoted(rccJob.QrcFile); - generateReason += " because the RCC settings changed"; - } - generate = true; - } - if (success && !generate) { - std::string error; - if (FileIsOlderThan(rccFileAbs, rccJob.QrcFile, &error)) { - if (this->Verbose) { - generateReason = "Generating "; - generateReason += cmQtAutoGen::Quoted(rccFileAbs); - generateReason += " because it is older than "; - generateReason += cmQtAutoGen::Quoted(rccJob.QrcFile); - } - generate = true; - } else { - if (!error.empty()) { - this->LogError(cmQtAutoGen::RCC, error); - success = false; - } - } - } - if (success && !generate) { - // Acquire input file list - std::vector<std::string> readFiles; - std::vector<std::string> const* files = nullptr; - if (!rccJob.Inputs.empty()) { - files = &rccJob.Inputs; - } else { - // Read input file list from qrc file - std::string error; - if (cmQtAutoGen::RccListInputs(this->QtMajorVersion, this->RccExecutable, - rccJob.QrcFile, readFiles, &error)) { - files = &readFiles; - } else { - this->LogFileError(cmQtAutoGen::RCC, rccJob.QrcFile, error); - success = false; - } - } - // Test if any input file is newer than the build file - if (files != nullptr) { - std::string error; - for (std::string const& resFile : *files) { - if (!cmSystemTools::FileExists(resFile.c_str())) { - error = "Could not find the file\n "; - error += cmQtAutoGen::Quoted(resFile); - error += "\nwhich is listed in\n "; - error += cmQtAutoGen::Quoted(rccJob.QrcFile); - break; - } - if (FileIsOlderThan(rccFileAbs, resFile, &error)) { - if (this->Verbose) { - generateReason = "Generating "; - generateReason += cmQtAutoGen::Quoted(rccFileAbs); - generateReason += " from "; - generateReason += cmQtAutoGen::Quoted(rccJob.QrcFile); - generateReason += " because it is older than "; - generateReason += cmQtAutoGen::Quoted(resFile); - } - generate = true; - break; - } - if (!error.empty()) { - break; - } - } - // Print error - if (!error.empty()) { - this->LogError(cmQtAutoGen::RCC, error); - success = false; - } - } - } - // Regenerate on demand - if (generate) { - // Log - if (this->Verbose) { - this->LogBold("Generating RCC source " + rccFileRel); - this->LogInfo(cmQtAutoGen::RCC, generateReason); - } - - // Make sure the parent directory exists - if (this->MakeParentDirectory(cmQtAutoGen::RCC, rccFileAbs)) { - // Compose rcc command - std::vector<std::string> cmd; - cmd.push_back(this->RccExecutable); - cmd.insert(cmd.end(), rccJob.Options.begin(), rccJob.Options.end()); - cmd.push_back("-o"); - cmd.push_back(rccFileAbs); - cmd.push_back(rccJob.QrcFile); - - std::string output; - if (this->RunCommand(cmd, output)) { - // Success - rccGenerated = true; - } else { - { - std::string emsg = "rcc failed for\n "; - emsg += cmQtAutoGen::Quoted(rccJob.QrcFile); - this->LogCommandError(cmQtAutoGen::RCC, emsg, cmd, output); - } - cmSystemTools::RemoveFile(rccFileAbs); - success = false; - } - } else { - // Parent directory creation failed - success = false; - } - } - - // Generate a wrapper source file on demand - if (success && (this->MultiConfig == cmQtAutoGen::WRAP)) { - // Wrapper file name - std::string const& wrapperFileAbs = rccJob.RccFile; - std::string const wrapperFileRel = cmSystemTools::RelativePath( - this->AutogenBuildDir.c_str(), wrapperFileAbs.c_str()); - // Wrapper file content - std::string content = "// This is an autogenerated configuration " - "wrapper file. Changes will be overwritten.\n" - "#include \""; - content += cmSystemTools::GetFilenameName(rccFileRel); - content += "\"\n"; - // Write content to file - if (this->FileDiffers(wrapperFileAbs, content)) { - // Write new wrapper file - if (this->Verbose) { - this->LogBold("Generating RCC wrapper " + wrapperFileRel); - } - if (!this->FileWrite(cmQtAutoGen::RCC, wrapperFileAbs, content)) { - this->LogFileError(cmQtAutoGen::RCC, wrapperFileAbs, - "rcc wrapper file writing failed"); - success = false; - } - } else if (rccGenerated) { - // Just touch the wrapper file - if (this->Verbose) { - this->LogInfo(cmQtAutoGen::RCC, - "Touching RCC wrapper " + wrapperFileRel); - } - cmSystemTools::Touch(wrapperFileAbs, false); - } - } - - return success; -} - -void cmQtAutoGenerators::LogBold(std::string const& message) const -{ - cmSystemTools::MakefileColorEcho(cmsysTerminal_Color_ForegroundBlue | - cmsysTerminal_Color_ForegroundBold, - message.c_str(), true, this->ColorOutput); -} - -void cmQtAutoGenerators::LogInfo(cmQtAutoGen::Generator genType, - std::string const& message) const -{ - std::string msg = cmQtAutoGen::GeneratorName(genType); - msg += ": "; - msg += message; - if (msg.back() != '\n') { - msg.push_back('\n'); - } - cmSystemTools::Stdout(msg.c_str(), msg.size()); -} - -void cmQtAutoGenerators::LogWarning(cmQtAutoGen::Generator genType, - std::string const& message) const -{ - std::string msg = cmQtAutoGen::GeneratorName(genType); - msg += " warning:"; - if (message.find('\n') == std::string::npos) { - // Single line message - msg.push_back(' '); - } else { - // Multi line message - msg.push_back('\n'); - } - // Message - msg += message; - if (msg.back() != '\n') { - msg.push_back('\n'); - } - msg.push_back('\n'); - cmSystemTools::Stdout(msg.c_str(), msg.size()); -} - -void cmQtAutoGenerators::LogFileWarning(cmQtAutoGen::Generator genType, - std::string const& filename, - std::string const& message) const -{ - std::string msg = " "; - msg += cmQtAutoGen::Quoted(filename); - msg.push_back('\n'); - // Message - msg += message; - this->LogWarning(genType, msg); -} - -void cmQtAutoGenerators::LogError(cmQtAutoGen::Generator genType, - std::string const& message) const -{ - std::string msg; - msg.push_back('\n'); - msg += HeadLine(cmQtAutoGen::GeneratorName(genType) + " error"); - // Message - msg += message; - if (msg.back() != '\n') { - msg.push_back('\n'); - } - msg.push_back('\n'); - cmSystemTools::Stderr(msg.c_str(), msg.size()); -} - -void cmQtAutoGenerators::LogFileError(cmQtAutoGen::Generator genType, - std::string const& filename, - std::string const& message) const -{ - std::string emsg = " "; - emsg += cmQtAutoGen::Quoted(filename); - emsg += '\n'; - // Message - emsg += message; - this->LogError(genType, emsg); -} - -void cmQtAutoGenerators::LogCommandError( - cmQtAutoGen::Generator genType, std::string const& message, - std::vector<std::string> const& command, std::string const& output) const -{ - std::string msg; - msg.push_back('\n'); - msg += HeadLine(cmQtAutoGen::GeneratorName(genType) + " subprocess error"); - msg += message; - if (msg.back() != '\n') { - msg.push_back('\n'); - } - msg.push_back('\n'); - msg += HeadLine("Command"); - msg += QuotedCommand(command); - if (msg.back() != '\n') { - msg.push_back('\n'); - } - msg.push_back('\n'); - msg += HeadLine("Output"); - msg += output; - if (msg.back() != '\n') { - msg.push_back('\n'); - } - msg.push_back('\n'); - cmSystemTools::Stderr(msg.c_str(), msg.size()); -} - -/** - * @brief Generates the parent directory of the given file on demand - * @return True on success - */ -bool cmQtAutoGenerators::MakeParentDirectory(cmQtAutoGen::Generator genType, - std::string const& filename) const -{ - bool success = true; - std::string const dirName = cmSystemTools::GetFilenamePath(filename); - if (!dirName.empty()) { - if (!cmSystemTools::MakeDirectory(dirName)) { - this->LogFileError(genType, filename, - "Could not create parent directory"); - success = false; - } - } - return success; -} - -bool cmQtAutoGenerators::FileDiffers(std::string const& filename, - std::string const& content) -{ - bool differs = true; - { - std::string oldContents; - if (ReadFile(oldContents, filename)) { - differs = (oldContents != content); - } - } - return differs; -} - -bool cmQtAutoGenerators::FileWrite(cmQtAutoGen::Generator genType, - std::string const& filename, - std::string const& content) -{ - std::string error; - // Make sure the parent directory exists - if (this->MakeParentDirectory(genType, filename)) { - cmsys::ofstream outfile; - outfile.open(filename.c_str(), - (std::ios::out | std::ios::binary | std::ios::trunc)); - if (outfile) { - outfile << content; - // Check for write errors - if (!outfile.good()) { - error = "File writing failed"; - } - } else { - error = "Opening file for writing failed"; - } - } - if (!error.empty()) { - this->LogFileError(genType, filename, error); - return false; - } - return true; -} - -/** - * @brief Runs a command and returns true on success - * @return True on success - */ -bool cmQtAutoGenerators::RunCommand(std::vector<std::string> const& command, - std::string& output) const -{ - // Log command - if (this->Verbose) { - std::string qcmd = QuotedCommand(command); - qcmd.push_back('\n'); - cmSystemTools::Stdout(qcmd.c_str(), qcmd.size()); - } - // Execute command - int retVal = 0; - bool res = cmSystemTools::RunSingleCommand( - command, &output, &output, &retVal, nullptr, cmSystemTools::OUTPUT_NONE); - return (res && (retVal == 0)); -} - /** * @brief Tries to find the header file to the given file base path by * appending different header extensions * @return True on success */ -bool cmQtAutoGenerators::FindHeader(std::string& header, - std::string const& testBasePath) const +bool cmQtAutoGeneratorMocUic::FindHeader(std::string& header, + std::string const& testBasePath) const { for (std::string const& ext : this->HeaderExtensions) { std::string testFilePath(testBasePath); diff --git a/Source/cmQtAutoGenerators.h b/Source/cmQtAutoGeneratorMocUic.h index a7bb538..d510939 100644 --- a/Source/cmQtAutoGenerators.h +++ b/Source/cmQtAutoGeneratorMocUic.h @@ -1,12 +1,13 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmQtAutoGenerators_h -#define cmQtAutoGenerators_h +#ifndef cmQtAutoGeneratorMocUic_h +#define cmQtAutoGeneratorMocUic_h #include "cmConfigure.h" // IWYU pragma: keep #include "cmFilePathChecksum.h" #include "cmQtAutoGen.h" +#include "cmQtAutoGenerator.h" #include "cmsys/RegularExpression.hxx" #include <map> @@ -17,12 +18,11 @@ class cmMakefile; -class cmQtAutoGenerators +class cmQtAutoGeneratorMocUic : public cmQtAutoGenerator { - CM_DISABLE_COPY(cmQtAutoGenerators) + CM_DISABLE_COPY(cmQtAutoGeneratorMocUic) public: - cmQtAutoGenerators(); - bool Run(std::string const& targetDirectory, std::string const& config); + cmQtAutoGeneratorMocUic(); private: // -- Types @@ -80,30 +80,19 @@ private: std::string IncludeString; }; - /// @brief RCC job - struct RccJob - { - std::string QrcFile; - std::string RccFile; - std::vector<std::string> Options; - std::vector<std::string> Inputs; - }; - // -- Initialization - bool InitInfoFile(cmMakefile* makefile, std::string const& targetDirectory, - std::string const& config); + bool InitInfoFile(cmMakefile* makefile); // -- Settings file void SettingsFileRead(cmMakefile* makefile); bool SettingsFileWrite(); bool SettingsChanged() const { - return (this->MocSettingsChanged || this->RccSettingsChanged || - this->UicSettingsChanged); + return (this->MocSettingsChanged || this->UicSettingsChanged); } // -- Central processing - bool Process(); + bool Process(cmMakefile* makefile) override; // -- Source parsing bool ParseSourceFile(std::string const& absFilename, const SourceJob& job); @@ -146,54 +135,17 @@ private: bool UicGenerateAll(); bool UicGenerateFile(const UicJob& uicJob); - // -- Rcc - bool RccEnabled() const { return !this->RccExecutable.empty(); } - bool RccGenerateAll(); - bool RccGenerateFile(const RccJob& rccJob); - - // -- Log info - void LogBold(std::string const& message) const; - void LogInfo(cmQtAutoGen::Generator genType, - std::string const& message) const; - // -- Log warning - void LogWarning(cmQtAutoGen::Generator genType, - std::string const& message) const; - void LogFileWarning(cmQtAutoGen::Generator genType, - std::string const& filename, - std::string const& message) const; - // -- Log error - void LogError(cmQtAutoGen::Generator genType, - std::string const& message) const; - void LogFileError(cmQtAutoGen::Generator genType, - std::string const& filename, - std::string const& message) const; - void LogCommandError(cmQtAutoGen::Generator genType, - std::string const& message, - std::vector<std::string> const& command, - std::string const& output) const; - // -- Utility - bool MakeParentDirectory(cmQtAutoGen::Generator genType, - std::string const& filename) const; - bool FileDiffers(std::string const& filename, std::string const& content); - bool FileWrite(cmQtAutoGen::Generator genType, std::string const& filename, - std::string const& content); bool FindHeader(std::string& header, std::string const& testBasePath) const; - bool RunCommand(std::vector<std::string> const& command, - std::string& output) const; // -- Meta - std::string InfoFile; std::string ConfigSuffix; cmQtAutoGen::MultiConfig MultiConfig; // -- Settings bool IncludeProjectDirsBefore; - bool Verbose; - bool ColorOutput; std::string SettingsFile; std::string SettingsStringMoc; std::string SettingsStringUic; - std::string SettingsStringRcc; // -- Directories std::string ProjectSourceDir; std::string ProjectBinaryDir; @@ -202,11 +154,9 @@ private: std::string AutogenBuildDir; std::string AutogenIncludeDir; // -- Qt environment - std::string QtMajorVersion; - std::string QtMinorVersion; + unsigned long QtVersionMajor; std::string MocExecutable; std::string UicExecutable; - std::string RccExecutable; // -- File lists std::map<std::string, SourceJob> HeaderJobs; std::map<std::string, SourceJob> SourceJobs; @@ -240,9 +190,6 @@ private: std::vector<std::string> UicSearchPaths; cmsys::RegularExpression UicRegExpInclude; std::vector<std::unique_ptr<UicJob>> UicJobs; - // -- Rcc - bool RccSettingsChanged; - std::vector<RccJob> RccJobs; }; #endif diff --git a/Source/cmQtAutoGeneratorRcc.cxx b/Source/cmQtAutoGeneratorRcc.cxx new file mode 100644 index 0000000..3c9f1a8 --- /dev/null +++ b/Source/cmQtAutoGeneratorRcc.cxx @@ -0,0 +1,425 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmQtAutoGen.h" +#include "cmQtAutoGeneratorRcc.h" + +#include "cmAlgorithms.h" +#include "cmCryptoHash.h" +#include "cmMakefile.h" +#include "cmOutputConverter.h" +#include "cmSystemTools.h" + +// -- Static variables + +static const char* SettingsKeyRcc = "ARCC_SETTINGS_HASH"; + +// -- Class methods + +cmQtAutoGeneratorRcc::cmQtAutoGeneratorRcc() + : MultiConfig(cmQtAutoGen::WRAP) + , SettingsChanged(false) +{ +} + +bool cmQtAutoGeneratorRcc::InfoFileRead(cmMakefile* makefile) +{ + // Utility lambdas + auto InfoGet = [makefile](const char* key) { + return makefile->GetSafeDefinition(key); + }; + auto InfoGetList = [makefile](const char* key) -> std::vector<std::string> { + std::vector<std::string> list; + cmSystemTools::ExpandListArgument(makefile->GetSafeDefinition(key), list); + return list; + }; + auto InfoGetConfig = [makefile, this](const char* key) -> std::string { + const char* valueConf = nullptr; + { + std::string keyConf = key; + keyConf += '_'; + keyConf += this->GetInfoConfig(); + valueConf = makefile->GetDefinition(keyConf); + } + if (valueConf == nullptr) { + valueConf = makefile->GetSafeDefinition(key); + } + return std::string(valueConf); + }; + auto InfoGetConfigList = + [&InfoGetConfig](const char* key) -> std::vector<std::string> { + std::vector<std::string> list; + cmSystemTools::ExpandListArgument(InfoGetConfig(key), list); + return list; + }; + + // -- Read info file + if (!makefile->ReadListFile(this->GetInfoFile().c_str())) { + this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(), + "File processing failed"); + return false; + } + + // -- Meta + this->MultiConfig = + cmQtAutoGen::MultiConfigType(InfoGet("ARCC_MULTI_CONFIG")); + this->ConfigSuffix = InfoGetConfig("ARCC_CONFIG_SUFFIX"); + if (this->ConfigSuffix.empty()) { + this->ConfigSuffix = "_"; + this->ConfigSuffix += this->GetInfoConfig(); + } + + this->SettingsFile = InfoGetConfig("ARCC_SETTINGS_FILE"); + + // - Files and directories + this->ProjectSourceDir = InfoGet("ARCC_CMAKE_SOURCE_DIR"); + this->ProjectBinaryDir = InfoGet("ARCC_CMAKE_BINARY_DIR"); + this->CurrentSourceDir = InfoGet("ARCC_CMAKE_CURRENT_SOURCE_DIR"); + this->CurrentBinaryDir = InfoGet("ARCC_CMAKE_CURRENT_BINARY_DIR"); + this->AutogenBuildDir = InfoGet("ARCC_BUILD_DIR"); + + // - Qt environment + this->RccExecutable = InfoGet("ARCC_RCC_EXECUTABLE"); + this->RccListOptions = InfoGetList("ARCC_RCC_LIST_OPTIONS"); + + // - Job + this->QrcFile = InfoGet("ARCC_SOURCE"); + this->RccFile = InfoGet("ARCC_OUTPUT"); + this->Options = InfoGetConfigList("ARCC_OPTIONS"); + this->Inputs = InfoGetList("ARCC_INPUTS"); + + // - Validity checks + if (this->SettingsFile.empty()) { + this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(), + "Settings file name missing"); + return false; + } + if (this->AutogenBuildDir.empty()) { + this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(), + "Autogen build directory missing"); + return false; + } + if (this->RccExecutable.empty()) { + this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(), + "rcc executable missing"); + return false; + } + if (this->QrcFile.empty()) { + this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(), + "rcc input file missing"); + return false; + } + if (this->RccFile.empty()) { + this->LogFileError(cmQtAutoGen::RCC, this->GetInfoFile(), + "rcc output file missing"); + return false; + } + + // Init derived information + // ------------------------ + + // Init file path checksum generator + this->FilePathChecksum.setupParentDirs( + this->CurrentSourceDir, this->CurrentBinaryDir, this->ProjectSourceDir, + this->ProjectBinaryDir); + + return true; +} + +void cmQtAutoGeneratorRcc::SettingsFileRead(cmMakefile* makefile) +{ + // Compose current settings strings + { + cmCryptoHash crypt(cmCryptoHash::AlgoSHA256); + std::string const sep(" ~~~ "); + { + std::string str; + str += this->RccExecutable; + str += sep; + str += cmJoin(this->RccListOptions, ";"); + str += sep; + str += this->QrcFile; + str += sep; + str += this->RccFile; + str += sep; + str += cmJoin(this->Options, ";"); + str += sep; + str += cmJoin(this->Inputs, ";"); + str += sep; + this->SettingsString = crypt.HashString(str); + } + } + + // Read old settings + if (makefile->ReadListFile(this->SettingsFile.c_str())) { + { + auto SMatch = [makefile](const char* key, std::string const& value) { + return (value == makefile->GetSafeDefinition(key)); + }; + if (!SMatch(SettingsKeyRcc, this->SettingsString)) { + this->SettingsChanged = true; + } + } + // In case any setting changed remove the old settings file. + // This triggers a full rebuild on the next run if the current + // build is aborted before writing the current settings in the end. + if (this->SettingsChanged) { + cmSystemTools::RemoveFile(this->SettingsFile); + } + } else { + // If the file could not be read re-generate everythiung. + this->SettingsChanged = true; + } +} + +bool cmQtAutoGeneratorRcc::SettingsFileWrite() +{ + bool success = true; + // Only write if any setting changed + if (this->SettingsChanged) { + if (this->GetVerbose()) { + this->LogInfo(cmQtAutoGen::RCC, "Writing settings file " + + cmQtAutoGen::Quoted(this->SettingsFile)); + } + // Compose settings file content + std::string settings; + { + auto SettingAppend = [&settings](const char* key, + std::string const& value) { + settings += "set("; + settings += key; + settings += " "; + settings += cmOutputConverter::EscapeForCMake(value); + settings += ")\n"; + }; + SettingAppend(SettingsKeyRcc, this->SettingsString); + } + // Write settings file + if (!this->FileWrite(cmQtAutoGen::RCC, this->SettingsFile, settings)) { + this->LogFileError(cmQtAutoGen::RCC, this->SettingsFile, + "Settings file writing failed"); + // Remove old settings file to trigger a full rebuild on the next run + cmSystemTools::RemoveFile(this->SettingsFile); + success = false; + } + } + return success; +} + +bool cmQtAutoGeneratorRcc::Process(cmMakefile* makefile) +{ + // Read info file + if (!this->InfoFileRead(makefile)) { + return false; + } + // Read latest settings + this->SettingsFileRead(makefile); + // Generate rcc file + if (!this->RccGenerate()) { + return false; + } + // Write latest settings + if (!this->SettingsFileWrite()) { + return false; + } + return true; +} + +/** + * @return True on success + */ +bool cmQtAutoGeneratorRcc::RccGenerate() +{ + bool success = true; + bool rccGenerated = false; + + std::string rccFileAbs; + { + std::string suffix; + switch (this->MultiConfig) { + case cmQtAutoGen::SINGLE: + break; + case cmQtAutoGen::WRAP: + suffix = "_CMAKE"; + suffix += this->ConfigSuffix; + suffix += "_"; + break; + case cmQtAutoGen::FULL: + suffix = this->ConfigSuffix; + break; + } + rccFileAbs = cmQtAutoGen::AppendFilenameSuffix(this->RccFile, suffix); + } + std::string const rccFileRel = cmSystemTools::RelativePath( + this->AutogenBuildDir.c_str(), rccFileAbs.c_str()); + + // Check if regeneration is required + bool generate = false; + std::string generateReason; + if (!cmSystemTools::FileExists(this->QrcFile)) { + { + std::string error = "Could not find the file\n "; + error += cmQtAutoGen::Quoted(this->QrcFile); + this->LogError(cmQtAutoGen::RCC, error); + } + success = false; + } + if (success && !generate && !cmSystemTools::FileExists(rccFileAbs.c_str())) { + if (this->GetVerbose()) { + generateReason = "Generating "; + generateReason += cmQtAutoGen::Quoted(rccFileAbs); + generateReason += " from its source file "; + generateReason += cmQtAutoGen::Quoted(this->QrcFile); + generateReason += " because it doesn't exist"; + } + generate = true; + } + if (success && !generate && this->SettingsChanged) { + if (this->GetVerbose()) { + generateReason = "Generating "; + generateReason += cmQtAutoGen::Quoted(rccFileAbs); + generateReason += " from "; + generateReason += cmQtAutoGen::Quoted(this->QrcFile); + generateReason += " because the RCC settings changed"; + } + generate = true; + } + if (success && !generate) { + std::string error; + if (FileIsOlderThan(rccFileAbs, this->QrcFile, &error)) { + if (this->GetVerbose()) { + generateReason = "Generating "; + generateReason += cmQtAutoGen::Quoted(rccFileAbs); + generateReason += " because it is older than "; + generateReason += cmQtAutoGen::Quoted(this->QrcFile); + } + generate = true; + } else { + if (!error.empty()) { + this->LogError(cmQtAutoGen::RCC, error); + success = false; + } + } + } + if (success && !generate) { + // Acquire input file list + std::vector<std::string> readFiles; + std::vector<std::string> const* files = nullptr; + if (!this->Inputs.empty()) { + files = &this->Inputs; + } else { + // Read input file list from qrc file + std::string error; + if (cmQtAutoGen::RccListInputs(this->RccExecutable, this->RccListOptions, + this->QrcFile, readFiles, &error)) { + files = &readFiles; + } else { + this->LogFileError(cmQtAutoGen::RCC, this->QrcFile, error); + success = false; + } + } + // Test if any input file is newer than the build file + if (files != nullptr) { + std::string error; + for (std::string const& resFile : *files) { + if (!cmSystemTools::FileExists(resFile.c_str())) { + error = "Could not find the file\n "; + error += cmQtAutoGen::Quoted(resFile); + error += "\nwhich is listed in\n "; + error += cmQtAutoGen::Quoted(this->QrcFile); + break; + } + if (FileIsOlderThan(rccFileAbs, resFile, &error)) { + if (this->GetVerbose()) { + generateReason = "Generating "; + generateReason += cmQtAutoGen::Quoted(rccFileAbs); + generateReason += " from "; + generateReason += cmQtAutoGen::Quoted(this->QrcFile); + generateReason += " because it is older than "; + generateReason += cmQtAutoGen::Quoted(resFile); + } + generate = true; + break; + } + if (!error.empty()) { + break; + } + } + // Print error + if (!error.empty()) { + this->LogError(cmQtAutoGen::RCC, error); + success = false; + } + } + } + // Regenerate on demand + if (generate) { + // Log + if (this->GetVerbose()) { + this->LogBold("Generating RCC source " + rccFileRel); + this->LogInfo(cmQtAutoGen::RCC, generateReason); + } + + // Make sure the parent directory exists + if (this->MakeParentDirectory(cmQtAutoGen::RCC, rccFileAbs)) { + // Compose rcc command + std::vector<std::string> cmd; + cmd.push_back(this->RccExecutable); + cmd.insert(cmd.end(), this->Options.begin(), this->Options.end()); + cmd.push_back("-o"); + cmd.push_back(rccFileAbs); + cmd.push_back(this->QrcFile); + + std::string output; + if (this->RunCommand(cmd, output)) { + // Success + rccGenerated = true; + } else { + { + std::string emsg = "rcc failed for\n "; + emsg += cmQtAutoGen::Quoted(this->QrcFile); + this->LogCommandError(cmQtAutoGen::RCC, emsg, cmd, output); + } + cmSystemTools::RemoveFile(rccFileAbs); + success = false; + } + } else { + // Parent directory creation failed + success = false; + } + } + + // Generate a wrapper source file on demand + if (success && (this->MultiConfig == cmQtAutoGen::WRAP)) { + // Wrapper file name + std::string const& wrapperFileAbs = this->RccFile; + std::string const wrapperFileRel = cmSystemTools::RelativePath( + this->AutogenBuildDir.c_str(), wrapperFileAbs.c_str()); + // Wrapper file content + std::string content = "// This is an autogenerated configuration " + "wrapper file. Changes will be overwritten.\n" + "#include \""; + content += cmSystemTools::GetFilenameName(rccFileRel); + content += "\"\n"; + // Write content to file + if (this->FileDiffers(wrapperFileAbs, content)) { + // Write new wrapper file + if (this->GetVerbose()) { + this->LogBold("Generating RCC wrapper " + wrapperFileRel); + } + if (!this->FileWrite(cmQtAutoGen::RCC, wrapperFileAbs, content)) { + this->LogFileError(cmQtAutoGen::RCC, wrapperFileAbs, + "rcc wrapper file writing failed"); + success = false; + } + } else if (rccGenerated) { + // Just touch the wrapper file + if (this->GetVerbose()) { + this->LogInfo(cmQtAutoGen::RCC, + "Touching RCC wrapper " + wrapperFileRel); + } + cmSystemTools::Touch(wrapperFileAbs, false); + } + } + + return success; +} diff --git a/Source/cmQtAutoGeneratorRcc.h b/Source/cmQtAutoGeneratorRcc.h new file mode 100644 index 0000000..0e3f690 --- /dev/null +++ b/Source/cmQtAutoGeneratorRcc.h @@ -0,0 +1,56 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#ifndef cmQtAutoGeneratorRcc_h +#define cmQtAutoGeneratorRcc_h + +#include "cmConfigure.h" // IWYU pragma: keep + +#include "cmFilePathChecksum.h" +#include "cmQtAutoGen.h" +#include "cmQtAutoGenerator.h" + +#include <string> +#include <vector> + +class cmMakefile; + +class cmQtAutoGeneratorRcc : public cmQtAutoGenerator +{ + CM_DISABLE_COPY(cmQtAutoGeneratorRcc) +public: + cmQtAutoGeneratorRcc(); + +private: + // -- Initialization & settings + bool InfoFileRead(cmMakefile* makefile); + void SettingsFileRead(cmMakefile* makefile); + bool SettingsFileWrite(); + // -- Central processing + bool Process(cmMakefile* makefile) override; + bool RccGenerate(); + + // -- Config settings + std::string ConfigSuffix; + cmQtAutoGen::MultiConfig MultiConfig; + // -- Settings + bool SettingsChanged; + std::string SettingsFile; + std::string SettingsString; + // -- Directories + std::string ProjectSourceDir; + std::string ProjectBinaryDir; + std::string CurrentSourceDir; + std::string CurrentBinaryDir; + std::string AutogenBuildDir; + cmFilePathChecksum FilePathChecksum; + // -- Qt environment + std::string RccExecutable; + std::vector<std::string> RccListOptions; + // -- Job + std::string QrcFile; + std::string RccFile; + std::vector<std::string> Options; + std::vector<std::string> Inputs; +}; + +#endif diff --git a/Source/cmServerDictionary.h b/Source/cmServerDictionary.h index 040c1fd..62dee11 100644 --- a/Source/cmServerDictionary.h +++ b/Source/cmServerDictionary.h @@ -91,10 +91,11 @@ static const std::string kWATCHED_DIRECTORIES_KEY = "watchedDirectories"; static const std::string kWATCHED_FILES_KEY = "watchedFiles"; static const std::string kHAS_INSTALL_RULE = "hasInstallRule"; static const std::string kINSTALL_PATHS = "installPaths"; -static const std::string kHAS_ENABLED_TESTS = "hasEnabledTests"; static const std::string kCTEST_NAME = "ctestName"; static const std::string kCTEST_COMMAND = "ctestCommand"; static const std::string kCTEST_INFO = "ctestInfo"; +static const std::string kMINIMUM_CMAKE_VERSION = "minimumCMakeVersion"; +static const std::string kIS_GENERATOR_PROVIDED_KEY = "isGeneratorProvided"; static const std::string kTARGET_CROSS_REFERENCES_KEY = "crossReferences"; static const std::string kLINE_NUMBER_KEY = "line"; diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx index 0cb906b..cfac513 100644 --- a/Source/cmServerProtocol.cxx +++ b/Source/cmServerProtocol.cxx @@ -771,10 +771,10 @@ static void DumpBacktraceRange(Json::Value& result, const std::string& type, } } -static Json::Value DumpCTestInfo(const std::string& name, cmTest* testInfo) +static Json::Value DumpCTestInfo(cmTest* testInfo) { Json::Value result = Json::objectValue; - result[kCTEST_NAME] = name; + result[kCTEST_NAME] = testInfo->GetName(); // Concat command entries together. After the first should be the arguments // for the command @@ -801,76 +801,17 @@ static Json::Value DumpCTestInfo(const std::string& name, cmTest* testInfo) return result; } -static Json::Value DumpCTestTarget(cmGeneratorTarget* target, - const std::string& config) +static void DumpMakefileTests(cmMakefile* mf, const std::string& config, + Json::Value* result) { - cmLocalGenerator* lg = target->GetLocalGenerator(); - const cmState* state = lg->GetState(); - - const cmStateEnums::TargetType type = target->GetType(); - const std::string typeName = state->GetTargetTypeName(type); - - Json::Value ttl = Json::arrayValue; - ttl.append("EXECUTABLE"); - ttl.append("STATIC_LIBRARY"); - ttl.append("SHARED_LIBRARY"); - ttl.append("MODULE_LIBRARY"); - ttl.append("OBJECT_LIBRARY"); - ttl.append("UTILITY"); - ttl.append("INTERFACE_LIBRARY"); - - if (!hasString(ttl, typeName) || target->IsImported()) { - return Json::Value(); - } - - Json::Value result = Json::objectValue; - result[kNAME_KEY] = target->GetName(); - result[kTYPE_KEY] = typeName; - - if (type == cmStateEnums::INTERFACE_LIBRARY) { - return result; - } - result[kFULL_NAME_KEY] = target->GetFullName(config); - - if (target->Makefile->IsOn("CMAKE_TESTING_ENABLED")) { - result[kHAS_ENABLED_TESTS] = true; - std::vector<std::string> CTestNames; - - Json::Value testInfo = Json::arrayValue; - std::vector<std::string> testNames; - target->Makefile->GetTestNames(testNames); - for (auto& name : testNames) { - auto test = target->Makefile->GetTest(name); - if (test != nullptr) { - testInfo.append(DumpCTestInfo(name, test)); - } - } - result[kCTEST_INFO] = testInfo; - } - - return result; -} - -static Json::Value DumpCTestTargetsList( - const std::vector<cmLocalGenerator*>& generators, const std::string& config) -{ - Json::Value result = Json::arrayValue; - - std::vector<cmGeneratorTarget*> targetList; - for (const auto& lgIt : generators) { - auto list = lgIt->GetGeneratorTargets(); - targetList.insert(targetList.end(), list.begin(), list.end()); - } - std::sort(targetList.begin(), targetList.end()); - - for (cmGeneratorTarget* target : targetList) { - Json::Value tmp = DumpCTestTarget(target, config); + std::vector<cmTest*> tests; + mf->GetTests(config, tests); + for (auto test : tests) { + Json::Value tmp = DumpCTestInfo(test); if (!tmp.isNull()) { - result.append(tmp); + result->append(tmp); } } - - return result; } static Json::Value DumpCTestProjectList(const cmake* cm, @@ -884,11 +825,17 @@ static Json::Value DumpCTestProjectList(const cmake* cm, Json::Value pObj = Json::objectValue; pObj[kNAME_KEY] = projectIt.first; - // All Projects must have at least one local generator - assert(!projectIt.second.empty()); + Json::Value tests = Json::arrayValue; - // Project structure information: - pObj[kTARGETS_KEY] = DumpCTestTargetsList(projectIt.second, config); + // Gather tests for every generator + for (const auto& lg : projectIt.second) { + // Make sure they're generated. + lg->GenerateTestFiles(); + cmMakefile* mf = lg->GetMakefile(); + DumpMakefileTests(mf, config, &tests); + } + + pObj[kCTEST_INFO] = tests; result.append(pObj); } @@ -942,6 +889,8 @@ static Json::Value DumpTarget(cmGeneratorTarget* target, Json::Value result = Json::objectValue; result[kNAME_KEY] = target->GetName(); + result[kIS_GENERATOR_PROVIDED_KEY] = + target->Target->GetIsGeneratorProvided(); result[kTYPE_KEY] = typeName; result[kSOURCE_DIRECTORY_KEY] = lg->GetCurrentSourceDirectory(); result[kBUILD_DIRECTORY_KEY] = lg->GetCurrentBinaryDirectory(); @@ -1116,11 +1065,26 @@ static Json::Value DumpProjectList(const cmake* cm, std::string const& config) // Project structure information: const cmMakefile* mf = lg->GetMakefile(); - pObj[kHAS_INSTALL_RULE] = mf->GetInstallGenerators().empty() == false; + pObj[kMINIMUM_CMAKE_VERSION] = + mf->GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION"); pObj[kSOURCE_DIRECTORY_KEY] = mf->GetCurrentSourceDirectory(); pObj[kBUILD_DIRECTORY_KEY] = mf->GetCurrentBinaryDirectory(); pObj[kTARGETS_KEY] = DumpTargetsList(projectIt.second, config); + // For a project-level install rule it might be defined in any of its + // associated generators. + bool hasInstallRule = false; + for (const auto generator : projectIt.second) { + hasInstallRule = + generator->GetMakefile()->GetInstallGenerators().empty() == false; + + if (hasInstallRule) { + break; + } + } + + pObj[kHAS_INSTALL_RULE] = hasInstallRule; + result.append(pObj); } diff --git a/Source/cmSourceFileLocation.cxx b/Source/cmSourceFileLocation.cxx index 4f337f2..6add7b3 100644 --- a/Source/cmSourceFileLocation.cxx +++ b/Source/cmSourceFileLocation.cxx @@ -8,9 +8,7 @@ #include "cmSystemTools.h" #include "cmake.h" -#include <algorithm> #include <assert.h> -#include <vector> cmSourceFileLocation::cmSourceFileLocation() : Makefile(nullptr) @@ -86,13 +84,9 @@ void cmSourceFileLocation::UpdateExtension(const std::string& name) // The global generator checks extensions of enabled languages. cmGlobalGenerator* gg = this->Makefile->GetGlobalGenerator(); cmMakefile const* mf = this->Makefile; - const std::vector<std::string>& srcExts = - mf->GetCMakeInstance()->GetSourceExtensions(); - const std::vector<std::string>& hdrExts = - mf->GetCMakeInstance()->GetHeaderExtensions(); + auto cm = mf->GetCMakeInstance(); if (!gg->GetLanguageFromExtension(ext.c_str()).empty() || - std::find(srcExts.begin(), srcExts.end(), ext) != srcExts.end() || - std::find(hdrExts.begin(), hdrExts.end(), ext) != hdrExts.end()) { + cm->IsSourceExtension(ext) || cm->IsHeaderExtension(ext)) { // This is a known extension. Use the given filename with extension. this->Name = cmSystemTools::GetFilenameName(name); this->AmbiguousExtension = false; @@ -149,14 +143,8 @@ bool cmSourceFileLocation::MatchesAmbiguousExtension( // disk. One of these must match if loc refers to this source file. std::string const& ext = this->Name.substr(loc.Name.size() + 1); cmMakefile const* mf = this->Makefile; - const std::vector<std::string>& srcExts = - mf->GetCMakeInstance()->GetSourceExtensions(); - if (std::find(srcExts.begin(), srcExts.end(), ext) != srcExts.end()) { - return true; - } - std::vector<std::string> hdrExts = - mf->GetCMakeInstance()->GetHeaderExtensions(); - return std::find(hdrExts.begin(), hdrExts.end(), ext) != hdrExts.end(); + auto cm = mf->GetCMakeInstance(); + return cm->IsSourceExtension(ext) || cm->IsHeaderExtension(ext); } bool cmSourceFileLocation::Matches(cmSourceFileLocation const& loc) diff --git a/Source/cmSourceGroup.cxx b/Source/cmSourceGroup.cxx index fba4c31..18bcb49 100644 --- a/Source/cmSourceGroup.cxx +++ b/Source/cmSourceGroup.cxx @@ -60,14 +60,14 @@ void cmSourceGroup::AddGroupFile(const std::string& name) this->GroupFiles.insert(name); } -const char* cmSourceGroup::GetName() const +std::string const& cmSourceGroup::GetName() const { - return this->Name.c_str(); + return this->Name; } -const char* cmSourceGroup::GetFullName() const +std::string const& cmSourceGroup::GetFullName() const { - return this->FullName.c_str(); + return this->FullName; } bool cmSourceGroup::MatchesRegex(const char* name) @@ -105,7 +105,7 @@ cmSourceGroup* cmSourceGroup::LookupChild(const char* name) const // st for (; iter != end; ++iter) { - std::string sgName = iter->GetName(); + std::string const& sgName = iter->GetName(); // look if descenened is the one were looking for if (sgName == name) { diff --git a/Source/cmSourceGroup.h b/Source/cmSourceGroup.h index e8bd697..7c7c35f 100644 --- a/Source/cmSourceGroup.h +++ b/Source/cmSourceGroup.h @@ -55,12 +55,12 @@ public: /** * Get the name of this group. */ - const char* GetName() const; + std::string const& GetName() const; /** * Get the full path name for group. */ - const char* GetFullName() const; + std::string const& GetFullName() const; /** * Check if the given name matches this group's regex. diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index c6cd502..de23b08 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -176,6 +176,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, Visibility vis, cmMakefile* mf) { assert(mf); + this->IsGeneratorProvided = false; this->Name = name; this->TargetTypeValue = type; this->Makefile = mf; @@ -238,6 +239,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, this->SetPropertyDefault("COMPILE_PDB_OUTPUT_DIRECTORY", nullptr); this->SetPropertyDefault("Fortran_FORMAT", nullptr); this->SetPropertyDefault("Fortran_MODULE_DIRECTORY", nullptr); + this->SetPropertyDefault("Fortran_COMPILER_LAUNCHER", nullptr); this->SetPropertyDefault("GNUtoMS", nullptr); this->SetPropertyDefault("OSX_ARCHITECTURES", nullptr); this->SetPropertyDefault("IOS_INSTALL_COMBINED", nullptr); @@ -279,6 +281,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, this->SetPropertyDefault("CUDA_STANDARD_REQUIRED", nullptr); this->SetPropertyDefault("CUDA_EXTENSIONS", nullptr); this->SetPropertyDefault("CUDA_COMPILER_LAUNCHER", nullptr); + this->SetPropertyDefault("CUDA_SEPARABLE_COMPILATION", nullptr); this->SetPropertyDefault("LINK_SEARCH_START_STATIC", nullptr); this->SetPropertyDefault("LINK_SEARCH_END_STATIC", nullptr); } @@ -884,6 +887,13 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); return; } + if (prop == "IMPORTED_GLOBAL" && !this->IsImported()) { + std::ostringstream e; + e << "IMPORTED_GLOBAL property can't be set on non-imported targets (\"" + << this->Name << "\")\n"; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + return; + } if (prop == "INCLUDE_DIRECTORIES") { this->Internal->IncludeDirectoriesEntries.clear(); @@ -933,6 +943,19 @@ void cmTarget::SetProperty(const std::string& prop, const char* value) this->Internal->SourceEntries.push_back(value); this->Internal->SourceBacktraces.push_back(lfbt); } + } else if (prop == "IMPORTED_GLOBAL") { + if (!cmSystemTools::IsOn(value)) { + std::ostringstream e; + e << "IMPORTED_GLOBAL property can't be set to FALSE on targets (\"" + << this->Name << "\")\n"; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + return; + } + /* no need to change anything if value does not change */ + if (!this->ImportedGloballyVisible) { + this->ImportedGloballyVisible = true; + this->GetGlobalGenerator()->IndexTarget(this); + } } else if (cmHasLiteralPrefix(prop, "IMPORTED_LIBNAME") && !this->CheckImportedLibName(prop, value ? value : "")) { /* error was reported by check method */ @@ -977,6 +1000,14 @@ void cmTarget::AppendProperty(const std::string& prop, const char* value, this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); return; } + if (prop == "IMPORTED_GLOBAL") { + std::ostringstream e; + e << "IMPORTED_GLOBAL property can't be appended, only set on imported " + "targets (\"" + << this->Name << "\")\n"; + this->Makefile->IssueMessage(cmake::FATAL_ERROR, e.str()); + return; + } if (prop == "INCLUDE_DIRECTORIES") { if (value && *value) { this->Internal->IncludeDirectoriesEntries.push_back(value); @@ -1143,6 +1174,21 @@ static void cmTargetCheckINTERFACE_LINK_LIBRARIES(const char* value, context->IssueMessage(cmake::FATAL_ERROR, e.str()); } +static void cmTargetCheckIMPORTED_GLOBAL(const cmTarget* target, + cmMakefile* context) +{ + std::vector<cmTarget*> targets = context->GetOwnedImportedTargets(); + std::vector<cmTarget*>::const_iterator it = + std::find(targets.begin(), targets.end(), target); + if (it == targets.end()) { + std::ostringstream e; + e << "Attempt to promote imported target \"" << target->GetName() + << "\" to global scope (by setting IMPORTED_GLOBAL) " + "which is not built in this directory."; + context->IssueMessage(cmake::FATAL_ERROR, e.str()); + } +} + void cmTarget::CheckProperty(const std::string& prop, cmMakefile* context) const { @@ -1157,11 +1203,16 @@ void cmTarget::CheckProperty(const std::string& prop, cmTargetCheckLINK_INTERFACE_LIBRARIES(prop, value, context, true); } } - if (cmHasLiteralPrefix(prop, "INTERFACE_LINK_LIBRARIES")) { + if (prop == "INTERFACE_LINK_LIBRARIES") { if (const char* value = this->GetProperty(prop)) { cmTargetCheckINTERFACE_LINK_LIBRARIES(value, context); } } + if (prop == "IMPORTED_GLOBAL") { + if (this->IsImported()) { + cmTargetCheckIMPORTED_GLOBAL(this, context); + } + } } const char* cmTarget::GetComputedProperty( @@ -1182,6 +1233,7 @@ const char* cmTarget::GetProperty(const std::string& prop) const MAKE_STATIC_PROP(COMPILE_OPTIONS); MAKE_STATIC_PROP(COMPILE_DEFINITIONS); MAKE_STATIC_PROP(IMPORTED); + MAKE_STATIC_PROP(IMPORTED_GLOBAL); MAKE_STATIC_PROP(MANUALLY_ADDED_DEPENDENCIES); MAKE_STATIC_PROP(NAME); MAKE_STATIC_PROP(BINARY_DIR); @@ -1196,6 +1248,7 @@ const char* cmTarget::GetProperty(const std::string& prop) const specialProps.insert(propCOMPILE_OPTIONS); specialProps.insert(propCOMPILE_DEFINITIONS); specialProps.insert(propIMPORTED); + specialProps.insert(propIMPORTED_GLOBAL); specialProps.insert(propMANUALLY_ADDED_DEPENDENCIES); specialProps.insert(propNAME); specialProps.insert(propBINARY_DIR); @@ -1264,6 +1317,9 @@ const char* cmTarget::GetProperty(const std::string& prop) const if (prop == propIMPORTED) { return this->IsImported() ? "TRUE" : "FALSE"; } + if (prop == propIMPORTED_GLOBAL) { + return this->IsImportedGloballyVisible() ? "TRUE" : "FALSE"; + } if (prop == propNAME) { return this->GetName().c_str(); } diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 940e26c..56f3e3a 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -180,6 +180,12 @@ public: bool GetHaveInstallRule() const { return this->HaveInstallRule; } void SetHaveInstallRule(bool h) { this->HaveInstallRule = h; } + /** + * Get/Set whether this target was auto-created by a generator. + */ + bool GetIsGeneratorProvided() const { return this->IsGeneratorProvided; } + void SetIsGeneratorProvided(bool igp) { this->IsGeneratorProvided = igp; } + /** Add a utility on which this project depends. A utility is an executable * name as would be specified to the ADD_EXECUTABLE or UTILITY_SOURCE * commands. It is not a full path nor does it have an extension. @@ -284,6 +290,7 @@ private: std::string const& value) const; private: + bool IsGeneratorProvided; cmPropertyMap Properties; std::set<std::string> SystemIncludeDirectories; std::set<std::string> LinkDirectoriesEmmitted; diff --git a/Source/cmTargetPropertyComputer.cxx b/Source/cmTargetPropertyComputer.cxx index 1d2520d..ed9026e 100644 --- a/Source/cmTargetPropertyComputer.cxx +++ b/Source/cmTargetPropertyComputer.cxx @@ -57,6 +57,7 @@ bool cmTargetPropertyComputer::WhiteListedInterfaceProperty( builtIns.insert("COMPATIBLE_INTERFACE_STRING"); builtIns.insert("EXPORT_NAME"); builtIns.insert("IMPORTED"); + builtIns.insert("IMPORTED_GLOBAL"); builtIns.insert("NAME"); builtIns.insert("TYPE"); } diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx index 78ca6bc..b548359 100644 --- a/Source/cmTestGenerator.cxx +++ b/Source/cmTestGenerator.cxx @@ -34,6 +34,16 @@ void cmTestGenerator::Compute(cmLocalGenerator* lg) this->LG = lg; } +bool cmTestGenerator::TestsForConfig(const std::string& config) +{ + return this->GeneratesForConfig(config); +} + +cmTest* cmTestGenerator::GetTest() const +{ + return this->Test; +} + void cmTestGenerator::GenerateScriptConfigs(std::ostream& os, Indent indent) { // Create the tests. diff --git a/Source/cmTestGenerator.h b/Source/cmTestGenerator.h index 1ca61c2..73d05a3 100644 --- a/Source/cmTestGenerator.h +++ b/Source/cmTestGenerator.h @@ -30,6 +30,11 @@ public: void Compute(cmLocalGenerator* lg); + /** Test if this generator installs the test for a given configuration. */ + bool TestsForConfig(const std::string& config); + + cmTest* GetTest() const; + protected: void GenerateScriptConfigs(std::ostream& os, Indent indent) override; void GenerateScriptActions(std::ostream& os, Indent indent) override; diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 1aadf67..caeeeb9 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -1469,11 +1469,14 @@ void cmVisualStudio10TargetGenerator::WriteGroups() } this->WriteString("<ItemGroup>\n", 1); - for (std::set<cmSourceGroup*>::iterator g = groupsUsed.begin(); - g != groupsUsed.end(); ++g) { - cmSourceGroup* sg = *g; - const char* name = sg->GetFullName(); - if (strlen(name) != 0) { + std::vector<cmSourceGroup*> groupsVec(groupsUsed.begin(), groupsUsed.end()); + std::sort(groupsVec.begin(), groupsVec.end(), + [](cmSourceGroup* l, cmSourceGroup* r) { + return l->GetFullName() < r->GetFullName(); + }); + for (cmSourceGroup* sg : groupsVec) { + std::string const& name = sg->GetFullName(); + if (!name.empty()) { this->WriteString("<Filter Include=\"", 2); (*this->BuildFileStream) << name << "\">\n"; std::string guidName = "SG_Filter_"; @@ -1558,12 +1561,12 @@ void cmVisualStudio10TargetGenerator::WriteGroupSources( std::string const& source = sf->GetFullPath(); cmSourceGroup* sourceGroup = this->Makefile->FindSourceGroup(source.c_str(), sourceGroups); - const char* filter = sourceGroup->GetFullName(); + std::string const& filter = sourceGroup->GetFullName(); this->WriteString("<", 2); std::string path = this->ConvertPath(source, s->RelativePath); this->ConvertToWindowsSlash(path); (*this->BuildFileStream) << name << " Include=\"" << cmVS10EscapeXML(path); - if (strlen(filter)) { + if (!filter.empty()) { (*this->BuildFileStream) << "\">\n"; this->WriteString("<Filter>", 3); (*this->BuildFileStream) << filter << "</Filter>\n"; @@ -1689,12 +1692,8 @@ void cmVisualStudio10TargetGenerator::WriteExtraSource(cmSourceFile const* sf) } else if (ext == "natvis") { tool = "Natvis"; } else if (ext == "settings") { - // remove path to current source dir (if files are in current source dir) - if (!sourceLink.empty()) { - settingsLastGenOutput = sourceLink; - } else { - settingsLastGenOutput = sf->GetFullPath(); - } + settingsLastGenOutput = + cmsys::SystemTools::GetFilenameName(sf->GetFullPath()); std::size_t pos = settingsLastGenOutput.find(".settings"); settingsLastGenOutput.replace(pos, 9, ".Designer.cs"); settingsGenerator = "SettingsSingleFileGenerator"; diff --git a/Source/cmXCodeObject.cxx b/Source/cmXCodeObject.cxx index e54f1f3..1747c9c 100644 --- a/Source/cmXCodeObject.cxx +++ b/Source/cmXCodeObject.cxx @@ -115,16 +115,15 @@ void cmXCodeObject::Print(std::ostream& out) if (separator == "\n") { out << separator; } - std::map<std::string, cmXCodeObject*>::iterator i; cmXCodeObject::Indent(3 * indentFactor, out); out << "isa = " << PBXTypeNames[this->IsA] << ";" << separator; - for (i = this->ObjectAttributes.begin(); i != this->ObjectAttributes.end(); - ++i) { - if (i->first == "isa") { + for (const auto& keyVal : this->ObjectAttributes) { + if (keyVal.first == "isa") { continue; } - PrintAttribute(out, 3, separator, indentFactor, i->first, i->second, this); + PrintAttribute(out, 3, separator, indentFactor, keyVal.first, + keyVal.second, this); } cmXCodeObject::Indent(2 * indentFactor, out); out << "};\n"; @@ -167,11 +166,9 @@ void cmXCodeObject::PrintAttribute(std::ostream& out, int level, if (separator == "\n") { out << separator; } - std::map<std::string, cmXCodeObject*>::const_iterator i; - for (i = object->ObjectAttributes.begin(); - i != object->ObjectAttributes.end(); ++i) { - PrintAttribute(out, (level + 1) * factor, separator, factor, i->first, - i->second, object); + for (const auto& keyVal : object->ObjectAttributes) { + PrintAttribute(out, (level + 1) * factor, separator, factor, + keyVal.first, keyVal.second, object); } cmXCodeObject::Indent(level * factor, out); out << "};" << separator; @@ -221,7 +218,7 @@ void cmXCodeObject::CopyAttributes(cmXCodeObject* copy) this->Object = copy->Object; } -void cmXCodeObject::PrintString(std::ostream& os, std::string String) +void cmXCodeObject::PrintString(std::ostream& os, const std::string& String) { // The string needs to be quoted if it contains any characters // considered special by the Xcode project file parser. @@ -234,13 +231,12 @@ void cmXCodeObject::PrintString(std::ostream& os, std::string String) // Print the string, quoted and escaped as necessary. os << quote; - for (std::string::const_iterator i = String.begin(); i != String.end(); - ++i) { - if (*i == '"' || *i == '\\') { + for (auto c : String) { + if (c == '"' || c == '\\') { // Escape double-quotes and backslashes. os << '\\'; } - os << *i; + os << c; } os << quote; } diff --git a/Source/cmXCodeObject.h b/Source/cmXCodeObject.h index b0f1d31..51e5d36 100644 --- a/Source/cmXCodeObject.h +++ b/Source/cmXCodeObject.h @@ -150,7 +150,7 @@ public: return this->List; } void SetComment(const std::string& c) { this->Comment = c; } - static void PrintString(std::ostream& os, std::string String); + static void PrintString(std::ostream& os, const std::string& String); protected: void PrintString(std::ostream& os) const; diff --git a/Source/cmXMLWriter.h b/Source/cmXMLWriter.h index 981255d..c890acf 100644 --- a/Source/cmXMLWriter.h +++ b/Source/cmXMLWriter.h @@ -7,6 +7,8 @@ #include "cmXMLSafe.h" +#include <chrono> +#include <ctime> #include <ostream> #include <stack> #include <string> @@ -99,6 +101,22 @@ private: return cmXMLSafe(value).Quotes(false); } + /* + * Convert a std::chrono::system::time_point to the number of seconds since + * the UN*X epoch. + * + * It would be tempting to convert a time_point to number of seconds by + * using time_since_epoch(). Unfortunately the C++11 standard does not + * specify what the epoch of the system_clock must be. + * Therefore we must assume it is an arbitary point in time. Instead of this + * method, it is recommended to convert it by means of the to_time_t method. + */ + static std::time_t SafeContent( + std::chrono::system_clock::time_point const& value) + { + return std::chrono::system_clock::to_time_t(value); + } + template <typename T> static T SafeContent(T value) { diff --git a/Source/cmake.cxx b/Source/cmake.cxx index fde77a7..2a5bb6c 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -200,6 +200,11 @@ cmake::cmake(Role role) this->SourceFileExtensions.push_back("M"); this->SourceFileExtensions.push_back("mm"); + std::copy(this->SourceFileExtensions.begin(), + this->SourceFileExtensions.end(), + std::inserter(this->SourceFileExtensionsSet, + this->SourceFileExtensionsSet.end())); + this->HeaderFileExtensions.push_back("h"); this->HeaderFileExtensions.push_back("hh"); this->HeaderFileExtensions.push_back("h++"); @@ -208,6 +213,11 @@ cmake::cmake(Role role) this->HeaderFileExtensions.push_back("hxx"); this->HeaderFileExtensions.push_back("in"); this->HeaderFileExtensions.push_back("txx"); + + std::copy(this->HeaderFileExtensions.begin(), + this->HeaderFileExtensions.end(), + std::inserter(this->HeaderFileExtensionsSet, + this->HeaderFileExtensionsSet.end())); } cmake::~cmake() @@ -1647,6 +1657,21 @@ void cmake::AddCacheEntry(const std::string& key, const char* value, this->UnwatchUnusedCli(key); } +std::string cmake::StripExtension(const std::string& file) const +{ + auto dotpos = file.rfind('.'); + if (dotpos != std::string::npos) { + auto ext = file.substr(dotpos + 1); +#if defined(_WIN32) || defined(__APPLE__) + ext = cmSystemTools::LowerCase(ext); +#endif + if (this->IsSourceExtension(ext) || this->IsHeaderExtension(ext)) { + return file.substr(0, dotpos); + } + } + return file; +} + const char* cmake::GetCacheDefinition(const std::string& name) const { return this->State->GetInitializedCacheValue(name); diff --git a/Source/cmake.h b/Source/cmake.h index 5c5a90d..02c6cdb 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -8,6 +8,7 @@ #include <map> #include <set> #include <string> +#include <unordered_set> #include <vector> #include "cmInstalledFile.h" @@ -225,11 +226,27 @@ public: { return this->SourceFileExtensions; } + + bool IsSourceExtension(const std::string& ext) const + { + return this->SourceFileExtensionsSet.find(ext) != + this->SourceFileExtensionsSet.end(); + } + const std::vector<std::string>& GetHeaderExtensions() const { return this->HeaderFileExtensions; } + bool IsHeaderExtension(const std::string& ext) const + { + return this->HeaderFileExtensionsSet.find(ext) != + this->HeaderFileExtensionsSet.end(); + } + + // Strips the extension (if present and known) from a filename + std::string StripExtension(const std::string& file) const; + /** * Given a variable name, return its value (as a string). */ @@ -486,7 +503,9 @@ private: std::string CheckStampList; std::string VSSolutionFile; std::vector<std::string> SourceFileExtensions; + std::unordered_set<std::string> SourceFileExtensionsSet; std::vector<std::string> HeaderFileExtensions; + std::unordered_set<std::string> HeaderFileExtensionsSet; bool ClearBuildSystem; bool DebugTryCompile; cmFileTimeComparison* FileComparison; diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index ef75b01..3d9f65a 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -6,7 +6,8 @@ #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" #include "cmMakefile.h" -#include "cmQtAutoGenerators.h" +#include "cmQtAutoGeneratorMocUic.h" +#include "cmQtAutoGeneratorRcc.h" #include "cmStateDirectory.h" #include "cmStateSnapshot.h" #include "cmSystemTools.h" @@ -992,11 +993,20 @@ int cmcmd::ExecuteCMakeCommand(std::vector<std::string>& args) } #ifdef CMAKE_BUILD_WITH_CMAKE - if (args[1] == "cmake_autogen" && args.size() >= 4) { - cmQtAutoGenerators autogen; + if ((args[1] == "cmake_autogen") && (args.size() >= 4)) { + cmQtAutoGeneratorMocUic autoGen; + std::string const& infoDir = args[2]; std::string const& config = args[3]; - bool autogenSuccess = autogen.Run(args[2], config); - return autogenSuccess ? 0 : 1; + return autoGen.Run(infoDir, config) ? 0 : 1; + } + if ((args[1] == "cmake_autorcc") && (args.size() >= 3)) { + cmQtAutoGeneratorRcc autoGen; + std::string const& infoFile = args[2]; + std::string config; + if (args.size() > 3) { + config = args[3]; + }; + return autoGen.Run(infoFile, config) ? 0 : 1; } #endif @@ -1577,9 +1587,11 @@ std::ostream& operator<<(std::ostream& stream, stream.flags(flags); return stream; } + static bool RunCommand(const char* comment, std::vector<std::string>& command, bool verbose, NumberFormat exitFormat, - int* retCodeOut = nullptr) + int* retCodeOut = nullptr, + bool (*retCodeOkay)(int) = nullptr) { if (verbose) { std::cout << comment << ":\n"; @@ -1589,18 +1601,17 @@ static bool RunCommand(const char* comment, std::vector<std::string>& command, int retCode = 0; bool commandResult = cmSystemTools::RunSingleCommand( command, &output, &output, &retCode, nullptr, cmSystemTools::OUTPUT_NONE); - bool returnValue; + bool const retCodeSuccess = + retCode == 0 || (retCodeOkay && retCodeOkay(retCode)); + bool const success = commandResult && retCodeSuccess; if (retCodeOut) { - if (!commandResult) { - *retCodeOut = (retCode == 0) ? -1 : retCode; - } else { + if (commandResult || !retCodeSuccess) { *retCodeOut = retCode; + } else { + *retCodeOut = -1; } - returnValue = true; // always return true if retCodeOut is requested - } else { - returnValue = commandResult && (retCode == 0); } - if (!commandResult || retCode) { + if (!success) { std::cout << comment << ": command \"" << cmJoin(command, " ") << "\" failed (exit code " << NumberFormatter(exitFormat, retCode) @@ -1613,7 +1624,7 @@ static bool RunCommand(const char* comment, std::vector<std::string>& command, std::cout << output; } } - return returnValue; + return success; } bool cmVSLink::Parse(std::vector<std::string>::const_iterator argBeg, @@ -1711,6 +1722,13 @@ int cmVSLink::Link() return LinkNonIncremental(); } +static bool mtRetIsUpdate(int mtRet) +{ + // 'mt /notify_update' returns a special value (differing between + // Windows and POSIX hosts) when it updated the manifest file. + return mtRet == 0x41020001 || mtRet == 0xbb; +} + int cmVSLink::LinkIncremental() { // This follows the steps listed here: @@ -1782,9 +1800,9 @@ int cmVSLink::LinkIncremental() // Run the manifest tool to create the final manifest. int mtRet = this->RunMT("/out:" + this->ManifestFile, true); - // If mt returns 1090650113 (or 187 on a posix host) then it updated the - // manifest file so we need to embed it again. Otherwise we are done. - if (mtRet != 1090650113 && mtRet != 187) { + // If mt returns a special value then it updated the manifest file so + // we need to embed it again. Otherwise we are done. + if (!mtRetIsUpdate(mtRet)) { return mtRet; } @@ -1837,7 +1855,8 @@ int cmVSLink::RunMT(std::string const& out, bool notify) mtCommand.push_back("/notify_update"); } int mtRet = 0; - if (!RunCommand("MT", mtCommand, this->Verbose, FORMAT_HEX, &mtRet)) { + if (!RunCommand("MT", mtCommand, this->Verbose, FORMAT_HEX, &mtRet, + mtRetIsUpdate)) { return -1; } return mtRet; diff --git a/Source/ctest.cxx b/Source/ctest.cxx index f6466fa..ad5fec0 100644 --- a/Source/ctest.cxx +++ b/Source/ctest.cxx @@ -104,8 +104,6 @@ static const char* cmDocumentationOptions[][2] = { { "--test-timeout", "The time limit in seconds, internal use only." }, { "--test-load", "CPU load threshold for starting new parallel tests." }, { "--tomorrow-tag", "Nightly or experimental starts with next day tag." }, - { "--ctest-config", "The configuration file used to initialize CTest state " - "when submitting dashboards." }, { "--overwrite", "Overwrite CTest configuration option." }, { "--extra-submit <file>[;<file>]", "Submit extra files to the dashboard." }, { "--force-new-ctest-process", diff --git a/Source/kwsys/CMakeLists.txt b/Source/kwsys/CMakeLists.txt index e4406e7..51f4088 100644 --- a/Source/kwsys/CMakeLists.txt +++ b/Source/kwsys/CMakeLists.txt @@ -1150,17 +1150,17 @@ IF(KWSYS_STANDALONE OR CMake_SOURCE_DIR) SET(testProcess_COMPILE_FLAGS "") # Some Apple compilers produce bad optimizations in this source. IF(APPLE AND CMAKE_C_COMPILER_ID MATCHES "^(GNU|LLVM)$") - STRING(APPEND testProcess_COMPILE_FLAGS " -O0") + SET(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -O0") ELSEIF(CMAKE_C_COMPILER_ID STREQUAL "XL" AND NOT (CMAKE_SYSTEM MATCHES "Linux.*ppc64le" AND NOT CMAKE_C_COMPILER_VERSION VERSION_LESS "13.1.1")) # Tell IBM XL not to warn about our test infinite loop # v13.1.1 and newer on Linux ppc64le is clang based and does not accept # the -qsuppress option - STRING(APPEND testProcess_COMPILE_FLAGS " -qsuppress=1500-010") + SET(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -qsuppress=1500-010") ENDIF() IF(CMAKE_C_FLAGS MATCHES "-fsanitize=") - STRING(APPEND testProcess_COMPILE_FLAGS " -DCRASH_USING_ABORT") + SET(testProcess_COMPILE_FLAGS "${testProcess_COMPILE_FLAGS} -DCRASH_USING_ABORT") ENDIF() SET_PROPERTY(SOURCE testProcess.c PROPERTY COMPILE_FLAGS "${testProcess_COMPILE_FLAGS}") diff --git a/Source/kwsys/DynamicLoader.hxx.in b/Source/kwsys/DynamicLoader.hxx.in index 7e71a45..dc34692 100644 --- a/Source/kwsys/DynamicLoader.hxx.in +++ b/Source/kwsys/DynamicLoader.hxx.in @@ -35,7 +35,7 @@ namespace @KWSYS_NAMESPACE@ { * or absolute) pathname. Otherwise, the dynamic linker searches for the * library as follows : see ld.so(8) for further details): * Whereas this distinction does not exist on Win32. Therefore ideally you - * should be doing full path to garantee to have a consistent way of dealing + * should be doing full path to guarantee to have a consistent way of dealing * with dynamic loading of shared library. * * \warning the Cygwin implementation do not use the Win32 HMODULE. Put extra @@ -72,7 +72,7 @@ public: static LibraryHandle OpenLibrary(const std::string&); /** Attempt to detach a dynamic library from the - * process. A value of true is returned if it is sucessful. */ + * process. A value of true is returned if it is successful. */ static int CloseLibrary(LibraryHandle); /** Find the address of the symbol in the given library. */ diff --git a/Source/kwsys/Process.h.in b/Source/kwsys/Process.h.in index 6cb9443..daf334a 100644 --- a/Source/kwsys/Process.h.in +++ b/Source/kwsys/Process.h.in @@ -421,7 +421,7 @@ enum kwsysProcess_Pipes_e /** * Block until the child process terminates or the given timeout - * expires. If no process is running, returns immediatly. The + * expires. If no process is running, returns immediately. The * argument is: * * timeout = Specifies the maximum time this call may block. Upon diff --git a/Source/kwsys/RegularExpression.hxx.in b/Source/kwsys/RegularExpression.hxx.in index 606e3da..763fdab 100644 --- a/Source/kwsys/RegularExpression.hxx.in +++ b/Source/kwsys/RegularExpression.hxx.in @@ -109,12 +109,12 @@ namespace @KWSYS_NAMESPACE@ { * object as an argument and creates an object initialized with the * information from the given RegularExpression object. * - * The find member function finds the first occurence of the regualr + * The find member function finds the first occurrence of the regular * expression of that object in the string given to find as an argument. Find * returns a boolean, and if true, mutates the private data appropriately. * Find sets pointers to the beginning and end of the thing last found, they * are pointers into the actual string that was searched. The start and end - * member functions return indicies into the searched string that correspond + * member functions return indices into the searched string that correspond * to the beginning and end pointers respectively. The compile member * function takes a char* and puts the compiled version of the char* argument * into the object's private data fields. The == and != operators only check diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx index 366fe30..ab1f40a 100644 --- a/Source/kwsys/SystemInformation.cxx +++ b/Source/kwsys/SystemInformation.cxx @@ -3633,7 +3633,7 @@ SystemInformationImplementation::GetHostMemoryAvailable( // apply resource limits across groups of processes. // this is of use on certain SMP systems (eg. SGI UV) // where the host has a large amount of ram but a given user's - // access to it is severly restricted. The system will + // access to it is severely restricted. The system will // apply a limit across a set of processes. Units are in KiB. if (hostLimitEnvVarName) { const char* hostLimitEnvVarValue = getenv(hostLimitEnvVarName); diff --git a/Source/kwsys/SystemInformation.hxx.in b/Source/kwsys/SystemInformation.hxx.in index 516c505..5678e8a 100644 --- a/Source/kwsys/SystemInformation.hxx.in +++ b/Source/kwsys/SystemInformation.hxx.in @@ -124,7 +124,7 @@ public: // are the processes comprising an mpi program which is running in // parallel. The amount of memory reported may differ from the host // total if a host wide resource limit is applied. Such reource limits - // are reported to us via an applicaiton specified environment variable. + // are reported to us via an application specified environment variable. LongLong GetHostMemoryAvailable(const char* hostLimitEnvVarName = NULL); // Get total system RAM in units of KiB available to this process. diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index 72babc3..50aa857 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -27,6 +27,7 @@ #include <iostream> #include <set> #include <sstream> +#include <utility> #include <vector> // Work-around CMake dependency scanning limitation. This must @@ -1691,7 +1692,7 @@ bool SystemTools::StringEndsWith(const std::string& str1, const char* str2) : false; } -// Returns a pointer to the last occurence of str2 in str1 +// Returns a pointer to the last occurrence of str2 in str1 const char* SystemTools::FindLastString(const char* str1, const char* str2) { if (!str1 || !str2) { @@ -3372,7 +3373,7 @@ std::string SystemTools::RelativePath(const std::string& local, } #ifdef _WIN32 -static std::string GetCasePathName(std::string const& pathIn) +static std::pair<std::string, bool> GetCasePathName(std::string const& pathIn) { std::string casePath; std::vector<std::string> path_components; @@ -3381,7 +3382,7 @@ static std::string GetCasePathName(std::string const& pathIn) { // Relative paths cannot be converted. casePath = pathIn; - return casePath; + return std::make_pair(casePath, false); } // Start with root component. @@ -3433,7 +3434,7 @@ static std::string GetCasePathName(std::string const& pathIn) casePath += path_components[idx]; } - return casePath; + return std::make_pair(casePath, converting); } #endif @@ -3448,12 +3449,14 @@ std::string SystemTools::GetActualCaseForPath(const std::string& p) if (i != SystemTools::PathCaseMap->end()) { return i->second; } - std::string casePath = GetCasePathName(p); - if (casePath.size() > MAX_PATH) { - return casePath; + std::pair<std::string, bool> casePath = GetCasePathName(p); + if (casePath.first.size() > MAX_PATH) { + return casePath.first; } - (*SystemTools::PathCaseMap)[p] = casePath; - return casePath; + if (casePath.second) { + (*SystemTools::PathCaseMap)[p] = casePath.first; + } + return casePath.first; #endif } diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in index 3d109a8..8a02b75 100644 --- a/Source/kwsys/SystemTools.hxx.in +++ b/Source/kwsys/SystemTools.hxx.in @@ -107,7 +107,7 @@ public: } /** - * Replace replace all occurences of the string in the source string. + * Replace replace all occurrences of the string in the source string. */ static void ReplaceString(std::string& source, const char* replace, const char* with); @@ -175,7 +175,7 @@ public: static bool StringEndsWith(const std::string& str1, const char* str2); /** - * Returns a pointer to the last occurence of str2 in str1 + * Returns a pointer to the last occurrence of str2 in str1 */ static const char* FindLastString(const char* str1, const char* str2); @@ -905,7 +905,7 @@ public: /** * Delay the execution for a specified amount of time specified - * in miliseconds + * in milliseconds */ static void Delay(unsigned int msec); diff --git a/Source/kwsys/kwsysPlatformTestsCXX.cxx b/Source/kwsys/kwsysPlatformTestsCXX.cxx index e67d436..f1f9ed3 100644 --- a/Source/kwsys/kwsysPlatformTestsCXX.cxx +++ b/Source/kwsys/kwsysPlatformTestsCXX.cxx @@ -281,7 +281,7 @@ int main() #ifdef TEST_KWSYS_CXX_HAS_BACKTRACE #if defined(__PATHSCALE__) || defined(__PATHCC__) || \ (defined(__LSB_VERSION__) && (__LSB_VERSION__ < 41)) -backtrace doesnt work with this compiler or os +backtrace does not work with this compiler or os #endif #if (defined(__GNUC__) || defined(__PGI)) && !defined(_GNU_SOURCE) #define _GNU_SOURCE |