diff options
author | Kyle Edwards <kyle.edwards@kitware.com> | 2021-07-12 20:12:46 (GMT) |
---|---|---|
committer | Kyle Edwards <kyle.edwards@kitware.com> | 2021-07-12 20:12:46 (GMT) |
commit | 17aa96bb7a6cf16cce1c9bd81dd54b2784826e7d (patch) | |
tree | 0fc8275e0f79c51e924e80419844d60eacf639be /Source | |
parent | b2c03347b07e24a5298361451277264fda8fdb4c (diff) | |
parent | c9cd039e5f312f2717c6522ac7117791856f734b (diff) | |
download | CMake-17aa96bb7a6cf16cce1c9bd81dd54b2784826e7d.zip CMake-17aa96bb7a6cf16cce1c9bd81dd54b2784826e7d.tar.gz CMake-17aa96bb7a6cf16cce1c9bd81dd54b2784826e7d.tar.bz2 |
Merge branch 'master' into file-grd-arch
Diffstat (limited to 'Source')
51 files changed, 688 insertions, 572 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index 9a18184..d8ba784 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -10,36 +10,6 @@ if (NOT CMAKE_SYSTEM_NAME STREQUAL "QNX") endif() include(CheckIncludeFile) -# Check if we can build support for ELF parsing. -if(WIN32) - set(HAVE_ELF_H 0) -elseif(CMAKE_CXX_PLATFORM_ID MATCHES "OpenBSD") - CHECK_INCLUDE_FILES("stdint.h;elf_abi.h" HAVE_ELF_H) -else() - CHECK_INCLUDE_FILE("elf.h" HAVE_ELF_H) -endif() -if(HAVE_ELF_H) - set(CMake_USE_ELF_PARSER 1) -elseif(HAIKU) - # On Haiku, we need to include elf32.h from the private headers - set(CMake_HAIKU_INCLUDE_DIRS - /boot/system/develop/headers/private/system - /boot/system/develop/headers/private/system/arch/x86 - ) - - set(CMAKE_REQUIRED_INCLUDES ${CMake_HAIKU_INCLUDE_DIRS}) - CHECK_INCLUDE_FILE("elf32.h" HAVE_ELF32_H) - unset(CMAKE_REQUIRED_INCLUDES) - - if(HAVE_ELF32_H) - set(CMake_USE_ELF_PARSER 1) - else() - unset(CMake_HAIKU_INCLUDE_DIRS) - set(CMake_USE_ELF_PARSER) - endif() -else() - set(CMake_USE_ELF_PARSER) -endif() if(NOT CMake_DEFAULT_RECURSION_LIMIT) if(DEFINED ENV{DASHBOARD_TEST_FROM_CTEST}) @@ -111,11 +81,6 @@ include_directories( ${CMake_HAIKU_INCLUDE_DIRS} ) -# Check if we can build the ELF parser. -if(CMake_USE_ELF_PARSER) - set(ELF_SRCS cmELF.h cmELF.cxx) -endif() - # Check if we can build the Mach-O parser. if(CMake_USE_MACH_PARSER) set(MACH_SRCS cmMachO.h cmMachO.cxx) @@ -245,7 +210,8 @@ set(SRCS cmDocumentationSection.cxx cmDynamicLoader.cxx cmDynamicLoader.h - ${ELF_SRCS} + cmELF.h + cmELF.cxx cmExprParserHelper.cxx cmExportBuildAndroidMKGenerator.h cmExportBuildAndroidMKGenerator.cxx @@ -994,6 +960,7 @@ set(CTEST_SRCS cmCTest.cxx CTest/cmCTestSubmitHandler.cxx CTest/cmCTestTestCommand.cxx CTest/cmCTestTestHandler.cxx + CTest/cmCTestTestMeasurementXMLParser.cxx CTest/cmCTestUpdateCommand.cxx CTest/cmCTestUpdateHandler.cxx CTest/cmCTestUploadCommand.cxx diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 65bdb2c..1029ed8 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,8 +1,8 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 21) -set(CMake_VERSION_PATCH 0) -set(CMake_VERSION_RC 3) +set(CMake_VERSION_PATCH 20210712) +#set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) # Start with the full version number used in tags. It has no dev info. diff --git a/Source/CPack/cmCPackDebGenerator.cxx b/Source/CPack/cmCPackDebGenerator.cxx index 006d66d..db30a0d 100644 --- a/Source/CPack/cmCPackDebGenerator.cxx +++ b/Source/CPack/cmCPackDebGenerator.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCPackDebGenerator.h" +#include <algorithm> #include <cstdlib> #include <cstring> #include <map> @@ -525,6 +526,8 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel, return 0; } this->packageFiles = gl.GetFiles(); + // Sort files so that they have a reproducible order + std::sort(this->packageFiles.begin(), this->packageFiles.end()); } int res = this->createDeb(); @@ -551,6 +554,8 @@ int cmCPackDebGenerator::PackageOnePack(std::string const& initialTopLevel, return 0; } this->packageFiles = gl.GetFiles(); + // Sort files so that they have a reproducible order + std::sort(this->packageFiles.begin(), this->packageFiles.end()); res = this->createDbgsymDDeb(); if (res != 1) { @@ -672,6 +677,8 @@ int cmCPackDebGenerator::PackageComponentsAllInOne( return 0; } this->packageFiles = gl.GetFiles(); + // Sort files so that they have a reproducible order + std::sort(this->packageFiles.begin(), this->packageFiles.end()); int res = this->createDeb(); if (res != 1) { diff --git a/Source/CTest/cmCTestMemCheckHandler.cxx b/Source/CTest/cmCTestMemCheckHandler.cxx index 125d003..6bb8e79 100644 --- a/Source/CTest/cmCTestMemCheckHandler.cxx +++ b/Source/CTest/cmCTestMemCheckHandler.cxx @@ -305,7 +305,7 @@ int cmCTestMemCheckHandler::GetDefectCount() const return this->DefectCount; } -void cmCTestMemCheckHandler::GenerateDartOutput(cmXMLWriter& xml) +void cmCTestMemCheckHandler::GenerateCTestXML(cmXMLWriter& xml) { if (!this->CTest->GetProduceXML()) { return; diff --git a/Source/CTest/cmCTestMemCheckHandler.h b/Source/CTest/cmCTestMemCheckHandler.h index b200c43..a63a24d 100644 --- a/Source/CTest/cmCTestMemCheckHandler.h +++ b/Source/CTest/cmCTestMemCheckHandler.h @@ -119,9 +119,9 @@ private: bool InitializeMemoryChecking(); /** - * Generate the Dart compatible output + * Generate CTest DynamicAnalysis.xml files */ - void GenerateDartOutput(cmXMLWriter& xml) override; + void GenerateCTestXML(cmXMLWriter& xml) override; std::vector<std::string> CustomPreMemCheck; std::vector<std::string> CustomPostMemCheck; diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index a892113..4e9b0f0 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -2,6 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmCTestRunTest.h" +#include <algorithm> #include <chrono> #include <cstddef> // IWYU pragma: keep #include <cstdint> @@ -44,7 +45,9 @@ void cmCTestRunTest::CheckOutput(std::string const& line) // Check for special CTest XML tags in this line of output. // If any are found, this line is excluded from ProcessOutput. if (!line.empty() && line.find("<CTest") != std::string::npos) { + bool ctest_tag_found = false; if (this->TestHandler->CustomCompletionStatusRegex.find(line)) { + ctest_tag_found = true; this->TestResult.CustomCompletionStatus = this->TestHandler->CustomCompletionStatusRegex.match(1); cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, @@ -52,6 +55,20 @@ void cmCTestRunTest::CheckOutput(std::string const& line) << "Test Details changed to '" << this->TestResult.CustomCompletionStatus << "'" << std::endl); + } else if (this->TestHandler->CustomLabelRegex.find(line)) { + ctest_tag_found = true; + auto label = this->TestHandler->CustomLabelRegex.match(1); + auto& labels = this->TestProperties->Labels; + if (std::find(labels.begin(), labels.end(), label) == labels.end()) { + labels.push_back(label); + std::sort(labels.begin(), labels.end()); + cmCTestLog(this->CTest, HANDLER_VERBOSE_OUTPUT, + this->GetIndex() + << ": " + << "Test Label added: '" << label << "'" << std::endl); + } + } + if (ctest_tag_found) { return; } } @@ -245,7 +262,7 @@ bool cmCTestRunTest::EndTest(size_t completed, size_t total, bool started) *this->TestHandler->LogFile << "Test time = " << buf << std::endl; } - this->DartProcessing(); + this->ParseOutputForMeasurements(); // if this is doing MemCheck then all the output needs to be put into // Output since that is what is parsed by cmCTestMemCheckHandler @@ -681,18 +698,22 @@ void cmCTestRunTest::ComputeArguments() } } -void cmCTestRunTest::DartProcessing() +void cmCTestRunTest::ParseOutputForMeasurements() { if (!this->ProcessOutput.empty() && - this->ProcessOutput.find("<DartMeasurement") != std::string::npos) { - if (this->TestHandler->DartStuff.find(this->ProcessOutput)) { - this->TestResult.DartString = this->TestHandler->DartStuff.match(1); + (this->ProcessOutput.find("<DartMeasurement") != std::string::npos || + this->ProcessOutput.find("<CTestMeasurement") != std::string::npos)) { + if (this->TestHandler->AllTestMeasurementsRegex.find( + this->ProcessOutput)) { + this->TestResult.TestMeasurementsOutput = + this->TestHandler->AllTestMeasurementsRegex.match(1); // keep searching and replacing until none are left - while (this->TestHandler->DartStuff1.find(this->ProcessOutput)) { + while (this->TestHandler->SingleTestMeasurementRegex.find( + this->ProcessOutput)) { // replace the exact match for the string cmSystemTools::ReplaceString( - this->ProcessOutput, this->TestHandler->DartStuff1.match(1).c_str(), - ""); + this->ProcessOutput, + this->TestHandler->SingleTestMeasurementRegex.match(1).c_str(), ""); } } } diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h index 863ac1b..a4981c3 100644 --- a/Source/CTest/cmCTestRunTest.h +++ b/Source/CTest/cmCTestRunTest.h @@ -109,7 +109,7 @@ public: private: bool NeedsToRepeat(); - void DartProcessing(); + void ParseOutputForMeasurements(); void ExeNotFound(std::string exe); bool ForkProcess(cmDuration testTimeOut, bool explicitTimeout, std::vector<std::string>* environment, diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 730ec0f..72b86c1 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -32,6 +32,7 @@ #include "cmCTest.h" #include "cmCTestMultiProcessHandler.h" #include "cmCTestResourceGroupsLexerHelper.h" +#include "cmCTestTestMeasurementXMLParser.h" #include "cmDuration.h" #include "cmExecutionStatus.h" #include "cmGeneratedFileStream.h" @@ -303,15 +304,24 @@ cmCTestTestHandler::cmCTestTestHandler() // Support for JUnit XML output. this->JUnitXMLFileName = ""; - // regex to detect <DartMeasurement>...</DartMeasurement> - this->DartStuff.compile("(<DartMeasurement.*/DartMeasurement[a-zA-Z]*>)"); - // regex to detect each individual <DartMeasurement>...</DartMeasurement> - this->DartStuff1.compile( - "(<DartMeasurement[^<]*</DartMeasurement[a-zA-Z]*>)"); + // Regular expressions to scan test output for custom measurements. - // regex to detect <CTestDetails>...</CTestDetails> + // Capture the whole section of test output from the first opening + // <(CTest|Dart)Measurement*> tag to the last </(CTest|Dart)Measurement*> + // closing tag. + this->AllTestMeasurementsRegex.compile( + "(<(CTest|Dart)Measurement.*/(CTest|Dart)Measurement[a-zA-Z]*>)"); + + // Capture a single <(CTest|Dart)Measurement*> XML element. + this->SingleTestMeasurementRegex.compile( + "(<(CTest|Dart)Measurement[^<]*</(CTest|Dart)Measurement[a-zA-Z]*>)"); + + // Capture content from <CTestDetails>...</CTestDetails> this->CustomCompletionStatusRegex.compile( "<CTestDetails>(.*)</CTestDetails>"); + + // Capture content from <CTestLabel>...</CTestLabel> + this->CustomLabelRegex.compile("<CTestLabel>(.*)</CTestLabel>"); } void cmCTestTestHandler::Initialize() @@ -692,7 +702,7 @@ bool cmCTestTestHandler::GenerateXML() return false; } cmXMLWriter xml(xmlfile); - this->GenerateDartOutput(xml); + this->GenerateCTestXML(xml); } return true; @@ -1400,7 +1410,7 @@ void cmCTestTestHandler::GenerateTestCommand( { } -void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml) +void cmCTestTestHandler::GenerateCTestXML(cmXMLWriter& xml) { if (!this->CTest->GetProduceXML()) { return; @@ -1436,7 +1446,7 @@ void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml) xml.Element("Value", result.ReturnValue); xml.EndElement(); // NamedMeasurement } - this->GenerateRegressionImages(xml, result.DartString); + this->RecordCustomTestMeasurements(xml, result.TestMeasurementsOutput); xml.StartElement("NamedMeasurement"); xml.Attribute("type", "numeric/double"); xml.Attribute("name", "Execution Time"); @@ -1976,124 +1986,48 @@ void cmCTestTestHandler::ExpandTestsToRunInformationForRerunFailed() } } -// Just for convenience -#define SPACE_REGEX "[ \t\r\n]" -void cmCTestTestHandler::GenerateRegressionImages(cmXMLWriter& xml, - const std::string& dart) -{ - cmsys::RegularExpression twoattributes( - "<DartMeasurement" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*>([^<]*)</DartMeasurement>"); - cmsys::RegularExpression threeattributes( - "<DartMeasurement" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*>([^<]*)</DartMeasurement>"); - cmsys::RegularExpression fourattributes( - "<DartMeasurement" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*>([^<]*)</DartMeasurement>"); - cmsys::RegularExpression cdatastart( - "<DartMeasurement" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*>" SPACE_REGEX "*<!\\[CDATA\\["); - cmsys::RegularExpression cdataend("]]>" SPACE_REGEX "*</DartMeasurement>"); - cmsys::RegularExpression measurementfile( - "<DartMeasurementFile" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*(name|type|encoding|compression)=\"([^\"]*)\"" SPACE_REGEX - "*>([^<]*)</DartMeasurementFile>"); - - bool done = false; - std::string cxml = dart; - while (!done) { - if (twoattributes.find(cxml)) { - xml.StartElement("NamedMeasurement"); - xml.Attribute(twoattributes.match(1).c_str(), twoattributes.match(2)); - xml.Attribute(twoattributes.match(3).c_str(), twoattributes.match(4)); - xml.Element("Value", twoattributes.match(5)); - xml.EndElement(); - cxml.erase(twoattributes.start(), - twoattributes.end() - twoattributes.start()); - } else if (threeattributes.find(cxml)) { - xml.StartElement("NamedMeasurement"); - xml.Attribute(threeattributes.match(1).c_str(), - threeattributes.match(2)); - xml.Attribute(threeattributes.match(3).c_str(), - threeattributes.match(4)); - xml.Attribute(threeattributes.match(5).c_str(), - threeattributes.match(6)); - xml.Element("Value", twoattributes.match(7)); - xml.EndElement(); - cxml.erase(threeattributes.start(), - threeattributes.end() - threeattributes.start()); - } else if (fourattributes.find(cxml)) { +void cmCTestTestHandler::RecordCustomTestMeasurements(cmXMLWriter& xml, + std::string content) +{ + while (this->SingleTestMeasurementRegex.find(content)) { + // Extract regex match from content and parse it as an XML element. + auto measurement_str = this->SingleTestMeasurementRegex.match(1); + auto parser = cmCTestTestMeasurementXMLParser(); + parser.Parse(measurement_str.c_str()); + + if (parser.ElementName == "CTestMeasurement" || + parser.ElementName == "DartMeasurement") { xml.StartElement("NamedMeasurement"); - xml.Attribute(fourattributes.match(1).c_str(), fourattributes.match(2)); - xml.Attribute(fourattributes.match(3).c_str(), fourattributes.match(4)); - xml.Attribute(fourattributes.match(5).c_str(), fourattributes.match(6)); - xml.Attribute(fourattributes.match(7).c_str(), fourattributes.match(8)); - xml.Element("Value", twoattributes.match(9)); + xml.Attribute("type", parser.MeasurementType); + xml.Attribute("name", parser.MeasurementName); + xml.Element("Value", parser.CharacterData); xml.EndElement(); - cxml.erase(fourattributes.start(), - fourattributes.end() - fourattributes.start()); - } else if (cdatastart.find(cxml) && cdataend.find(cxml)) { - xml.StartElement("NamedMeasurement"); - xml.Attribute(cdatastart.match(1).c_str(), cdatastart.match(2)); - xml.Attribute(cdatastart.match(3).c_str(), cdatastart.match(4)); - xml.StartElement("Value"); - xml.CData( - cxml.substr(cdatastart.end(), cdataend.start() - cdatastart.end())); - xml.EndElement(); // Value - xml.EndElement(); // NamedMeasurement - cxml.erase(cdatastart.start(), cdataend.end() - cdatastart.start()); - } else if (measurementfile.find(cxml)) { - const std::string& filename = - cmCTest::CleanString(measurementfile.match(5)); - if (cmSystemTools::FileExists(filename)) { + } else if (parser.ElementName == "CTestMeasurementFile" || + parser.ElementName == "DartMeasurementFile") { + const std::string& filename = cmCTest::CleanString(parser.CharacterData); + if (!cmSystemTools::FileExists(filename)) { + xml.StartElement("NamedMeasurement"); + xml.Attribute("name", parser.MeasurementName); + xml.Attribute("text", "text/string"); + xml.Element("Value", "File " + filename + " not found"); + xml.EndElement(); + cmCTestOptionalLog( + this->CTest, HANDLER_OUTPUT, + "File \"" << filename << "\" not found." << std::endl, this->Quiet); + } else { long len = cmSystemTools::FileLength(filename); - std::string k1 = measurementfile.match(1); - std::string v1 = measurementfile.match(2); - std::string k2 = measurementfile.match(3); - std::string v2 = measurementfile.match(4); if (len == 0) { - if (cmSystemTools::LowerCase(k1) == "type") { - v1 = "text/string"; - } - if (cmSystemTools::LowerCase(k2) == "type") { - v2 = "text/string"; - } - xml.StartElement("NamedMeasurement"); - xml.Attribute(k1.c_str(), v1); - xml.Attribute(k2.c_str(), v2); + xml.Attribute("name", parser.MeasurementName); + xml.Attribute("type", "text/string"); xml.Attribute("encoding", "none"); xml.Element("Value", "Image " + filename + " is empty"); xml.EndElement(); } else { - std::string type; - std::string name; - if (cmSystemTools::LowerCase(k1) == "type") { - type = v1; - } else if (cmSystemTools::LowerCase(k2) == "type") { - type = v2; - } - if (cmSystemTools::LowerCase(k1) == "name") { - name = v1; - } else if (cmSystemTools::LowerCase(k2) == "name") { - name = v2; - } - if (type == "file") { + if (parser.MeasurementType == "file") { // Treat this measurement like an "ATTACHED_FILE" when the type // is explicitly "file" (not an image). - this->AttachFile(xml, filename, name); + this->AttachFile(xml, filename, parser.MeasurementName); } else { cmsys::ifstream ifs(filename.c_str(), std::ios::in @@ -2110,10 +2044,8 @@ void cmCTestTestHandler::GenerateRegressionImages(cmXMLWriter& xml, encoded_buffer.get(), 1); xml.StartElement("NamedMeasurement"); - xml.Attribute(measurementfile.match(1).c_str(), - measurementfile.match(2)); - xml.Attribute(measurementfile.match(3).c_str(), - measurementfile.match(4)); + xml.Attribute("name", parser.MeasurementName); + xml.Attribute("type", parser.MeasurementType); xml.Attribute("encoding", "base64"); std::ostringstream ostr; for (size_t cc = 0; cc < rlen; cc++) { @@ -2126,25 +2058,11 @@ void cmCTestTestHandler::GenerateRegressionImages(cmXMLWriter& xml, xml.EndElement(); // NamedMeasurement } } - } else { - int idx = 4; - if (measurementfile.match(1) == "name") { - idx = 2; - } - xml.StartElement("NamedMeasurement"); - xml.Attribute("name", measurementfile.match(idx)); - xml.Attribute("text", "text/string"); - xml.Element("Value", "File " + filename + " not found"); - xml.EndElement(); - cmCTestOptionalLog( - this->CTest, HANDLER_OUTPUT, - "File \"" << filename << "\" not found." << std::endl, this->Quiet); } - cxml.erase(measurementfile.start(), - measurementfile.end() - measurementfile.start()); - } else { - done = true; } + + // Remove this element from content. + cmSystemTools::ReplaceString(content, measurement_str.c_str(), ""); } } diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index bd51738..1b42647 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -177,7 +177,7 @@ public: std::string CompletionStatus; std::string CustomCompletionStatus; std::string Output; - std::string DartString; + std::string TestMeasurementsOutput; int TestCount; cmCTestTestProperties* Properties; }; @@ -276,9 +276,9 @@ public: private: /** - * Generate the Dart compatible output + * Write test results in CTest's Test.xml format */ - virtual void GenerateDartOutput(cmXMLWriter& xml); + virtual void GenerateCTestXML(cmXMLWriter& xml); /** * Write test results in JUnit XML format @@ -348,8 +348,7 @@ private: cmCTestResourceSpec ResourceSpec; std::string ResourceSpecFile; - void GenerateRegressionImages(cmXMLWriter& xml, const std::string& dart); - cmsys::RegularExpression DartStuff1; + void RecordCustomTestMeasurements(cmXMLWriter& xml, std::string content); void CheckLabelFilter(cmCTestTestProperties& it); void CheckLabelFilterExclude(cmCTestTestProperties& it); void CheckLabelFilterInclude(cmCTestTestProperties& it); @@ -358,8 +357,10 @@ private: bool UseUnion; ListOfTests TestList; size_t TotalNumberOfTests; - cmsys::RegularExpression DartStuff; + cmsys::RegularExpression AllTestMeasurementsRegex; + cmsys::RegularExpression SingleTestMeasurementRegex; cmsys::RegularExpression CustomCompletionStatusRegex; + cmsys::RegularExpression CustomLabelRegex; std::ostream* LogFile; diff --git a/Source/CTest/cmCTestTestMeasurementXMLParser.cxx b/Source/CTest/cmCTestTestMeasurementXMLParser.cxx new file mode 100644 index 0000000..636be24 --- /dev/null +++ b/Source/CTest/cmCTestTestMeasurementXMLParser.cxx @@ -0,0 +1,26 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include "cmCTestTestMeasurementXMLParser.h" + +#include <cstring> + +void cmCTestTestMeasurementXMLParser::StartElement(const std::string& name, + const char** attributes) +{ + this->CharacterData.clear(); + this->ElementName = name; + for (const char** attr = attributes; *attr; attr += 2) { + if (strcmp(attr[0], "name") == 0) { + this->MeasurementName = attr[1]; + } else if (strcmp(attr[0], "type") == 0) { + this->MeasurementType = attr[1]; + } + } +} + +void cmCTestTestMeasurementXMLParser::CharacterDataHandler(const char* data, + int length) +{ + this->CharacterData.append(data, length); +} diff --git a/Source/CTest/cmCTestTestMeasurementXMLParser.h b/Source/CTest/cmCTestTestMeasurementXMLParser.h new file mode 100644 index 0000000..b2c3eb3 --- /dev/null +++ b/Source/CTest/cmCTestTestMeasurementXMLParser.h @@ -0,0 +1,21 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ + +#include <string> + +#include "cmXMLParser.h" + +class cmCTestTestMeasurementXMLParser : public cmXMLParser +{ +public: + cmCTestTestMeasurementXMLParser() {} + std::string CharacterData; + std::string ElementName; + std::string MeasurementName; + std::string MeasurementType; + +protected: + void StartElement(const std::string& name, const char** atts) override; + void EndElement(const std::string& /*name*/) override {} + void CharacterDataHandler(const char* data, int length) override; +}; diff --git a/Source/LexerParser/cmFortranParser.cxx b/Source/LexerParser/cmFortranParser.cxx index 3f3ddde..50e9752 100644 --- a/Source/LexerParser/cmFortranParser.cxx +++ b/Source/LexerParser/cmFortranParser.cxx @@ -600,12 +600,12 @@ static const yytype_int8 yytranslate[] = static const yytype_uint8 yyrline[] = { 0, 101, 101, 101, 104, 108, 113, 122, 128, 135, - 140, 144, 149, 157, 162, 167, 172, 177, 182, 187, - 192, 197, 201, 205, 209, 213, 214, 219, 219, 219, - 220, 220, 221, 221, 222, 222, 223, 223, 224, 224, - 225, 225, 226, 226, 227, 227, 228, 228, 231, 232, - 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, - 243, 244, 245, 246, 247 + 140, 144, 149, 161, 166, 171, 176, 181, 186, 191, + 196, 201, 205, 209, 213, 217, 218, 223, 223, 223, + 224, 224, 225, 225, 226, 226, 227, 227, 228, 228, + 229, 229, 230, 230, 231, 231, 232, 232, 235, 236, + 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, + 247, 248, 249, 250, 251 }; #endif @@ -1747,142 +1747,146 @@ yyreduce: cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUse(parser, (yyvsp[-2].string)); } + if (cmsysString_strcasecmp((yyvsp[-4].string), "intrinsic") == 0) { + cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleUseIntrinsic(parser, (yyvsp[-2].string)); + } free((yyvsp[-4].string)); free((yyvsp[-2].string)); } -#line 1754 "cmFortranParser.cxx" +#line 1758 "cmFortranParser.cxx" break; case 13: /* stmt: INCLUDE STRING other EOSTMT */ -#line 157 "cmFortranParser.y" +#line 161 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1764 "cmFortranParser.cxx" +#line 1768 "cmFortranParser.cxx" break; case 14: /* stmt: CPP_LINE_DIRECTIVE STRING other EOSTMT */ -#line 162 "cmFortranParser.y" +#line 166 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleLineDirective(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1774 "cmFortranParser.cxx" +#line 1778 "cmFortranParser.cxx" break; case 15: /* stmt: CPP_INCLUDE_ANGLE other EOSTMT */ -#line 167 "cmFortranParser.y" +#line 171 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1784 "cmFortranParser.cxx" +#line 1788 "cmFortranParser.cxx" break; case 16: /* stmt: include STRING other EOSTMT */ -#line 172 "cmFortranParser.y" +#line 176 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleInclude(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1794 "cmFortranParser.cxx" +#line 1798 "cmFortranParser.cxx" break; case 17: /* stmt: define WORD other EOSTMT */ -#line 177 "cmFortranParser.y" +#line 181 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleDefine(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1804 "cmFortranParser.cxx" +#line 1808 "cmFortranParser.cxx" break; case 18: /* stmt: undef WORD other EOSTMT */ -#line 182 "cmFortranParser.y" +#line 186 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUndef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1814 "cmFortranParser.cxx" +#line 1818 "cmFortranParser.cxx" break; case 19: /* stmt: ifdef WORD other EOSTMT */ -#line 187 "cmFortranParser.y" +#line 191 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIfdef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1824 "cmFortranParser.cxx" +#line 1828 "cmFortranParser.cxx" break; case 20: /* stmt: ifndef WORD other EOSTMT */ -#line 192 "cmFortranParser.y" +#line 196 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIfndef(parser, (yyvsp[-2].string)); free((yyvsp[-2].string)); } -#line 1834 "cmFortranParser.cxx" +#line 1838 "cmFortranParser.cxx" break; case 21: /* stmt: if other EOSTMT */ -#line 197 "cmFortranParser.y" +#line 201 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleIf(parser); } -#line 1843 "cmFortranParser.cxx" +#line 1847 "cmFortranParser.cxx" break; case 22: /* stmt: elif other EOSTMT */ -#line 201 "cmFortranParser.y" +#line 205 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleElif(parser); } -#line 1852 "cmFortranParser.cxx" +#line 1856 "cmFortranParser.cxx" break; case 23: /* stmt: else other EOSTMT */ -#line 205 "cmFortranParser.y" +#line 209 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleElse(parser); } -#line 1861 "cmFortranParser.cxx" +#line 1865 "cmFortranParser.cxx" break; case 24: /* stmt: endif other EOSTMT */ -#line 209 "cmFortranParser.y" +#line 213 "cmFortranParser.y" { cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleEndif(parser); } -#line 1870 "cmFortranParser.cxx" +#line 1874 "cmFortranParser.cxx" break; case 48: /* misc_code: WORD */ -#line 231 "cmFortranParser.y" +#line 235 "cmFortranParser.y" { free ((yyvsp[0].string)); } -#line 1876 "cmFortranParser.cxx" +#line 1880 "cmFortranParser.cxx" break; case 55: /* misc_code: STRING */ -#line 238 "cmFortranParser.y" +#line 242 "cmFortranParser.y" { free ((yyvsp[0].string)); } -#line 1882 "cmFortranParser.cxx" +#line 1886 "cmFortranParser.cxx" break; -#line 1886 "cmFortranParser.cxx" +#line 1890 "cmFortranParser.cxx" default: break; } @@ -2107,6 +2111,6 @@ yyreturn: return yyresult; } -#line 250 "cmFortranParser.y" +#line 254 "cmFortranParser.y" /* End of grammar */ diff --git a/Source/LexerParser/cmFortranParser.y b/Source/LexerParser/cmFortranParser.y index a3e1c24..8ef1903 100644 --- a/Source/LexerParser/cmFortranParser.y +++ b/Source/LexerParser/cmFortranParser.y @@ -151,6 +151,10 @@ stmt: cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); cmFortranParser_RuleUse(parser, $5); } + if (cmsysString_strcasecmp($3, "intrinsic") == 0) { + cmFortranParser* parser = cmFortran_yyget_extra(yyscanner); + cmFortranParser_RuleUseIntrinsic(parser, $5); + } free($3); free($5); } diff --git a/Source/QtDialog/QCMake.cxx b/Source/QtDialog/QCMake.cxx index e6faef4..859c18d 100644 --- a/Source/QtDialog/QCMake.cxx +++ b/Source/QtDialog/QCMake.cxx @@ -550,17 +550,14 @@ void QCMake::loadPresets() } QCMakePreset preset; - preset.name = std::move(QString::fromLocal8Bit(p.Name.data())); - preset.displayName = - std::move(QString::fromLocal8Bit(p.DisplayName.data())); - preset.description = - std::move(QString::fromLocal8Bit(p.Description.data())); - preset.generator = std::move(QString::fromLocal8Bit(p.Generator.data())); - preset.architecture = - std::move(QString::fromLocal8Bit(p.Architecture.data())); + preset.name = QString::fromLocal8Bit(p.Name.data()); + preset.displayName = QString::fromLocal8Bit(p.DisplayName.data()); + preset.description = QString::fromLocal8Bit(p.Description.data()); + preset.generator = QString::fromLocal8Bit(p.Generator.data()); + preset.architecture = QString::fromLocal8Bit(p.Architecture.data()); preset.setArchitecture = !p.ArchitectureStrategy || p.ArchitectureStrategy == cmCMakePresetsFile::ArchToolsetStrategy::Set; - preset.toolset = std::move(QString::fromLocal8Bit(p.Toolset.data())); + preset.toolset = QString::fromLocal8Bit(p.Toolset.data()); preset.setToolset = !p.ToolsetStrategy || p.ToolsetStrategy == cmCMakePresetsFile::ArchToolsetStrategy::Set; preset.enabled = it.Expanded && it.Expanded->ConditionResult && diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h index a156a41..e1a4f8b 100644 --- a/Source/cmCommonTargetGenerator.h +++ b/Source/cmCommonTargetGenerator.h @@ -40,6 +40,7 @@ protected: cmLocalCommonGenerator* LocalCommonGenerator; cmGlobalCommonGenerator* GlobalCommonGenerator; std::vector<std::string> ConfigNames; + bool UseLWYU = false; void AppendFortranFormatFlags(std::string& flags, cmSourceFile const& source); diff --git a/Source/cmConfigure.cmake.h.in b/Source/cmConfigure.cmake.h.in index aeca6b4..6a419f6 100644 --- a/Source/cmConfigure.cmake.h.in +++ b/Source/cmConfigure.cmake.h.in @@ -16,7 +16,6 @@ #cmakedefine HAVE_ENVIRON_NOT_REQUIRE_PROTOTYPE #cmakedefine HAVE_UNSETENV -#cmakedefine CMake_USE_ELF_PARSER #cmakedefine CMake_USE_MACH_PARSER #cmakedefine CMake_USE_XCOFF_PARSER #define CMake_DEFAULT_RECURSION_LIMIT @CMake_DEFAULT_RECURSION_LIMIT@ diff --git a/Source/cmDependsFortran.cxx b/Source/cmDependsFortran.cxx index bca26b9..6024cf6 100644 --- a/Source/cmDependsFortran.cxx +++ b/Source/cmDependsFortran.cxx @@ -163,12 +163,17 @@ bool cmDependsFortran::Finalize(std::ostream& makeDepends, mod_dir = this->LocalGenerator->GetCurrentBinaryDirectory(); } + bool building_intrinsics = + !mf->GetSafeDefinition("CMAKE_Fortran_TARGET_BUILDING_INSTRINSIC_MODULES") + .empty(); + // Actually write dependencies to the streams. using ObjectInfoMap = cmDependsFortranInternals::ObjectInfoMap; ObjectInfoMap const& objInfo = this->Internal->ObjectInfo; for (auto const& i : objInfo) { if (!this->WriteDependenciesReal(i.first, i.second, mod_dir, stamp_dir, - makeDepends, internalDepends)) { + makeDepends, internalDepends, + building_intrinsics)) { return false; } } @@ -307,7 +312,8 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj, std::string const& mod_dir, std::string const& stamp_dir, std::ostream& makeDepends, - std::ostream& internalDepends) + std::ostream& internalDepends, + bool buildingIntrinsics) { // Get the source file for this object. std::string const& src = info.Source; @@ -339,8 +345,13 @@ bool cmDependsFortran::WriteDependenciesReal(std::string const& obj, makeDepends << '\n'; } + std::set<std::string> req = info.Requires; + if (buildingIntrinsics) { + req.insert(info.Intrinsics.begin(), info.Intrinsics.end()); + } + // Write module requirements to the output stream. - for (std::string const& i : info.Requires) { + for (std::string const& i : req) { // Require only modules not provided in the same source. if (info.Provides.find(i) != info.Provides.cend()) { continue; diff --git a/Source/cmDependsFortran.h b/Source/cmDependsFortran.h index 0d407bc..a74db91 100644 --- a/Source/cmDependsFortran.h +++ b/Source/cmDependsFortran.h @@ -72,7 +72,8 @@ protected: std::string const& mod_dir, std::string const& stamp_dir, std::ostream& makeDepends, - std::ostream& internalDepends); + std::ostream& internalDepends, + bool buildingIntrinsics); // The source file from which to start scanning. std::string SourceFile; diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx index 9a474e3..1678ce8 100644 --- a/Source/cmELF.cxx +++ b/Source/cmELF.cxx @@ -17,41 +17,9 @@ #include "cmsys/FStream.hxx" -// Include the ELF format information system header. -#if defined(__OpenBSD__) -# include <elf_abi.h> -#elif defined(__HAIKU__) -# include <elf32.h> -# include <elf64.h> -using Elf32_Ehdr = struct Elf32_Ehdr; -using Elf32_Shdr = struct Elf32_Shdr; -using Elf32_Sym = struct Elf32_Sym; -using Elf32_Rel = struct Elf32_Rel; -using Elf32_Rela = struct Elf32_Rela; -# define ELFMAG0 0x7F -# define ELFMAG1 'E' -# define ELFMAG2 'L' -# define ELFMAG3 'F' -# define ET_NONE 0 -# define ET_REL 1 -# define ET_EXEC 2 -# define ET_DYN 3 -# define ET_CORE 4 -# define EM_386 3 -# define EM_SPARC 2 -# define EM_PPC 20 -#else -# include <elf.h> -#endif -#if defined(__sun) -# include <sys/link.h> // For dynamic section information -#endif -#ifdef _SCO_DS -# include <link.h> // For DT_SONAME etc. -#endif -#ifndef DT_RUNPATH -# define DT_RUNPATH 29 -#endif +#include "cmelf/elf32.h" +#include "cmelf/elf64.h" +#include "cmelf/elf_common.h" // Low-level byte swapping implementation. template <size_t s> @@ -145,6 +113,7 @@ public: virtual std::vector<char> EncodeDynamicEntries( const cmELF::DynamicEntryList&) = 0; virtual StringEntry const* GetDynamicSectionString(unsigned int tag) = 0; + virtual bool IsMips() const = 0; virtual void PrintInfo(std::ostream& os) const = 0; // Lookup the SONAME in the DYNAMIC section. @@ -218,7 +187,6 @@ struct cmELFTypes32 }; // Configure the implementation template for 64-bit ELF files. -#ifndef _SCO_DS struct cmELFTypes64 { using ELF_Ehdr = Elf64_Ehdr; @@ -228,7 +196,6 @@ struct cmELFTypes64 using tagtype = ::uint64_t; static const char* GetName() { return "64-bit"; } }; -#endif // Parser implementation template. template <class Types> @@ -262,6 +229,8 @@ public: // Lookup a string from the dynamic section with the given tag. StringEntry const* GetDynamicSectionString(unsigned int tag) override; + bool IsMips() const override { return this->ELFHeader.e_machine == EM_MIPS; } + // Print information about the ELF file. void PrintInfo(std::ostream& os) const override { @@ -345,16 +314,12 @@ private: eti == ET_CORE) { return true; } -#if defined(ET_LOOS) && defined(ET_HIOS) if (eti >= ET_LOOS && eti <= ET_HIOS) { return true; } -#endif -#if defined(ET_LOPROC) && defined(ET_HIPROC) if (eti >= ET_LOPROC && eti <= ET_HIPROC) { return true; } -#endif return false; } @@ -465,18 +430,14 @@ cmELFInternalImpl<Types>::cmELFInternalImpl(cmELF* external, break; default: { unsigned int eti = static_cast<unsigned int>(this->ELFHeader.e_type); -#if defined(ET_LOOS) && defined(ET_HIOS) if (eti >= ET_LOOS && eti <= ET_HIOS) { this->ELFType = cmELF::FileTypeSpecificOS; break; } -#endif -#if defined(ET_LOPROC) && defined(ET_HIPROC) if (eti >= ET_LOPROC && eti <= ET_HIPROC) { this->ELFType = cmELF::FileTypeSpecificProc; break; } -#endif std::ostringstream e; e << "Unknown ELF file type " << eti; this->SetErrorMessage(e.str().c_str()); @@ -681,17 +642,12 @@ cmELF::StringEntry const* cmELFInternalImpl<Types>::GetDynamicSectionString( const long cmELF::TagRPath = DT_RPATH; const long cmELF::TagRunPath = DT_RUNPATH; - -#ifdef DT_MIPS_RLD_MAP_REL const long cmELF::TagMipsRldMapRel = DT_MIPS_RLD_MAP_REL; -#else -const long cmELF::TagMipsRldMapRel = 0; -#endif cmELF::cmELF(const char* fname) { // Try to open the file. - auto fin = cm::make_unique<cmsys::ifstream>(fname); + auto fin = cm::make_unique<cmsys::ifstream>(fname, std::ios::binary); // Quit now if the file could not be opened. if (!fin || !*fin) { @@ -736,15 +692,11 @@ cmELF::cmELF(const char* fname) // 32-bit ELF this->Internal = cm::make_unique<cmELFInternalImpl<cmELFTypes32>>( this, std::move(fin), order); - } -#ifndef _SCO_DS - else if (ident[EI_CLASS] == ELFCLASS64) { + } else if (ident[EI_CLASS] == ELFCLASS64) { // 64-bit ELF this->Internal = cm::make_unique<cmELFInternalImpl<cmELFTypes64>>( this, std::move(fin), order); - } -#endif - else { + } else { this->ErrorMessage = "ELF file class is not 32-bit or 64-bit."; return; } @@ -846,6 +798,14 @@ cmELF::StringEntry const* cmELF::GetRunPath() return nullptr; } +bool cmELF::IsMIPS() const +{ + if (this->Valid()) { + return this->Internal->IsMips(); + } + return false; +} + void cmELF::PrintInfo(std::ostream& os) const { if (this->Valid()) { diff --git a/Source/cmELF.h b/Source/cmELF.h index f88ebe9..ce8bd7f 100644 --- a/Source/cmELF.h +++ b/Source/cmELF.h @@ -11,10 +11,6 @@ #include <utility> #include <vector> -#if !defined(CMake_USE_ELF_PARSER) -# error "This file may be included only if CMake_USE_ELF_PARSER is enabled." -#endif - class cmELFInternal; /** \class cmELF @@ -102,6 +98,9 @@ public: /** Get the RUNPATH field if any. */ StringEntry const* GetRunPath(); + /** Returns true if the ELF file targets a MIPS CPU. */ + bool IsMIPS() const; + /** Print human-readable information about the ELF file. */ void PrintInfo(std::ostream& os) const; diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index dd611de..c69d484 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -924,13 +924,13 @@ void cmExportFileGenerator::GeneratePolicyHeaderCode(std::ostream& os) // Isolate the file policy level. // Support CMake versions as far back as 2.6 but also support using NEW - // policy settings for up to CMake 3.19 (this upper limit may be reviewed + // policy settings for up to CMake 3.20 (this upper limit may be reviewed // and increased from time to time). This reduces the opportunity for CMake // warnings when an older export file is later used with newer CMake // versions. /* clang-format off */ os << "cmake_policy(PUSH)\n" - << "cmake_policy(VERSION 2.6...3.19)\n"; + << "cmake_policy(VERSION 2.6...3.20)\n"; /* clang-format on */ } diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 0ad59c7..1e3076f 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -31,6 +31,7 @@ #include "cmArgumentParser.h" #include "cmCMakePath.h" #include "cmCryptoHash.h" +#include "cmELF.h" #include "cmExecutionStatus.h" #include "cmFSPermissions.h" #include "cmFileCopier.h" @@ -64,10 +65,6 @@ # include "cmFileLockResult.h" #endif -#if defined(CMake_USE_ELF_PARSER) -# include "cmELF.h" -#endif - #if defined(_WIN32) # include <windows.h> #endif @@ -1242,8 +1239,12 @@ bool HandleReadElfCommand(std::vector<std::string> const& args, return false; } -#if defined(CMake_USE_ELF_PARSER) cmELF elf(fileNameArg.c_str()); + if (!elf) { + status.SetError(cmStrCat("READ_ELF given FILE \"", fileNameArg, + "\" that is not a valid ELF file.")); + return false; + } if (!arguments.RPath.empty()) { if (cmELF::StringEntry const* se_rpath = elf.GetRPath()) { @@ -1261,15 +1262,6 @@ bool HandleReadElfCommand(std::vector<std::string> const& args, } return true; -#else - std::string error = "ELF parser not available on this platform."; - if (arguments.Error.empty()) { - status.SetError(error); - return false; - } - status.GetMakefile().AddDefinition(arguments.Error, error); - return true; -#endif } bool HandleInstallCommand(std::vector<std::string> const& args, diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index fba736e..a0de74c 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -478,17 +478,35 @@ bool cmFindPackageCommand::InitialPass(std::vector<std::string> const& args) this->VersionMaxPatch, this->VersionMaxTweak); } + const std::string makePackageRequiredVar = + cmStrCat("CMAKE_REQUIRE_FIND_PACKAGE_", this->Name); + const bool makePackageRequiredSet = + this->Makefile->IsOn(makePackageRequiredVar); + if (makePackageRequiredSet) { + if (this->Required) { + this->Makefile->IssueMessage( + MessageType::WARNING, + cmStrCat("for module ", this->Name, + " already called with REQUIRED, thus ", + makePackageRequiredVar, " has no effect.")); + } else { + this->Required = true; + } + } + std::string disableFindPackageVar = cmStrCat("CMAKE_DISABLE_FIND_PACKAGE_", this->Name); if (this->Makefile->IsOn(disableFindPackageVar)) { if (this->Required) { this->SetError( - cmStrCat("for module ", this->Name, " called with REQUIRED, but ", - disableFindPackageVar, + cmStrCat("for module ", this->Name, + (makePackageRequiredSet + ? " was made REQUIRED with " + makePackageRequiredVar + : " called with REQUIRED, "), + " but ", disableFindPackageVar, " is enabled. A REQUIRED package cannot be disabled.")); return false; } - return true; } diff --git a/Source/cmFortranParser.h b/Source/cmFortranParser.h index 1b14d17..70fe537 100644 --- a/Source/cmFortranParser.h +++ b/Source/cmFortranParser.h @@ -40,6 +40,8 @@ int cmFortranParser_GetOldStartcond(cmFortranParser* parser); /* Callbacks for parser. */ void cmFortranParser_Error(cmFortranParser* parser, const char* message); void cmFortranParser_RuleUse(cmFortranParser* parser, const char* module_name); +void cmFortranParser_RuleUseIntrinsic(cmFortranParser* parser, + const char* module_name); void cmFortranParser_RuleLineDirective(cmFortranParser* parser, const char* filename); void cmFortranParser_RuleInclude(cmFortranParser* parser, const char* name); @@ -99,6 +101,9 @@ public: std::set<std::string> Provides; std::set<std::string> Requires; + // Set of intrinsic modules. + std::set<std::string> Intrinsics; + // Set of files included in the translation unit. std::set<std::string> Includes; }; diff --git a/Source/cmFortranParserImpl.cxx b/Source/cmFortranParserImpl.cxx index 054a2a9..efcc5bb 100644 --- a/Source/cmFortranParserImpl.cxx +++ b/Source/cmFortranParserImpl.cxx @@ -197,6 +197,19 @@ void cmFortranParser_RuleUse(cmFortranParser* parser, const char* module_name) parser->Info.Requires.insert(parser->ModName(mod_name)); } +void cmFortranParser_RuleUseIntrinsic(cmFortranParser* parser, + const char* module_name) +{ + if (parser->InPPFalseBranch) { + return; + } + + // syntax: "use, intrinsic:: module_name" + // requires: "module_name.mod" + std::string const& mod_name = cmSystemTools::LowerCase(module_name); + parser->Info.Intrinsics.insert(parser->ModName(mod_name)); +} + void cmFortranParser_RuleLineDirective(cmFortranParser* parser, const char* filename) { diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index f1ef130..300c13b 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -2142,7 +2142,6 @@ bool cmGeneratorTarget::IsChrpathUsed(const std::string& config) const return true; } -#if defined(CMake_USE_ELF_PARSER) || defined(CMake_USE_XCOFF_PARSER) // Enable if the rpath flag uses a separator and the target uses // binaries we know how to edit. std::string ll = this->GetLinkerLanguage(config); @@ -2155,21 +2154,17 @@ bool cmGeneratorTarget::IsChrpathUsed(const std::string& config) const // CMAKE_EXECUTABLE_FORMAT. if (cmProp fmt = this->Makefile->GetDefinition("CMAKE_EXECUTABLE_FORMAT")) { -# if defined(CMake_USE_ELF_PARSER) if (*fmt == "ELF") { return true; } -# endif -# if defined(CMake_USE_XCOFF_PARSER) +#if defined(CMake_USE_XCOFF_PARSER) if (*fmt == "XCOFF") { return true; } -# endif +#endif } } } -#endif - static_cast<void>(config); return false; } @@ -4466,6 +4461,13 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkOptions( // Last step: replace "LINKER:" prefixed elements by // actual linker wrapper + return this->ResolveLinkerWrapper(result, language); +} + +std::vector<BT<std::string>>& cmGeneratorTarget::ResolveLinkerWrapper( + std::vector<BT<std::string>>& result, const std::string& language) const +{ + // replace "LINKER:" prefixed elements by actual linker wrapper const std::string wrapper(this->Makefile->GetSafeDefinition( "CMAKE_" + language + (this->IsDeviceLink() ? "_DEVICE_LINKER_WRAPPER_FLAG" @@ -6175,6 +6177,14 @@ std::string cmGeneratorTarget::GetFortranModuleDirectory( return this->FortranModuleDirectory; } +bool cmGeneratorTarget::IsFortranBuildingInstrinsicModules() const +{ + if (cmProp prop = this->GetProperty("Fortran_BUILDING_INSTRINSIC_MODULES")) { + return cmIsOn(*prop); + } + return false; +} + std::string cmGeneratorTarget::CreateFortranModuleDirectory( std::string const& working_dir) const { diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 6d2aa85..09f4167 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -498,6 +498,9 @@ public: std::vector<BT<std::string>> GetLinkOptions( std::string const& config, std::string const& language) const; + std::vector<BT<std::string>>& ResolveLinkerWrapper( + std::vector<BT<std::string>>& result, const std::string& language) const; + void GetStaticLibraryLinkOptions(std::vector<std::string>& result, const std::string& config, const std::string& language) const; @@ -832,6 +835,7 @@ public: std::string const& config) const; std::string GetFortranModuleDirectory(std::string const& working_dir) const; + bool IsFortranBuildingInstrinsicModules() const; const std::string& GetSourcesProperty() const; diff --git a/Source/cmGlobalCommonGenerator.cxx b/Source/cmGlobalCommonGenerator.cxx index 9e5bbca..a8e0f23 100644 --- a/Source/cmGlobalCommonGenerator.cxx +++ b/Source/cmGlobalCommonGenerator.cxx @@ -16,8 +16,8 @@ #include "cmStateSnapshot.h" #include "cmStateTypes.h" #include "cmStringAlgorithms.h" - -class cmake; +#include "cmSystemTools.h" +#include "cmake.h" cmGlobalCommonGenerator::cmGlobalCommonGenerator(cmake* cm) : cmGlobalGenerator(cm) @@ -95,3 +95,33 @@ bool cmGlobalCommonGenerator::IsExcludedFromAllInConfig( } return !t.ExcludedFromAllInConfigs.empty(); } + +std::string cmGlobalCommonGenerator::GetEditCacheCommand() const +{ + // If generating for an extra IDE, the edit_cache target cannot + // launch a terminal-interactive tool, so always use cmake-gui. + if (!this->GetExtraGeneratorName().empty()) { + return cmSystemTools::GetCMakeGUICommand(); + } + + // Use an internal cache entry to track the latest dialog used + // to edit the cache, and use that for the edit_cache target. + cmake* cm = this->GetCMakeInstance(); + std::string editCacheCommand = cm->GetCMakeEditCommand(); + if (!cm->GetCacheDefinition("CMAKE_EDIT_COMMAND") || + !editCacheCommand.empty()) { + if (this->SupportsDirectConsole() && editCacheCommand.empty()) { + editCacheCommand = cmSystemTools::GetCMakeCursesCommand(); + } + if (editCacheCommand.empty()) { + editCacheCommand = cmSystemTools::GetCMakeGUICommand(); + } + if (!editCacheCommand.empty()) { + cm->AddCacheEntry("CMAKE_EDIT_COMMAND", editCacheCommand.c_str(), + "Path to cache edit program executable.", + cmStateEnums::INTERNAL); + } + } + cmProp edit_cmd = cm->GetCacheDefinition("CMAKE_EDIT_COMMAND"); + return edit_cmd ? *edit_cmd : std::string(); +} diff --git a/Source/cmGlobalCommonGenerator.h b/Source/cmGlobalCommonGenerator.h index 2aa9d27..fed9ce8 100644 --- a/Source/cmGlobalCommonGenerator.h +++ b/Source/cmGlobalCommonGenerator.h @@ -42,4 +42,9 @@ public: std::map<std::string, DirectoryTarget> ComputeDirectoryTargets() const; bool IsExcludedFromAllInConfig(const DirectoryTarget::Target& t, const std::string& config); + +protected: + virtual bool SupportsDirectConsole() const { return true; } + const char* GetEditCacheTargetName() const override { return "edit_cache"; } + std::string GetEditCacheCommand() const override; }; diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 9193778..15a7304 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -498,6 +498,18 @@ bool cmGlobalGenerator::CheckLanguages( void cmGlobalGenerator::EnableLanguage( std::vector<std::string> const& languages, cmMakefile* mf, bool optional) { + if (!this->IsMultiConfig()) { + std::string envBuildType; + if (!mf->GetDefinition("CMAKE_BUILD_TYPE") && + cmSystemTools::GetEnv("CMAKE_BUILD_TYPE", envBuildType)) { + mf->AddCacheDefinition( + "CMAKE_BUILD_TYPE", envBuildType, + "Choose the type of build. Options include: empty, " + "Debug, Release, RelWithDebInfo, MinSizeRel.", + cmStateEnums::STRING); + } + } + if (languages.empty()) { cmSystemTools::Error("EnableLanguage must have a lang specified!"); cmSystemTools::SetFatalErrorOccured(); @@ -1251,10 +1263,8 @@ void cmGlobalGenerator::Configure() this->CreateDefaultGlobalTargets(globalTargets); for (const auto& mf : this->Makefiles) { - auto& targets = mf->GetTargets(); for (GlobalTargetInfo const& globalTarget : globalTargets) { - targets.emplace(globalTarget.Name, - this->CreateGlobalTarget(globalTarget, mf.get())); + this->CreateGlobalTarget(globalTarget, mf.get()); } } } @@ -1771,9 +1781,8 @@ void cmGlobalGenerator::CreateGeneratorTargets( std::map<cmTarget*, cmGeneratorTarget*> const& importedMap) { if (targetTypes == AllTargets) { - for (auto& target : mf->GetTargets()) { - cmTarget* t = &target.second; - lg->AddGeneratorTarget(cm::make_unique<cmGeneratorTarget>(t, lg)); + for (cmTarget* target : mf->GetOrderedTargets()) { + lg->AddGeneratorTarget(cm::make_unique<cmGeneratorTarget>(target, lg)); } } @@ -2812,12 +2821,19 @@ bool cmGlobalGenerator::UseFolderProperty() const return false; } -cmTarget cmGlobalGenerator::CreateGlobalTarget(GlobalTargetInfo const& gti, - cmMakefile* mf) +void cmGlobalGenerator::CreateGlobalTarget(GlobalTargetInfo const& gti, + cmMakefile* mf) { // Package - cmTarget target(gti.Name, cmStateEnums::GLOBAL_TARGET, - cmTarget::VisibilityNormal, mf, gti.PerConfig); + auto tb = + mf->CreateNewTarget(gti.Name, cmStateEnums::GLOBAL_TARGET, gti.PerConfig); + + // Do nothing if gti.Name is already used + if (!tb.second) { + return; + } + + cmTarget& target = tb.first; target.SetProperty("EXCLUDE_FROM_ALL", "TRUE"); std::vector<std::string> no_outputs; @@ -2841,8 +2857,6 @@ cmTarget cmGlobalGenerator::CreateGlobalTarget(GlobalTargetInfo const& gti, if (this->UseFolderProperty()) { target.SetProperty("FOLDER", this->GetPredefinedTargetsFolder()); } - - return target; } std::string cmGlobalGenerator::GenerateRuleFile( diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index 147146e..f0b59bf 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -596,7 +596,7 @@ protected: void AddGlobalTarget_RebuildCache( std::vector<GlobalTargetInfo>& targets) const; void AddGlobalTarget_Install(std::vector<GlobalTargetInfo>& targets); - cmTarget CreateGlobalTarget(GlobalTargetInfo const& gti, cmMakefile* mf); + void CreateGlobalTarget(GlobalTargetInfo const& gti, cmMakefile* mf); std::string FindMakeProgramFile; std::string ConfiguredFilesPath; diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 963118f..47a931d 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -382,7 +382,7 @@ void cmGlobalNinjaGenerator::WriteCustomCommandBuild( if (restat) { vars["restat"] = "1"; } - if (uses_terminal && this->SupportsConsolePool()) { + if (uses_terminal && this->SupportsDirectConsole()) { vars["pool"] = "console"; } else if (!job_pool.empty()) { vars["pool"] = job_pool; @@ -920,14 +920,7 @@ void cmGlobalNinjaGenerator::EnableLanguage( std::vector<std::string> const& langs, cmMakefile* mf, bool optional) { if (this->IsMultiConfig()) { - if (!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES")) { - mf->AddCacheDefinition( - "CMAKE_CONFIGURATION_TYPES", "Debug;Release;RelWithDebInfo", - "Semicolon separated list of supported configuration types, only " - "supports Debug, Release, MinSizeRel, and RelWithDebInfo, anything " - "else will be ignored", - cmStateEnums::STRING); - } + mf->InitCMAKE_CONFIGURATION_TYPES("Debug;Release;RelWithDebInfo"); } this->cmGlobalGenerator::EnableLanguage(langs, mf, optional); @@ -1019,13 +1012,6 @@ bool cmGlobalNinjaGenerator::HasRule(const std::string& name) // Private virtual overrides -std::string cmGlobalNinjaGenerator::GetEditCacheCommand() const -{ - // Ninja by design does not run interactive tools in the terminal, - // so our only choice is cmake-gui. - return cmSystemTools::GetCMakeGUICommand(); -} - void cmGlobalNinjaGenerator::ComputeTargetObjectDirectory( cmGeneratorTarget* gt) const { @@ -1847,7 +1833,7 @@ void cmGlobalNinjaGenerator::WriteTargetRebuildManifest(std::ostream& os) // Use 'console' pool to get non buffered output of the CMake re-run call // Available since Ninja 1.5 - if (this->SupportsConsolePool()) { + if (this->SupportsDirectConsole()) { reBuild.Variables["pool"] = "console"; } @@ -1941,7 +1927,7 @@ std::string cmGlobalNinjaGenerator::NinjaCmd() const return "ninja"; } -bool cmGlobalNinjaGenerator::SupportsConsolePool() const +bool cmGlobalNinjaGenerator::SupportsDirectConsole() const { return this->NinjaSupportsConsolePool; } diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index bb4ce2b..ec73475 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -220,7 +220,6 @@ public: { return "package_source"; } - const char* GetEditCacheTargetName() const override { return "edit_cache"; } const char* GetRebuildCacheTargetName() const override { return "rebuild_cache"; @@ -406,7 +405,7 @@ public: return "1.10.2"; } static std::string RequiredNinjaVersionForCodePage() { return "1.11"; } - bool SupportsConsolePool() const; + bool SupportsDirectConsole() const override; bool SupportsImplicitOuts() const; bool SupportsManifestRestat() const; bool SupportsMultilineDepfile() const; @@ -489,7 +488,6 @@ protected: std::string DefaultFileConfig; private: - std::string GetEditCacheCommand() const override; bool FindMakeProgram(cmMakefile* mf) override; void CheckNinjaFeatures(); void CheckNinjaCodePage(); diff --git a/Source/cmGlobalUnixMakefileGenerator3.cxx b/Source/cmGlobalUnixMakefileGenerator3.cxx index 9c3de1e..d9f94a1 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.cxx +++ b/Source/cmGlobalUnixMakefileGenerator3.cxx @@ -78,36 +78,6 @@ void cmGlobalUnixMakefileGenerator3::GetDocumentation( entry.Brief = "Generates standard UNIX makefiles."; } -std::string cmGlobalUnixMakefileGenerator3::GetEditCacheCommand() const -{ - // If generating for an extra IDE, the edit_cache target cannot - // launch a terminal-interactive tool, so always use cmake-gui. - if (!this->GetExtraGeneratorName().empty()) { - return cmSystemTools::GetCMakeGUICommand(); - } - - // Use an internal cache entry to track the latest dialog used - // to edit the cache, and use that for the edit_cache target. - cmake* cm = this->GetCMakeInstance(); - std::string editCacheCommand = cm->GetCMakeEditCommand(); - if (!cm->GetCacheDefinition("CMAKE_EDIT_COMMAND") || - !editCacheCommand.empty()) { - if (editCacheCommand.empty()) { - editCacheCommand = cmSystemTools::GetCMakeCursesCommand(); - } - if (editCacheCommand.empty()) { - editCacheCommand = cmSystemTools::GetCMakeGUICommand(); - } - if (!editCacheCommand.empty()) { - cm->AddCacheEntry("CMAKE_EDIT_COMMAND", editCacheCommand.c_str(), - "Path to cache edit program executable.", - cmStateEnums::INTERNAL); - } - } - cmProp edit_cmd = cm->GetCacheDefinition("CMAKE_EDIT_COMMAND"); - return edit_cmd ? *edit_cmd : std::string(); -} - void cmGlobalUnixMakefileGenerator3::ComputeTargetObjectDirectory( cmGeneratorTarget* gt) const { diff --git a/Source/cmGlobalUnixMakefileGenerator3.h b/Source/cmGlobalUnixMakefileGenerator3.h index 7c950cc..94ee476 100644 --- a/Source/cmGlobalUnixMakefileGenerator3.h +++ b/Source/cmGlobalUnixMakefileGenerator3.h @@ -228,7 +228,6 @@ protected: { return "package_source"; } - const char* GetEditCacheTargetName() const override { return "edit_cache"; } const char* GetRebuildCacheTargetName() const override { return "rebuild_cache"; @@ -278,7 +277,6 @@ protected: private: const char* GetBuildIgnoreErrorsFlag() const override { return "-i"; } - std::string GetEditCacheCommand() const override; std::map<cmStateSnapshot, std::set<cmGeneratorTarget const*>, cmStateSnapshot::StrictWeakOrder> diff --git a/Source/cmGlobalVisualStudio7Generator.cxx b/Source/cmGlobalVisualStudio7Generator.cxx index 0c85a044..f8aa172 100644 --- a/Source/cmGlobalVisualStudio7Generator.cxx +++ b/Source/cmGlobalVisualStudio7Generator.cxx @@ -107,14 +107,7 @@ void cmGlobalVisualStudio7Generator::EnableLanguage( { mf->AddDefinition("CMAKE_GENERATOR_RC", "rc"); mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1"); - if (!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES")) { - mf->AddCacheDefinition( - "CMAKE_CONFIGURATION_TYPES", "Debug;Release;MinSizeRel;RelWithDebInfo", - "Semicolon separated list of supported configuration types, " - "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, " - "anything else will be ignored.", - cmStateEnums::STRING); - } + mf->InitCMAKE_CONFIGURATION_TYPES("Debug;Release;MinSizeRel;RelWithDebInfo"); // Create list of configurations requested by user's cache, if any. this->cmGlobalVisualStudioGenerator::EnableLanguage(lang, mf, optional); diff --git a/Source/cmGlobalXCodeGenerator.cxx b/Source/cmGlobalXCodeGenerator.cxx index 77403b0..3994816 100644 --- a/Source/cmGlobalXCodeGenerator.cxx +++ b/Source/cmGlobalXCodeGenerator.cxx @@ -431,14 +431,7 @@ void cmGlobalXCodeGenerator::EnableLanguage( { mf->AddDefinition("XCODE", "1"); mf->AddDefinition("XCODE_VERSION", this->VersionString); - if (!mf->GetDefinition("CMAKE_CONFIGURATION_TYPES")) { - mf->AddCacheDefinition( - "CMAKE_CONFIGURATION_TYPES", "Debug;Release;MinSizeRel;RelWithDebInfo", - "Semicolon separated list of supported configuration types, " - "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, " - "anything else will be ignored.", - cmStateEnums::STRING); - } + mf->InitCMAKE_CONFIGURATION_TYPES("Debug;Release;MinSizeRel;RelWithDebInfo"); mf->AddDefinition("CMAKE_GENERATOR_NO_COMPILER_ENV", "1"); this->cmGlobalGenerator::EnableLanguage(lang, mf, optional); this->ComputeArchitectures(mf); diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index 3b282de..028952a 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -107,10 +107,9 @@ cmLocalGenerator::cmLocalGenerator(cmGlobalGenerator* gg, cmMakefile* makefile) { std::vector<std::string> cpath; cmSystemTools::GetPath(cpath, "CPATH"); - for (std::string& cp : cpath) { + for (std::string const& cp : cpath) { if (cmSystemTools::FileIsFullPath(cp)) { - cp = cmSystemTools::CollapseFullPath(cp); - this->EnvCPATH.emplace(std::move(cp)); + this->EnvCPATH.emplace_back(cmSystemTools::CollapseFullPath(cp)); } } } @@ -878,9 +877,12 @@ std::string cmLocalGenerator::GetIncludeFlags( // Support special system include flag if it is available and the // normal flag is repeated for each directory. cmProp sysIncludeFlag = nullptr; + cmProp sysIncludeFlagWarning = nullptr; if (repeatFlag) { sysIncludeFlag = this->Makefile->GetDefinition( cmStrCat("CMAKE_INCLUDE_SYSTEM_FLAG_", lang)); + sysIncludeFlagWarning = this->Makefile->GetDefinition( + cmStrCat("_CMAKE_INCLUDE_SYSTEM_FLAG_", lang, "_WARNING")); } cmProp fwSearchFlag = this->Makefile->GetDefinition( @@ -889,6 +891,7 @@ std::string cmLocalGenerator::GetIncludeFlags( cmStrCat("CMAKE_", lang, "_SYSTEM_FRAMEWORK_SEARCH_FLAG")); bool flagUsed = false; + bool sysIncludeFlagUsed = false; std::set<std::string> emitted; #ifdef __APPLE__ emitted.insert("/System/Library/Frameworks"); @@ -915,6 +918,7 @@ std::string cmLocalGenerator::GetIncludeFlags( if (sysIncludeFlag && target && target->IsSystemIncludeDirectory(i, config, lang)) { includeFlags << *sysIncludeFlag; + sysIncludeFlagUsed = true; } else { includeFlags << includeFlag; } @@ -931,6 +935,9 @@ std::string cmLocalGenerator::GetIncludeFlags( } includeFlags << sep; } + if (sysIncludeFlagUsed && sysIncludeFlagWarning) { + includeFlags << *sysIncludeFlagWarning; + } std::string flags = includeFlags.str(); // remove trailing separators if ((sep[0] != ' ') && !flags.empty() && flags.back() == sep[0]) { @@ -1239,19 +1246,31 @@ std::vector<BT<std::string>> cmLocalGenerator::GetIncludeDirectoriesImplicit( } } + bool const isCorCxx = (lang == "C" || lang == "CXX"); + + // Resolve symlinks in CPATH for comparison with resolved include paths. + // We do this here instead of when EnvCPATH is populated in case symlinks + // on disk have changed in the meantime. + std::set<std::string> resolvedEnvCPATH; + if (isCorCxx) { + for (std::string const& i : this->EnvCPATH) { + resolvedEnvCPATH.emplace(this->GlobalGenerator->GetRealPath(i)); + } + } + // Checks if this is not an excluded (implicit) include directory. - auto notExcluded = [this, &implicitSet, &implicitExclude, - &lang](std::string const& dir) { - return ( - // Do not exclude directories that are not in an excluded set. - ((!cm::contains(implicitSet, this->GlobalGenerator->GetRealPath(dir))) && - (!cm::contains(implicitExclude, dir))) + auto notExcluded = [this, &implicitSet, &implicitExclude, &resolvedEnvCPATH, + isCorCxx](std::string const& dir) -> bool { + std::string const& real_dir = this->GlobalGenerator->GetRealPath(dir); + return + // Do not exclude directories that are not in any excluded set. + !(cm::contains(implicitSet, real_dir) || + cm::contains(implicitExclude, dir)) // Do not exclude entries of the CPATH environment variable even though // they are implicitly searched by the compiler. They are meant to be // user-specified directories that can be re-ordered or converted to // -isystem without breaking real compiler builtin headers. - || - ((lang == "C" || lang == "CXX") && cm::contains(this->EnvCPATH, dir))); + || (isCorCxx && cm::contains(resolvedEnvCPATH, real_dir)); }; // Get the target-specific include directories. @@ -3039,6 +3058,30 @@ void cmLocalGenerator::AppendPositionIndependentLinkerFlags( } } +bool cmLocalGenerator::AppendLWYUFlags(std::string& flags, + const cmGeneratorTarget* target, + const std::string& lang) +{ + auto useLWYU = target->GetPropertyAsBool("LINK_WHAT_YOU_USE") && + (target->GetType() == cmStateEnums::TargetType::EXECUTABLE || + target->GetType() == cmStateEnums::TargetType::SHARED_LIBRARY || + target->GetType() == cmStateEnums::TargetType::MODULE_LIBRARY); + + if (useLWYU) { + const auto& lwyuFlag = this->GetMakefile()->GetSafeDefinition( + cmStrCat("CMAKE_", lang, "_LINK_WHAT_YOU_USE_FLAG")); + useLWYU = !lwyuFlag.empty(); + + if (useLWYU) { + std::vector<BT<std::string>> lwyuOpts; + lwyuOpts.emplace_back(lwyuFlag); + this->AppendFlags(flags, target->ResolveLinkerWrapper(lwyuOpts, lang)); + } + } + + return useLWYU; +} + void cmLocalGenerator::AppendCompileOptions(std::string& options, std::string const& options_list, const char* regex) const diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 993280a..1e09b23 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -171,6 +171,8 @@ public: cmGeneratorTarget* target, const std::string& config, const std::string& lang); + bool AppendLWYUFlags(std::string& flags, const cmGeneratorTarget* target, + const std::string& lang); enum class IncludePathStyle { @@ -587,7 +589,7 @@ protected: std::string::size_type ObjectPathMax; std::set<std::string> ObjectMaxPathViolations; - std::set<std::string> EnvCPATH; + std::vector<std::string> EnvCPATH; using GeneratorTargetMap = std::unordered_map<std::string, cmGeneratorTarget*>; diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index 7f7b1e7..9f8e7ed 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -279,7 +279,7 @@ void cmLocalNinjaGenerator::WriteNinjaRequiredVersion(std::ostream& os) std::string requiredVersion = cmGlobalNinjaGenerator::RequiredNinjaVersion(); // Ninja generator uses the 'console' pool if available (>= 1.5) - if (this->GetGlobalNinjaGenerator()->SupportsConsolePool()) { + if (this->GetGlobalNinjaGenerator()->SupportsDirectConsole()) { requiredVersion = cmGlobalNinjaGenerator::RequiredNinjaVersionForConsolePool(); } diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index c970abe..7ac5113 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -2118,15 +2118,23 @@ cmTarget* cmMakefile::AddExecutable(const std::string& exeName, cmTarget* cmMakefile::AddNewTarget(cmStateEnums::TargetType type, const std::string& name) { - auto it = this->Targets - .emplace(name, - cmTarget(name, type, cmTarget::VisibilityNormal, this, - cmTarget::PerConfig::Yes)) - .first; + return &this->CreateNewTarget(name, type).first; +} + +std::pair<cmTarget&, bool> cmMakefile::CreateNewTarget( + const std::string& name, cmStateEnums::TargetType type, + cmTarget::PerConfig perConfig) +{ + auto ib = this->Targets.emplace( + name, cmTarget(name, type, cmTarget::VisibilityNormal, this, perConfig)); + auto it = ib.first; + if (!ib.second) { + return std::make_pair(std::ref(it->second), false); + } this->OrderedTargets.push_back(&it->second); this->GetGlobalGenerator()->IndexTarget(&it->second); this->GetStateSnapshot().GetDirectory().AddNormalTargetName(name); - return &it->second; + return std::make_pair(std::ref(it->second), true); } cmTarget* cmMakefile::AddNewUtilityTarget(const std::string& utilityName, @@ -3182,6 +3190,23 @@ void cmMakefile::RemoveVariablesInString(std::string& source, } } +void cmMakefile::InitCMAKE_CONFIGURATION_TYPES(std::string const& genDefault) +{ + if (this->GetDefinition("CMAKE_CONFIGURATION_TYPES")) { + return; + } + std::string initConfigs; + if (!cmSystemTools::GetEnv("CMAKE_CONFIGURATION_TYPES", initConfigs)) { + initConfigs = genDefault; + } + this->AddCacheDefinition( + "CMAKE_CONFIGURATION_TYPES", initConfigs, + "Semicolon separated list of supported configuration types, " + "only supports Debug, Release, MinSizeRel, and RelWithDebInfo, " + "anything else will be ignored.", + cmStateEnums::STRING); +} + std::string cmMakefile::GetDefaultConfiguration() const { if (this->GetGlobalGenerator()->IsMultiConfig()) { @@ -4426,13 +4451,12 @@ bool cmMakefile::SetPolicy(cmPolicies::PolicyID id, return false; } - // Deprecate old policies, especially those that require a lot - // of code to maintain the old behavior. - if (status == cmPolicies::OLD && id <= cmPolicies::CMP0081 && + // Deprecate old policies. + if (status == cmPolicies::OLD && id <= cmPolicies::CMP0088 && !(this->GetCMakeInstance()->GetIsInTryCompile() && ( // Policies set by cmCoreTryCompile::TryCompileCode. - id == cmPolicies::CMP0065))) { + id == cmPolicies::CMP0065 || id == cmPolicies::CMP0083))) { this->IssueMessage(MessageType::DEPRECATION_WARNING, cmPolicies::GetPolicyDeprecatedWarning(id)); } diff --git a/Source/cmMakefile.h b/Source/cmMakefile.h index 77e9c74..5886c86 100644 --- a/Source/cmMakefile.h +++ b/Source/cmMakefile.h @@ -13,6 +13,7 @@ #include <stack> #include <string> #include <unordered_map> +#include <utility> #include <vector> #include <cm/optional> @@ -230,6 +231,10 @@ public: cmTarget* AddImportedTarget(const std::string& name, cmStateEnums::TargetType type, bool global); + std::pair<cmTarget&, bool> CreateNewTarget( + const std::string& name, cmStateEnums::TargetType type, + cmTarget::PerConfig perConfig = cmTarget::PerConfig::Yes); + cmTarget* AddNewTarget(cmStateEnums::TargetType type, const std::string& name); @@ -310,6 +315,8 @@ public: */ void SetProjectName(std::string const& name); + void InitCMAKE_CONFIGURATION_TYPES(std::string const& genDefault); + /* Get the default configuration */ std::string GetDefaultConfiguration() const; diff --git a/Source/cmMakefileExecutableTargetGenerator.cxx b/Source/cmMakefileExecutableTargetGenerator.cxx index 3a2744e..306b38f 100644 --- a/Source/cmMakefileExecutableTargetGenerator.cxx +++ b/Source/cmMakefileExecutableTargetGenerator.cxx @@ -397,9 +397,8 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) this->LocalGenerator->GetLinkLibsCMP0065( linkLanguage, *this->GeneratorTarget)); - if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE")) { - this->LocalGenerator->AppendFlags(linkFlags, " -Wl,--no-as-needed"); - } + this->UseLWYU = this->LocalGenerator->AppendLWYUFlags( + linkFlags, this->GeneratorTarget, linkLanguage); // Add language feature flags. this->LocalGenerator->AddLanguageFlagsForLinking( @@ -577,12 +576,18 @@ void cmMakefileExecutableTargetGenerator::WriteExecutableRule(bool relink) vars.Launcher = linkerLauncher.c_str(); } - if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE")) { - std::string cmakeCommand = - cmStrCat(this->LocalGenerator->ConvertToOutputFormat( - cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL), - " -E __run_co_compile --lwyu=", targetOutPathReal); - real_link_commands.push_back(std::move(cmakeCommand)); + if (this->UseLWYU) { + cmProp lwyuCheck = + this->Makefile->GetDefinition("CMAKE_LINK_WHAT_YOU_USE_CHECK"); + if (lwyuCheck) { + std::string cmakeCommand = cmStrCat( + this->LocalGenerator->ConvertToOutputFormat( + cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL), + " -E __run_co_compile --lwyu="); + cmakeCommand += this->LocalGenerator->EscapeForShell(*lwyuCheck); + cmakeCommand += cmStrCat(" --source=", targetOutPathReal); + real_link_commands.push_back(std::move(cmakeCommand)); + } } std::string launcher; diff --git a/Source/cmMakefileLibraryTargetGenerator.cxx b/Source/cmMakefileLibraryTargetGenerator.cxx index d0e3837..64992f2 100644 --- a/Source/cmMakefileLibraryTargetGenerator.cxx +++ b/Source/cmMakefileLibraryTargetGenerator.cxx @@ -178,9 +178,9 @@ void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink) this->AddModuleDefinitionFlag(linkLineComputer.get(), extraFlags, this->GetConfigName()); - if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE")) { - this->LocalGenerator->AppendFlags(extraFlags, " -Wl,--no-as-needed"); - } + this->UseLWYU = this->LocalGenerator->AppendLWYUFlags( + extraFlags, this->GeneratorTarget, linkLanguage); + this->WriteLibraryRules(linkRuleVar, extraFlags, relink); } @@ -871,13 +871,18 @@ void cmMakefileLibraryTargetGenerator::WriteLibraryRules( // Get the set of commands. std::string linkRule = this->GetLinkRule(linkRuleVar); cmExpandList(linkRule, real_link_commands); - if (this->GeneratorTarget->GetPropertyAsBool("LINK_WHAT_YOU_USE") && - (this->GeneratorTarget->GetType() == cmStateEnums::SHARED_LIBRARY)) { - std::string cmakeCommand = cmStrCat( - this->LocalGenerator->ConvertToOutputFormat( - cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL), - " -E __run_co_compile --lwyu=", targetOutPathReal); - real_link_commands.push_back(std::move(cmakeCommand)); + if (this->UseLWYU) { + cmProp lwyuCheck = + this->Makefile->GetDefinition("CMAKE_LINK_WHAT_YOU_USE_CHECK"); + if (lwyuCheck) { + std::string cmakeCommand = cmStrCat( + this->LocalGenerator->ConvertToOutputFormat( + cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL), + " -E __run_co_compile --lwyu="); + cmakeCommand += this->LocalGenerator->EscapeForShell(*lwyuCheck); + cmakeCommand += cmStrCat(" --source=", targetOutPathReal); + real_link_commands.push_back(std::move(cmakeCommand)); + } } // Expand placeholders. diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 6d8376c..d6145f8 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -1380,6 +1380,13 @@ void cmMakefileTargetGenerator::WriteTargetDependRules() << "set(CMAKE_Fortran_TARGET_MODULE_DIR \"" << this->GeneratorTarget->GetFortranModuleDirectory(working_dir) << "\")\n"; + + if (this->GeneratorTarget->IsFortranBuildingInstrinsicModules()) { + *this->InfoFileStream + << "\n" + << "# Fortran compiler is building intrinsic modules.\n" + << "set(CMAKE_Fortran_TARGET_BUILDING_INSTRINSIC_MODULES ON) \n"; + } /* clang-format on */ // and now write the rule to use it diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index 5a4c652..93a54c2 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -581,17 +581,23 @@ std::vector<std::string> cmNinjaNormalTargetGenerator::ComputeLinkCmd( } } cmExpandList(linkCmdStr, linkCmds); - if (this->GetGeneratorTarget()->GetPropertyAsBool("LINK_WHAT_YOU_USE")) { - std::string cmakeCommand = cmStrCat( - this->GetLocalGenerator()->ConvertToOutputFormat( - cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL), - " -E __run_co_compile --lwyu="); - cmGeneratorTarget& gt = *this->GetGeneratorTarget(); - std::string targetOutputReal = this->ConvertToNinjaPath( - gt.GetFullPath(config, cmStateEnums::RuntimeBinaryArtifact, - /*realname=*/true)); - cmakeCommand += targetOutputReal; - linkCmds.push_back(std::move(cmakeCommand)); + if (this->UseLWYU) { + cmProp lwyuCheck = mf->GetDefinition("CMAKE_LINK_WHAT_YOU_USE_CHECK"); + if (lwyuCheck) { + std::string cmakeCommand = cmStrCat( + this->GetLocalGenerator()->ConvertToOutputFormat( + cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL), + " -E __run_co_compile --lwyu="); + cmakeCommand += + this->GetLocalGenerator()->EscapeForShell(*lwyuCheck); + + std::string targetOutputReal = + this->ConvertToNinjaPath(this->GetGeneratorTarget()->GetFullPath( + config, cmStateEnums::RuntimeBinaryArtifact, + /*realname=*/true)); + cmakeCommand += cmStrCat(" --source=", targetOutputReal); + linkCmds.push_back(std::move(cmakeCommand)); + } } return linkCmds; } @@ -1156,9 +1162,11 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( this->AddModuleDefinitionFlag(linkLineComputer.get(), vars["LINK_FLAGS"], config); - if (gt->GetPropertyAsBool("LINK_WHAT_YOU_USE")) { - vars["LINK_FLAGS"] += " -Wl,--no-as-needed"; - } + + this->UseLWYU = this->GetLocalGenerator()->AppendLWYUFlags( + vars["LINK_FLAGS"], this->GetGeneratorTarget(), + this->TargetLinkLanguage(config)); + vars["LINK_FLAGS"] = globalGen->EncodeLiteral(vars["LINK_FLAGS"]); vars["MANIFESTS"] = this->GetManifests(config); diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 2894201..4dd78e5 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -1111,11 +1111,30 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() // Register info file as generated by CMake this->Makefile->AddCMakeOutputFile(this->AutogenTarget.InfoFile); + // Determine whether to use a depfile for the AUTOGEN target. + const bool useNinjaDepfile = this->QtVersion >= IntegerVersion(5, 15) && + this->GlobalGen->GetName().find("Ninja") != std::string::npos; + // Files provided by the autogen target std::vector<std::string> autogenByproducts; + std::vector<std::string> timestampByproducts; if (this->Moc.Enabled) { this->AddGeneratedSource(this->Moc.CompilationFile, this->Moc, true); - autogenByproducts.push_back(this->Moc.CompilationFileGenex); + if (useNinjaDepfile) { + if (this->MultiConfig) { + // Make all mocs_compilation_<CONFIG>.cpp files byproducts of the + // ${target}_autogen/timestamp custom command. + // We cannot just use Moc.CompilationFileGenex here, because that + // custom command runs cmake_autogen for each configuration. + for (const auto& p : this->Moc.CompilationFile.Config) { + timestampByproducts.push_back(p.second); + } + } else { + timestampByproducts.push_back(this->Moc.CompilationFileGenex); + } + } else { + autogenByproducts.push_back(this->Moc.CompilationFileGenex); + } } if (this->Uic.Enabled) { @@ -1265,8 +1284,6 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() this->AutogenTarget.DependFiles.begin(), this->AutogenTarget.DependFiles.end()); - const bool useNinjaDepfile = this->QtVersion >= IntegerVersion(5, 15) && - this->GlobalGen->GetName().find("Ninja") != std::string::npos; if (useNinjaDepfile) { // Create a custom command that generates a timestamp file and // has a depfile assigned. The depfile is created by JobDepFilesMergeT. @@ -1327,8 +1344,9 @@ bool cmQtAutoGenInitializer::InitAutogenTarget() this->AddGeneratedSource(outputFile, this->Moc); const std::string no_main_dependency; this->LocalGen->AddCustomCommandToOutput( - outputFile, dependencies, no_main_dependency, commandLines, - autogenComment.c_str(), this->Dir.Work.c_str(), + { outputFile }, timestampByproducts, dependencies, no_main_dependency, + /*implicit_depends=*/{}, commandLines, autogenComment.c_str(), + this->Dir.Work.c_str(), /*cmp0116=*/cmPolicies::NEW, /*replace=*/false, /*escapeOldStyle=*/false, /*uses_terminal=*/false, diff --git a/Source/cmStandardLevelResolver.cxx b/Source/cmStandardLevelResolver.cxx index 37ed4c1..74b9d6f 100644 --- a/Source/cmStandardLevelResolver.cxx +++ b/Source/cmStandardLevelResolver.cxx @@ -387,6 +387,10 @@ bool cmStandardLevelResolver::CheckCompileFeaturesAvailable( return false; } + if (!this->Makefile->GetGlobalGenerator()->GetLanguageEnabled(lang)) { + return true; + } + const char* features = this->CompileFeaturesAvailable(lang, error); if (!features) { return false; diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 10d2e50..f082ae8 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -20,6 +20,7 @@ #include <cm3p/uv.h> #include "cmDuration.h" +#include "cmELF.h" #include "cmMessageMetadata.h" #include "cmProcessOutput.h" #include "cmRange.h" @@ -46,10 +47,6 @@ # include "cmCryptoHash.h" #endif -#if defined(CMake_USE_ELF_PARSER) -# include "cmELF.h" -#endif - #if defined(CMake_USE_MACH_PARSER) # include "cmMachO.h" #endif @@ -2446,14 +2443,12 @@ void cmSystemTools::MakefileColorEcho(int color, const char* message, bool cmSystemTools::GuessLibrarySOName(std::string const& fullPath, std::string& soname) { -// For ELF shared libraries use a real parser to get the correct -// soname. -#if defined(CMake_USE_ELF_PARSER) + // For ELF shared libraries use a real parser to get the correct + // soname. cmELF elf(fullPath.c_str()); if (elf) { return elf.GetSOName(soname); } -#endif // If the file is not a symlink we have no guess for its soname. if (!cmSystemTools::FileIsSymlink(fullPath)) { @@ -2491,7 +2486,6 @@ bool cmSystemTools::GuessLibraryInstallName(std::string const& fullPath, return false; } -#if defined(CMake_USE_ELF_PARSER) || defined(CMake_USE_XCOFF_PARSER) std::string::size_type cmSystemToolsFindRPath(cm::string_view const& have, cm::string_view const& want) { @@ -2523,9 +2517,7 @@ std::string::size_type cmSystemToolsFindRPath(cm::string_view const& have, // The desired rpath was not found. return std::string::npos; } -#endif -#if defined(CMake_USE_ELF_PARSER) namespace { struct cmSystemToolsRPathInfo { @@ -2539,10 +2531,10 @@ using EmptyCallback = std::function<bool(std::string*, const cmELF&)>; using AdjustCallback = std::function<bool( cm::optional<std::string>&, const std::string&, const char*, std::string*)>; -// FIXME: Dispatch if multiple formats are supported. -bool AdjustRPath(std::string const& file, const EmptyCallback& emptyCallback, - const AdjustCallback& adjustCallback, std::string* emsg, - bool* changed) +cm::optional<bool> AdjustRPathELF(std::string const& file, + const EmptyCallback& emptyCallback, + const AdjustCallback& adjustCallback, + std::string* emsg, bool* changed) { if (changed) { *changed = false; @@ -2553,6 +2545,9 @@ bool AdjustRPath(std::string const& file, const EmptyCallback& emptyCallback, { // Parse the ELF binary. cmELF elf(file.c_str()); + if (!elf) { + return cm::nullopt; // Not a valid ELF file. + } // Get the RPATH and RUNPATH entries from it. int se_count = 0; @@ -2686,14 +2681,14 @@ std::function<bool(std::string*, const cmELF&)> MakeEmptyCallback( } return false; }; -}; +} } -bool cmSystemTools::ChangeRPath(std::string const& file, - std::string const& oldRPath, - std::string const& newRPath, - bool removeEnvironmentRPath, std::string* emsg, - bool* changed) +cm::optional<bool> ChangeRPathELF(std::string const& file, + std::string const& oldRPath, + std::string const& newRPath, + bool removeEnvironmentRPath, + std::string* emsg, bool* changed) { auto adjustCallback = [oldRPath, newRPath, removeEnvironmentRPath]( cm::optional<std::string>& outRPath, @@ -2741,13 +2736,13 @@ bool cmSystemTools::ChangeRPath(std::string const& file, return true; }; - return AdjustRPath(file, MakeEmptyCallback(newRPath), adjustCallback, emsg, - changed); + return AdjustRPathELF(file, MakeEmptyCallback(newRPath), adjustCallback, + emsg, changed); } -bool cmSystemTools::SetRPath(std::string const& file, - std::string const& newRPath, std::string* emsg, - bool* changed) +static cm::optional<bool> SetRPathELF(std::string const& file, + std::string const& newRPath, + std::string* emsg, bool* changed) { auto adjustCallback = [newRPath](cm::optional<std::string>& outRPath, const std::string& inRPath, @@ -2759,22 +2754,31 @@ bool cmSystemTools::SetRPath(std::string const& file, return true; }; - return AdjustRPath(file, MakeEmptyCallback(newRPath), adjustCallback, emsg, - changed); + return AdjustRPathELF(file, MakeEmptyCallback(newRPath), adjustCallback, + emsg, changed); } -#elif defined(CMake_USE_XCOFF_PARSER) -bool cmSystemTools::ChangeRPath(std::string const& file, - std::string const& oldRPath, - std::string const& newRPath, - bool removeEnvironmentRPath, std::string* emsg, - bool* changed) +static cm::optional<bool> ChangeRPathXCOFF(std::string const& file, + std::string const& oldRPath, + std::string const& newRPath, + bool removeEnvironmentRPath, + std::string* emsg, bool* changed) { if (changed) { *changed = false; } - +#if !defined(CMake_USE_XCOFF_PARSER) + (void)file; + (void)oldRPath; + (void)newRPath; + (void)removeEnvironmentRPath; + (void)emsg; + return cm::nullopt; +#else bool chg = false; cmXCOFF xcoff(file.c_str(), cmXCOFF::Mode::ReadWrite); + if (!xcoff) { + return cm::nullopt; // Not a valid XCOFF file + } if (cm::optional<cm::string_view> maybeLibPath = xcoff.GetLibPath()) { cm::string_view libPath = *maybeLibPath; // Make sure the current rpath contains the old rpath. @@ -2830,31 +2834,47 @@ bool cmSystemTools::ChangeRPath(std::string const& file, *changed = chg; } return true; +#endif } -bool cmSystemTools::SetRPath(std::string const& /*file*/, - std::string const& /*newRPath*/, - std::string* /*emsg*/, bool* /*changed*/) +static cm::optional<bool> SetRPathXCOFF(std::string const& /*file*/, + std::string const& /*newRPath*/, + std::string* /*emsg*/, + bool* /*changed*/) { - return false; + return cm::nullopt; // Not implemented. } -#else -bool cmSystemTools::ChangeRPath(std::string const& /*file*/, - std::string const& /*oldRPath*/, - std::string const& /*newRPath*/, - bool /*removeEnvironmentRPath*/, - std::string* /*emsg*/, bool* /*changed*/) + +bool cmSystemTools::ChangeRPath(std::string const& file, + std::string const& oldRPath, + std::string const& newRPath, + bool removeEnvironmentRPath, std::string* emsg, + bool* changed) { + if (cm::optional<bool> result = ChangeRPathELF( + file, oldRPath, newRPath, removeEnvironmentRPath, emsg, changed)) { + return result.value(); + } + if (cm::optional<bool> result = ChangeRPathXCOFF( + file, oldRPath, newRPath, removeEnvironmentRPath, emsg, changed)) { + return result.value(); + } return false; } -bool cmSystemTools::SetRPath(std::string const& /*file*/, - std::string const& /*newRPath*/, - std::string* /*emsg*/, bool* /*changed*/) +bool cmSystemTools::SetRPath(std::string const& file, + std::string const& newRPath, std::string* emsg, + bool* changed) { + if (cm::optional<bool> result = SetRPathELF(file, newRPath, emsg, changed)) { + return result.value(); + } + if (cm::optional<bool> result = + SetRPathXCOFF(file, newRPath, emsg, changed)) { + return result.value(); + } return false; } -#endif bool cmSystemTools::VersionCompare(cmSystemTools::CompareOp op, const char* lhss, const char* rhss) @@ -2989,10 +3009,8 @@ int cmSystemTools::strverscmp(std::string const& lhs, std::string const& rhs) return cm_strverscmp(lhs.c_str(), rhs.c_str()); } -// FIXME: Dispatch if multiple formats are supported. -#if defined(CMake_USE_ELF_PARSER) -bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg, - bool* removed) +static cm::optional<bool> RemoveRPathELF(std::string const& file, + std::string* emsg, bool* removed) { if (removed) { *removed = false; @@ -3005,6 +3023,9 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg, { // Parse the ELF binary. cmELF elf(file.c_str()); + if (!elf) { + return cm::nullopt; // Not a valid ELF file. + } // Get the RPATH and RUNPATH entries from it and sort them by index // in the dynamic section header. @@ -3054,8 +3075,7 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg, entriesErased++; continue; } - if (cmELF::TagMipsRldMapRel != 0 && - it->first == cmELF::TagMipsRldMapRel) { + if (it->first == cmELF::TagMipsRldMapRel && elf.IsMIPS()) { // Background: debuggers need to know the "linker map" which contains // the addresses each dynamic object is loaded at. Most arches use // the DT_DEBUG tag which the dynamic linker writes to (directly) and @@ -3131,15 +3151,22 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg, } return true; } -#elif defined(CMake_USE_XCOFF_PARSER) -bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg, - bool* removed) + +static cm::optional<bool> RemoveRPathXCOFF(std::string const& file, + std::string* emsg, bool* removed) { if (removed) { *removed = false; } - +#if !defined(CMake_USE_XCOFF_PARSER) + (void)file; + (void)emsg; + return cm::nullopt; // Cannot handle XCOFF files. +#else cmXCOFF xcoff(file.c_str(), cmXCOFF::Mode::ReadWrite); + if (!xcoff) { + return cm::nullopt; // Not a valid XCOFF file. + } bool rm = xcoff.RemoveLibPath(); if (!xcoff) { if (emsg) { @@ -3152,55 +3179,60 @@ bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg, *removed = rm; } return true; +#endif } -#else -bool cmSystemTools::RemoveRPath(std::string const& /*file*/, - std::string* /*emsg*/, bool* /*removed*/) +bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg, + bool* removed) { + if (cm::optional<bool> result = RemoveRPathELF(file, emsg, removed)) { + return result.value(); + } + if (cm::optional<bool> result = RemoveRPathXCOFF(file, emsg, removed)) { + return result.value(); + } return false; } -#endif -// FIXME: Dispatch if multiple formats are supported. bool cmSystemTools::CheckRPath(std::string const& file, std::string const& newRPath) { -#if defined(CMake_USE_ELF_PARSER) // Parse the ELF binary. cmELF elf(file.c_str()); - - // Get the RPATH or RUNPATH entry from it. - cmELF::StringEntry const* se = elf.GetRPath(); - if (!se) { - se = elf.GetRunPath(); - } - - // Make sure the current rpath contains the new rpath. - if (newRPath.empty()) { + if (elf) { + // Get the RPATH or RUNPATH entry from it. + cmELF::StringEntry const* se = elf.GetRPath(); if (!se) { - return true; + se = elf.GetRunPath(); } - } else { - if (se && - cmSystemToolsFindRPath(se->Value, newRPath) != std::string::npos) { - return true; + + // Make sure the current rpath contains the new rpath. + if (newRPath.empty()) { + if (!se) { + return true; + } + } else { + if (se && + cmSystemToolsFindRPath(se->Value, newRPath) != std::string::npos) { + return true; + } } + return false; } - return false; -#elif defined(CMake_USE_XCOFF_PARSER) +#if defined(CMake_USE_XCOFF_PARSER) // Parse the XCOFF binary. cmXCOFF xcoff(file.c_str()); - if (cm::optional<cm::string_view> libPath = xcoff.GetLibPath()) { - if (cmSystemToolsFindRPath(*libPath, newRPath) != std::string::npos) { - return true; + if (xcoff) { + if (cm::optional<cm::string_view> libPath = xcoff.GetLibPath()) { + if (cmSystemToolsFindRPath(*libPath, newRPath) != std::string::npos) { + return true; + } } + return false; } - return false; -#else +#endif (void)file; (void)newRPath; return false; -#endif } bool cmSystemTools::RepeatedRemoveDirectory(const std::string& dir) diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 11a8b1f..82880a9 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -3543,8 +3543,6 @@ void cmVisualStudio10TargetGenerator::WriteNasmOptions( } Elem e2(e1, "NASM"); - std::vector<std::string> includes = - this->GetIncludes(configName, "ASM_NASM"); OptionsHelper nasmOptions(*(this->NasmOptions[configName]), e2); nasmOptions.OutputAdditionalIncludeDirectories("ASM_NASM"); nasmOptions.OutputFlagMap(); diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index 1f4c0b8..1e0f497 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -385,18 +385,15 @@ int HandleTidy(const std::string& runCmd, const std::string& sourceFile, return ret; } -int HandleLWYU(const std::string& runCmd, const std::string& /* sourceFile */, +int HandleLWYU(const std::string& runCmd, const std::string& sourceFile, const std::vector<std::string>&) { // Construct the ldd -r -u (link what you use lwyu) command line // ldd -u -r lwuy target - std::vector<std::string> lwyu_cmd; - lwyu_cmd.emplace_back("ldd"); - lwyu_cmd.emplace_back("-u"); - lwyu_cmd.emplace_back("-r"); - lwyu_cmd.push_back(runCmd); + std::vector<std::string> lwyu_cmd = cmExpandedList(runCmd, true); + lwyu_cmd.push_back(sourceFile); - // Run the ldd -u -r command line. + // Run the lwyu check command line, currently ldd is expected. // Capture its stdout and hide its stderr. // Ignore its return code because the tool always returns non-zero // if there are any warnings, but we just want to warn. |