diff options
Diffstat (limited to 'Source')
144 files changed, 1903 insertions, 1179 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index ec473d2..22d8032 100644 --- a/Source/CMakeLists.txt +++ b/Source/CMakeLists.txt @@ -383,8 +383,6 @@ set(SRCS cmProperty.h cmPropertyDefinition.cxx cmPropertyDefinition.h - cmPropertyDefinitionMap.cxx - cmPropertyDefinitionMap.h cmPropertyMap.cxx cmPropertyMap.h cmQtAutoGen.cxx @@ -490,10 +488,10 @@ set(SRCS cmBuildCommand.h cmBuildNameCommand.cxx cmBuildNameCommand.h - cmCMakeCommand.cxx - cmCMakeCommand.h cmCMakeHostSystemInformationCommand.cxx cmCMakeHostSystemInformationCommand.h + cmCMakeLanguageCommand.cxx + cmCMakeLanguageCommand.h cmCMakeMinimumRequired.cxx cmCMakeMinimumRequired.h cmCMakePolicyCommand.cxx diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index 72c70c2..feb55e8 100644 --- a/Source/CMakeVersion.cmake +++ b/Source/CMakeVersion.cmake @@ -1,7 +1,7 @@ # CMake version number components. set(CMake_VERSION_MAJOR 3) set(CMake_VERSION_MINOR 17) -set(CMake_VERSION_PATCH 20200501) +set(CMake_VERSION_PATCH 20200525) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) diff --git a/Source/CPack/WiX/cmWIXPatchParser.cxx b/Source/CPack/WiX/cmWIXPatchParser.cxx index 5588d2d..8b26c4e 100644 --- a/Source/CPack/WiX/cmWIXPatchParser.cxx +++ b/Source/CPack/WiX/cmWIXPatchParser.cxx @@ -6,7 +6,7 @@ #include <cm/memory> -#include "cm_expat.h" +#include <cm3p/expat.h> #include "cmCPackGenerator.h" diff --git a/Source/CPack/cmCPackArchiveGenerator.cxx b/Source/CPack/cmCPackArchiveGenerator.cxx index aaa5318..967cc60 100644 --- a/Source/CPack/cmCPackArchiveGenerator.cxx +++ b/Source/CPack/cmCPackArchiveGenerator.cxx @@ -8,7 +8,7 @@ #include <utility> #include <vector> -#include "cm_libarchive.h" +#include <cm3p/archive.h> #include "cmCPackComponentGroup.h" #include "cmCPackGenerator.h" diff --git a/Source/CPack/cmCPackExternalGenerator.cxx b/Source/CPack/cmCPackExternalGenerator.cxx index 142eb6f..11e1aec 100644 --- a/Source/CPack/cmCPackExternalGenerator.cxx +++ b/Source/CPack/cmCPackExternalGenerator.cxx @@ -8,10 +8,10 @@ #include <cm/memory> -#include "cmsys/FStream.hxx" +#include <cm3p/json/value.h> +#include <cm3p/json/writer.h> -#include "cm_jsoncpp_value.h" -#include "cm_jsoncpp_writer.h" +#include "cmsys/FStream.hxx" #include "cmCPackComponentGroup.h" #include "cmCPackLog.h" diff --git a/Source/CTest/cmCTestBZR.cxx b/Source/CTest/cmCTestBZR.cxx index c87fb83b..c533cd7 100644 --- a/Source/CTest/cmCTestBZR.cxx +++ b/Source/CTest/cmCTestBZR.cxx @@ -10,9 +10,9 @@ #include <cmext/algorithm> -#include "cmsys/RegularExpression.hxx" +#include <cm3p/expat.h> -#include "cm_expat.h" +#include "cmsys/RegularExpression.hxx" #include "cmCTest.h" #include "cmCTestVC.h" diff --git a/Source/CTest/cmCTestCurl.h b/Source/CTest/cmCTestCurl.h index 9c5ba66..b0d7f07 100644 --- a/Source/CTest/cmCTestCurl.h +++ b/Source/CTest/cmCTestCurl.h @@ -8,7 +8,7 @@ #include <string> #include <vector> -#include "cm_curl.h" +#include <cm3p/curl/curl.h> class cmCTest; diff --git a/Source/CTest/cmCTestMultiProcessHandler.cxx b/Source/CTest/cmCTestMultiProcessHandler.cxx index b7251d9..a08cb34 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.cxx +++ b/Source/CTest/cmCTestMultiProcessHandler.cxx @@ -21,13 +21,13 @@ #include <cm/memory> #include <cmext/algorithm> +#include <cm3p/json/value.h> +#include <cm3p/json/writer.h> +#include <cm3p/uv.h> + #include "cmsys/FStream.hxx" #include "cmsys/SystemInformation.hxx" -#include "cm_jsoncpp_value.h" -#include "cm_jsoncpp_writer.h" -#include "cm_uv.h" - #include "cmAffinity.h" #include "cmCTest.h" #include "cmCTestBinPacker.h" diff --git a/Source/CTest/cmCTestMultiProcessHandler.h b/Source/CTest/cmCTestMultiProcessHandler.h index 6e999f9..e21b912 100644 --- a/Source/CTest/cmCTestMultiProcessHandler.h +++ b/Source/CTest/cmCTestMultiProcessHandler.h @@ -11,10 +11,9 @@ #include <string> #include <vector> +#include <cm3p/uv.h> #include <stddef.h> -#include "cm_uv.h" - #include "cmCTest.h" #include "cmCTestResourceAllocator.h" #include "cmCTestTestHandler.h" diff --git a/Source/CTest/cmCTestResourceSpec.cxx b/Source/CTest/cmCTestResourceSpec.cxx index 8f91efb..21c97de 100644 --- a/Source/CTest/cmCTestResourceSpec.cxx +++ b/Source/CTest/cmCTestResourceSpec.cxx @@ -7,12 +7,12 @@ #include <utility> #include <vector> +#include <cm3p/json/reader.h> +#include <cm3p/json/value.h> + #include "cmsys/FStream.hxx" #include "cmsys/RegularExpression.hxx" -#include "cm_jsoncpp_reader.h" -#include "cm_jsoncpp_value.h" - static const cmsys::RegularExpression IdentifierRegex{ "^[a-z_][a-z0-9_]*$" }; static const cmsys::RegularExpression IdRegex{ "^[a-z0-9_]+$" }; diff --git a/Source/CTest/cmCTestRunTest.cxx b/Source/CTest/cmCTestRunTest.cxx index 7674d7a..ba7d47e 100644 --- a/Source/CTest/cmCTestRunTest.cxx +++ b/Source/CTest/cmCTestRunTest.cxx @@ -429,6 +429,7 @@ void cmCTestRunTest::StartFailure(std::string const& output, this->TestResult.Path = this->TestProperties->Directory; this->TestResult.Output = output; this->TestResult.FullCommandLine.clear(); + this->TestResult.Environment.clear(); } std::string cmCTestRunTest::GetTestPrefix(size_t completed, size_t total) const @@ -500,6 +501,7 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total) this->TestResult.Status = cmCTestTestHandler::NOT_RUN; this->TestResult.Output = "Disabled"; this->TestResult.FullCommandLine.clear(); + this->TestResult.Environment.clear(); return false; } @@ -519,6 +521,7 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total) cmCTestLog(this->CTest, HANDLER_OUTPUT, msg << std::endl); this->TestResult.Output = msg; this->TestResult.FullCommandLine.clear(); + this->TestResult.Environment.clear(); this->TestResult.CompletionStatus = "Fixture dependency failed"; this->TestResult.Status = cmCTestTestHandler::NOT_RUN; return false; @@ -539,6 +542,7 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total) cmCTestLog(this->CTest, ERROR_MESSAGE, msg << std::endl); this->TestResult.Output = msg; this->TestResult.FullCommandLine.clear(); + this->TestResult.Environment.clear(); this->TestResult.CompletionStatus = "Missing Configuration"; this->TestResult.Status = cmCTestTestHandler::NOT_RUN; return false; @@ -554,6 +558,7 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total) "Unable to find required file: " << file << std::endl); this->TestResult.Output = "Unable to find required file: " + file; this->TestResult.FullCommandLine.clear(); + this->TestResult.Environment.clear(); this->TestResult.CompletionStatus = "Required Files Missing"; this->TestResult.Status = cmCTestTestHandler::NOT_RUN; return false; @@ -569,6 +574,7 @@ bool cmCTestRunTest::StartTest(size_t completed, size_t total) "Unable to find executable: " << args[1] << std::endl); this->TestResult.Output = "Unable to find executable: " + args[1]; this->TestResult.FullCommandLine.clear(); + this->TestResult.Environment.clear(); this->TestResult.CompletionStatus = "Unable to find executable"; this->TestResult.Status = cmCTestTestHandler::NOT_RUN; return false; @@ -713,25 +719,43 @@ bool cmCTestRunTest::ForkProcess(cmDuration testTimeOut, bool explicitTimeout, cmSystemTools::SaveRestoreEnvironment sre; #endif + std::ostringstream envMeasurement; if (environment && !environment->empty()) { cmSystemTools::AppendEnv(*environment); + for (auto const& var : *environment) { + envMeasurement << var << std::endl; + } } if (this->UseAllocatedResources) { - this->SetupResourcesEnvironment(); + std::vector<std::string> envLog; + this->SetupResourcesEnvironment(&envLog); + for (auto const& var : envLog) { + envMeasurement << var << std::endl; + } } else { cmSystemTools::UnsetEnv("CTEST_RESOURCE_GROUP_COUNT"); + // Signify that this variable is being actively unset + envMeasurement << "#CTEST_RESOURCE_GROUP_COUNT=" << std::endl; } + this->TestResult.Environment = envMeasurement.str(); + // Remove last newline + this->TestResult.Environment.erase(this->TestResult.Environment.length() - + 1); + return this->TestProcess->StartProcess(this->MultiTestHandler.Loop, affinity); } -void cmCTestRunTest::SetupResourcesEnvironment() +void cmCTestRunTest::SetupResourcesEnvironment(std::vector<std::string>* log) { std::string processCount = "CTEST_RESOURCE_GROUP_COUNT="; processCount += std::to_string(this->AllocatedResources.size()); cmSystemTools::PutEnv(processCount); + if (log) { + log->push_back(processCount); + } std::size_t i = 0; for (auto const& process : this->AllocatedResources) { @@ -757,8 +781,14 @@ void cmCTestRunTest::SetupResourcesEnvironment() var += "id:" + it2.Id + ",slots:" + std::to_string(it2.Slots); } cmSystemTools::PutEnv(var); + if (log) { + log->push_back(var); + } } cmSystemTools::PutEnv(resourceList); + if (log) { + log->push_back(resourceList); + } ++i; } } diff --git a/Source/CTest/cmCTestRunTest.h b/Source/CTest/cmCTestRunTest.h index b1d188a..d831247 100644 --- a/Source/CTest/cmCTestRunTest.h +++ b/Source/CTest/cmCTestRunTest.h @@ -119,7 +119,7 @@ private: // Run post processing of the process output for MemCheck void MemCheckPostProcess(); - void SetupResourcesEnvironment(); + void SetupResourcesEnvironment(std::vector<std::string>* log = nullptr); // Returns "completed/total Test #Index: " std::string GetTestPrefix(size_t completed, size_t total) const; diff --git a/Source/CTest/cmCTestSubmitHandler.cxx b/Source/CTest/cmCTestSubmitHandler.cxx index 811a7e8..2989025 100644 --- a/Source/CTest/cmCTestSubmitHandler.cxx +++ b/Source/CTest/cmCTestSubmitHandler.cxx @@ -9,9 +9,9 @@ #include <cmext/algorithm> -#include "cm_curl.h" -#include "cm_jsoncpp_reader.h" -#include "cm_jsoncpp_value.h" +#include <cm3p/curl/curl.h> +#include <cm3p/json/reader.h> +#include <cm3p/json/value.h> #include "cmAlgorithms.h" #include "cmCTest.h" diff --git a/Source/CTest/cmCTestTestHandler.cxx b/Source/CTest/cmCTestTestHandler.cxx index 8fc5cd6..d0dbaae 100644 --- a/Source/CTest/cmCTestTestHandler.cxx +++ b/Source/CTest/cmCTestTestHandler.cxx @@ -1432,6 +1432,12 @@ void cmCTestTestHandler::GenerateDartOutput(cmXMLWriter& xml) xml.Attribute("name", "Command Line"); xml.Element("Value", result.FullCommandLine); xml.EndElement(); // NamedMeasurement + + xml.StartElement("NamedMeasurement"); + xml.Attribute("type", "text/string"); + xml.Attribute("name", "Environment"); + xml.Element("Value", result.Environment); + xml.EndElement(); // NamedMeasurement for (auto const& measure : result.Properties->Measurements) { xml.StartElement("NamedMeasurement"); xml.Attribute("type", "text/string"); diff --git a/Source/CTest/cmCTestTestHandler.h b/Source/CTest/cmCTestTestHandler.h index 55cecb6..0d88c30 100644 --- a/Source/CTest/cmCTestTestHandler.h +++ b/Source/CTest/cmCTestTestHandler.h @@ -169,6 +169,7 @@ public: std::string Path; std::string Reason; std::string FullCommandLine; + std::string Environment; cmDuration ExecutionTime; std::int64_t ReturnValue; int Status; diff --git a/Source/CTest/cmProcess.cxx b/Source/CTest/cmProcess.cxx index 2742fd7..a549117 100644 --- a/Source/CTest/cmProcess.cxx +++ b/Source/CTest/cmProcess.cxx @@ -17,7 +17,7 @@ #include "cmGetPipes.h" #include "cmStringAlgorithms.h" #if defined(_WIN32) -# include "cm_kwiml.h" +# include <cm3p/kwiml/int.h> #endif #define CM_PROCESS_BUF_SIZE 65536 diff --git a/Source/CTest/cmProcess.h b/Source/CTest/cmProcess.h index 526c920..1e6578c 100644 --- a/Source/CTest/cmProcess.h +++ b/Source/CTest/cmProcess.h @@ -11,11 +11,10 @@ #include <utility> #include <vector> +#include <cm3p/uv.h> #include <stddef.h> #include <stdint.h> -#include "cm_uv.h" - #include "cmDuration.h" #include "cmProcessOutput.h" #include "cmUVHandlePtr.h" diff --git a/Source/CursesDialog/cmCursesLongMessageForm.cxx b/Source/CursesDialog/cmCursesLongMessageForm.cxx index 664ba2f..591c546 100644 --- a/Source/CursesDialog/cmCursesLongMessageForm.cxx +++ b/Source/CursesDialog/cmCursesLongMessageForm.cxx @@ -68,7 +68,7 @@ void cmCursesLongMessageForm::UpdateStatusBar() bar[i] = ' '; } int width; - if (x < cmCursesMainForm::MAX_WIDTH) { + if (x >= 0 && x < cmCursesMainForm::MAX_WIDTH) { width = x; } else { width = cmCursesMainForm::MAX_WIDTH - 1; diff --git a/Source/bindexplib.cxx b/Source/bindexplib.cxx index 4a5c641..8435740 100644 --- a/Source/bindexplib.cxx +++ b/Source/bindexplib.cxx @@ -276,8 +276,9 @@ public: symbol.compare(0, 4, vectorPrefix)) { SectChar = this->SectionHeaders[pSymbolTable->SectionNumber - 1] .Characteristics; - // skip symbols containing a dot - if (symbol.find('.') == std::string::npos) { + // skip symbols containing a dot or are from managed code + if (symbol.find('.') == std::string::npos && + !SymbolIsFromManagedCode(symbol)) { if (!pSymbolTable->Type && (SectChar & IMAGE_SCN_MEM_WRITE)) { // Read only (i.e. constants) must be excluded this->DataSymbols.insert(symbol); @@ -302,6 +303,13 @@ public: } private: + bool SymbolIsFromManagedCode(std::string const& symbol) + { + return symbol == "__t2m" || symbol == "__m2mep" || symbol == "__mep" || + symbol.find("$$F") != std::string::npos || + symbol.find("$$J") != std::string::npos; + } + std::set<std::string>& Symbols; std::set<std::string>& DataSymbols; DWORD_PTR SymbolCount; diff --git a/Source/cmAffinity.cxx b/Source/cmAffinity.cxx index 8f9fe2a..35443e7 100644 --- a/Source/cmAffinity.cxx +++ b/Source/cmAffinity.cxx @@ -2,7 +2,7 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmAffinity.h" -#include "cm_uv.h" +#include <cm3p/uv.h> #ifndef CMAKE_USE_SYSTEM_LIBUV # ifdef _WIN32 diff --git a/Source/cmAlgorithms.h b/Source/cmAlgorithms.h index 8b0aa5e..c8e8dcb 100644 --- a/Source/cmAlgorithms.h +++ b/Source/cmAlgorithms.h @@ -15,8 +15,6 @@ #include <cmext/algorithm> -#include "cm_kwiml.h" - #include "cmRange.h" template <typename FwdIt> diff --git a/Source/cmArchiveWrite.cxx b/Source/cmArchiveWrite.cxx index 0f9b42c..78bb6e0 100644 --- a/Source/cmArchiveWrite.cxx +++ b/Source/cmArchiveWrite.cxx @@ -7,12 +7,14 @@ #include <iostream> #include <sstream> +#include <cm3p/archive.h> +#include <cm3p/archive_entry.h> + #include "cmsys/Directory.hxx" #include "cmsys/Encoding.hxx" #include "cmsys/FStream.hxx" #include "cm_get_date.h" -#include "cm_libarchive.h" #include "cmLocale.h" #include "cmStringAlgorithms.h" diff --git a/Source/cmCMakeCommand.cxx b/Source/cmCMakeCommand.cxx deleted file mode 100644 index c11a003..0000000 --- a/Source/cmCMakeCommand.cxx +++ /dev/null @@ -1,68 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#include "cmCMakeCommand.h" - -#include <algorithm> -#include <cstddef> - -#include "cmExecutionStatus.h" -#include "cmListFileCache.h" -#include "cmMakefile.h" -#include "cmRange.h" -#include "cmStringAlgorithms.h" - -bool cmCMakeCommand(std::vector<std::string> const& args, - cmExecutionStatus& status) -{ - if (args.empty()) { - status.SetError("called with incorrect number of arguments"); - return false; - } - - cmMakefile& makefile = status.GetMakefile(); - cmListFileContext context = makefile.GetExecutionContext(); - - bool result = false; - - if (args[0] == "INVOKE") { - if (args.size() == 1) { - status.SetError("called with incorrect number of arguments"); - return false; - } - - // First argument is the name of the function to call - cmListFileFunction func; - func.Name = args[1]; - func.Line = context.Line; - - // The rest of the arguments are passed to the function call above - func.Arguments.resize(args.size() - 1); - for (size_t i = 2; i < args.size(); ++i) { - cmListFileArgument lfarg; - lfarg.Line = context.Line; - lfarg.Value = args[i]; - func.Arguments.emplace_back(lfarg); - } - - result = makefile.ExecuteCommand(func, status); - } else if (args[0] == "EVAL") { - if (args.size() < 2) { - status.SetError("called with incorrect number of arguments"); - return false; - } - - auto code_iter = std::find(args.begin(), args.end(), "CODE"); - if (code_iter == args.end()) { - status.SetError("called without CODE argument"); - return false; - } - - const std::string code = cmJoin(cmMakeRange(++code_iter, args.end()), " "); - result = makefile.ReadListFileAsString( - code, cmStrCat(context.FilePath, ":", context.Line, ":EVAL")); - } else { - status.SetError("called with unknown meta-operation"); - } - - return result; -} diff --git a/Source/cmCMakeLanguageCommand.cxx b/Source/cmCMakeLanguageCommand.cxx new file mode 100644 index 0000000..66857be --- /dev/null +++ b/Source/cmCMakeLanguageCommand.cxx @@ -0,0 +1,111 @@ +/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying + file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmCMakeLanguageCommand.h" + +#include <algorithm> +#include <cstddef> +#include <memory> +#include <string> + +#include "cmExecutionStatus.h" +#include "cmListFileCache.h" +#include "cmMakefile.h" +#include "cmRange.h" +#include "cmStringAlgorithms.h" + +bool cmCMakeLanguageCommand(std::vector<cmListFileArgument> const& args, + cmExecutionStatus& status) +{ + if (args.empty()) { + status.SetError("called with incorrect number of arguments"); + return false; + } + + cmMakefile& makefile = status.GetMakefile(); + cmListFileContext context = makefile.GetExecutionContext(); + + bool result = false; + + std::vector<std::string> dispatchExpandedArgs; + std::vector<cmListFileArgument> dispatchArgs; + dispatchArgs.emplace_back(args[0]); + makefile.ExpandArguments(dispatchArgs, dispatchExpandedArgs); + + if (dispatchExpandedArgs.empty()) { + status.SetError("called with incorrect number of arguments"); + return false; + } + + if (dispatchExpandedArgs[0] == "CALL") { + if ((args.size() == 1 && dispatchExpandedArgs.size() != 2) || + dispatchExpandedArgs.size() > 2) { + status.SetError("called with incorrect number of arguments"); + return false; + } + + // First argument is the name of the function to call + std::string callCommand; + size_t startArg; + if (dispatchExpandedArgs.size() == 1) { + std::vector<std::string> functionExpandedArg; + std::vector<cmListFileArgument> functionArg; + functionArg.emplace_back(args[1]); + makefile.ExpandArguments(functionArg, functionExpandedArg); + + if (functionExpandedArg.size() != 1) { + status.SetError("called with incorrect number of arguments"); + return false; + } + + callCommand = functionExpandedArg[0]; + startArg = 2; + } else { + callCommand = dispatchExpandedArgs[1]; + startArg = 1; + } + + cmListFileFunction func; + func.Name = callCommand; + func.Line = context.Line; + + // The rest of the arguments are passed to the function call above + for (size_t i = startArg; i < args.size(); ++i) { + cmListFileArgument lfarg; + lfarg.Delim = args[i].Delim; + lfarg.Line = context.Line; + lfarg.Value = args[i].Value; + func.Arguments.emplace_back(lfarg); + } + + result = makefile.ExecuteCommand(func, status); + } else if (dispatchExpandedArgs[0] == "EVAL") { + std::vector<std::string> expandedArgs; + makefile.ExpandArguments(args, expandedArgs); + + if (expandedArgs.size() < 2) { + status.SetError("called with incorrect number of arguments"); + return false; + } + + if (expandedArgs[1] != "CODE") { + auto code_iter = + std::find(expandedArgs.begin() + 2, expandedArgs.end(), "CODE"); + if (code_iter == expandedArgs.end()) { + status.SetError("called without CODE argument"); + } else { + status.SetError( + "called with unsupported arguments between EVAL and CODE arguments"); + } + return false; + } + + const std::string code = + cmJoin(cmMakeRange(expandedArgs.begin() + 2, expandedArgs.end()), " "); + result = makefile.ReadListFileAsString( + code, cmStrCat(context.FilePath, ":", context.Line, ":EVAL")); + } else { + status.SetError("called with unknown meta-operation"); + } + + return result; +} diff --git a/Source/cmCMakeCommand.h b/Source/cmCMakeLanguageCommand.h index cf9f4c3..7306515 100644 --- a/Source/cmCMakeCommand.h +++ b/Source/cmCMakeLanguageCommand.h @@ -1,20 +1,20 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmCMakeCommand_h -#define cmCMakeCommand_h +#ifndef cmCMakeLanguageCommand_h +#define cmCMakeLanguageCommand_h #include "cmConfigure.h" // IWYU pragma: keep -#include <string> #include <vector> class cmExecutionStatus; +struct cmListFileArgument; /** * \brief Calls a scripted or build-in command * */ -bool cmCMakeCommand(std::vector<std::string> const& args, - cmExecutionStatus& status); +bool cmCMakeLanguageCommand(std::vector<cmListFileArgument> const& args, + cmExecutionStatus& status); #endif diff --git a/Source/cmCTest.cxx b/Source/cmCTest.cxx index 2a0ddba1..9b023d9 100644 --- a/Source/cmCTest.cxx +++ b/Source/cmCTest.cxx @@ -21,6 +21,9 @@ #include <cmext/algorithm> #include <cmext/string_view> +#include <cm3p/curl/curl.h> +#include <cm3p/zlib.h> + #include "cmsys/Base64.h" #include "cmsys/Directory.hxx" #include "cmsys/FStream.hxx" @@ -28,9 +31,6 @@ #include "cmsys/Process.h" #include "cmsys/RegularExpression.hxx" #include "cmsys/SystemInformation.hxx" - -#include "cm_curl.h" -#include "cm_zlib.h" #if defined(_WIN32) # include <windows.h> // IWYU pragma: keep #else diff --git a/Source/cmCommands.cxx b/Source/cmCommands.cxx index 28b4267..c94f128 100644 --- a/Source/cmCommands.cxx +++ b/Source/cmCommands.cxx @@ -91,8 +91,8 @@ # include "cmAddLinkOptionsCommand.h" # include "cmAuxSourceDirectoryCommand.h" # include "cmBuildNameCommand.h" -# include "cmCMakeCommand.h" # include "cmCMakeHostSystemInformationCommand.h" +# include "cmCMakeLanguageCommand.h" # include "cmExportCommand.h" # include "cmExportLibraryDependenciesCommand.h" # include "cmFLTKWrapUICommand.h" @@ -197,9 +197,9 @@ void GetScriptingCommands(cmState* state) "match the opening WHILE command."); #if !defined(CMAKE_BOOTSTRAP) - state->AddBuiltinCommand("cmake_command", cmCMakeCommand); state->AddBuiltinCommand("cmake_host_system_information", cmCMakeHostSystemInformationCommand); + state->AddBuiltinCommand("cmake_language", cmCMakeLanguageCommand); state->AddBuiltinCommand("load_cache", cmLoadCacheCommand); state->AddBuiltinCommand("remove", cmRemoveCommand); state->AddBuiltinCommand("variable_watch", cmVariableWatchCommand); diff --git a/Source/cmCommonTargetGenerator.cxx b/Source/cmCommonTargetGenerator.cxx index 5414409..32a33ee 100644 --- a/Source/cmCommonTargetGenerator.cxx +++ b/Source/cmCommonTargetGenerator.cxx @@ -98,6 +98,34 @@ void cmCommonTargetGenerator::AppendFortranFormatFlags( } } +void cmCommonTargetGenerator::AppendFortranPreprocessFlags( + std::string& flags, cmSourceFile const& source) +{ + const std::string srcpp = source.GetSafeProperty("Fortran_PREPROCESS"); + cmOutputConverter::FortranPreprocess preprocess = + cmOutputConverter::GetFortranPreprocess(srcpp); + if (preprocess == cmOutputConverter::FortranPreprocess::Unset) { + std::string const& tgtpp = + this->GeneratorTarget->GetSafeProperty("Fortran_PREPROCESS"); + preprocess = cmOutputConverter::GetFortranPreprocess(tgtpp); + } + const char* var = nullptr; + switch (preprocess) { + case cmOutputConverter::FortranPreprocess::Needed: + var = "CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_ON"; + break; + case cmOutputConverter::FortranPreprocess::NotNeeded: + var = "CMAKE_Fortran_COMPILE_OPTIONS_PREPROCESS_OFF"; + break; + default: + break; + } + if (var) { + this->LocalCommonGenerator->AppendCompileOptions( + flags, this->Makefile->GetSafeDefinition(var)); + } +} + std::string cmCommonTargetGenerator::GetFlags(const std::string& l, const std::string& config, const std::string& arch) diff --git a/Source/cmCommonTargetGenerator.h b/Source/cmCommonTargetGenerator.h index 78cedf5..c3c3a3a 100644 --- a/Source/cmCommonTargetGenerator.h +++ b/Source/cmCommonTargetGenerator.h @@ -45,6 +45,9 @@ protected: void AppendFortranFormatFlags(std::string& flags, cmSourceFile const& source); + void AppendFortranPreprocessFlags(std::string& flags, + cmSourceFile const& source); + virtual void AddIncludeFlags(std::string& flags, std::string const& lang, const std::string& config) = 0; diff --git a/Source/cmComputeLinkInformation.cxx b/Source/cmComputeLinkInformation.cxx index ea7ede4..8723d08 100644 --- a/Source/cmComputeLinkInformation.cxx +++ b/Source/cmComputeLinkInformation.cxx @@ -12,7 +12,6 @@ #include <cmext/algorithm> #include "cmComputeLinkDepends.h" -#include "cmGeneratorExpression.h" #include "cmGeneratorTarget.h" #include "cmGlobalGenerator.h" #include "cmListFileCache.h" @@ -587,32 +586,18 @@ void cmComputeLinkInformation::AddImplicitLinkInfo() } void cmComputeLinkInformation::AddRuntimeLinkLibrary(std::string const& lang) -{ // Add the lang runtime library flags. This is activated by the presence - // of a default selection whether or not it is overridden by a property. - std::string defaultVar = - cmStrCat("CMAKE_", lang, "_RUNTIME_LIBRARY_DEFAULT"); - cmProp langRuntimeLibraryDefault = this->Makefile->GetDef(defaultVar); - if (langRuntimeLibraryDefault && !langRuntimeLibraryDefault->empty()) { - cmProp runtimeLibraryValue = - this->Target->GetProperty(cmStrCat(lang, "_RUNTIME_LIBRARY")); - if (!runtimeLibraryValue) { - runtimeLibraryValue = langRuntimeLibraryDefault; - } - - std::string runtimeLibrary = - cmSystemTools::UpperCase(cmGeneratorExpression::Evaluate( - *runtimeLibraryValue, this->Target->GetLocalGenerator(), this->Config, - this->Target)); - if (!runtimeLibrary.empty()) { - if (const char* runtimeLinkOptions = this->Makefile->GetDefinition( - "CMAKE_" + lang + "_RUNTIME_LIBRARY_LINK_OPTIONS_" + - runtimeLibrary)) { - std::vector<std::string> libsVec = cmExpandedList(runtimeLinkOptions); - for (std::string const& i : libsVec) { - if (!cm::contains(this->ImplicitLinkLibs, i)) { - this->AddItem(i, nullptr); - } - } +{ + std::string const& runtimeLibrary = + this->Target->GetRuntimeLinkLibrary(lang, this->Config); + if (runtimeLibrary.empty()) { + return; + } + if (const char* runtimeLinkOptions = this->Makefile->GetDefinition( + "CMAKE_" + lang + "_RUNTIME_LIBRARY_LINK_OPTIONS_" + runtimeLibrary)) { + std::vector<std::string> libsVec = cmExpandedList(runtimeLinkOptions); + for (std::string const& i : libsVec) { + if (!cm::contains(this->ImplicitLinkLibs, i)) { + this->AddItem(i, nullptr); } } } diff --git a/Source/cmConnection.cxx b/Source/cmConnection.cxx index 884e314..e4d0cf1 100644 --- a/Source/cmConnection.cxx +++ b/Source/cmConnection.cxx @@ -5,7 +5,7 @@ #include <cassert> #include <cstring> -#include "cm_uv.h" +#include <cm3p/uv.h> #include "cmServer.h" @@ -20,8 +20,13 @@ void cmEventBasedConnection::on_alloc_buffer(uv_handle_t* handle, uv_buf_t* buf) { (void)(handle); +#ifndef __clang_analyzer__ char* rawBuffer = new char[suggested_size]; *buf = uv_buf_init(rawBuffer, static_cast<unsigned int>(suggested_size)); +#else + (void)(suggested_size); + (void)(buf); +#endif /* __clang_analyzer__ */ } void cmEventBasedConnection::on_read(uv_stream_t* stream, ssize_t nread, @@ -76,6 +81,7 @@ void cmEventBasedConnection::WriteData(const std::string& _data) assert(uv_thread_equal(&curr_thread_id, &this->Server->ServeThreadId)); #endif +#ifndef __clang_analyzer__ auto data = _data; assert(this->WriteStream.get()); if (BufferStrategy) { @@ -90,6 +96,9 @@ void cmEventBasedConnection::WriteData(const std::string& _data) memcpy(req->buf.base, data.c_str(), ds); uv_write(reinterpret_cast<uv_write_t*>(req), this->WriteStream, &req->buf, 1, on_write); +#else + (void)(_data); +#endif /* __clang_analyzer__ */ } void cmEventBasedConnection::ReadData(const std::string& data) diff --git a/Source/cmConnection.h b/Source/cmConnection.h index 7bb2494..5335a7f 100644 --- a/Source/cmConnection.h +++ b/Source/cmConnection.h @@ -9,7 +9,7 @@ #include <memory> #include <string> -#include "cm_uv.h" +#include <cm3p/uv.h> #include "cmUVHandlePtr.h" diff --git a/Source/cmCoreTryCompile.cxx b/Source/cmCoreTryCompile.cxx index 4e2caed..cc2cd01 100644 --- a/Source/cmCoreTryCompile.cxx +++ b/Source/cmCoreTryCompile.cxx @@ -44,6 +44,8 @@ static std::string const kCMAKE_CUDA_ARCHITECTURES = "CMAKE_CUDA_ARCHITECTURES"; static std::string const kCMAKE_CUDA_COMPILER_TARGET = "CMAKE_CUDA_COMPILER_TARGET"; +static std::string const kCMAKE_CUDA_RUNTIME_LIBRARY = + "CMAKE_CUDA_RUNTIME_LIBRARY"; static std::string const kCMAKE_ENABLE_EXPORTS = "CMAKE_ENABLE_EXPORTS"; static std::string const kCMAKE_LINK_SEARCH_END_STATIC = "CMAKE_LINK_SEARCH_END_STATIC"; @@ -717,6 +719,7 @@ int cmCoreTryCompile::TryCompileCode(std::vector<std::string> const& argv, vars.insert(kCMAKE_CXX_COMPILER_TARGET); vars.insert(kCMAKE_CUDA_ARCHITECTURES); vars.insert(kCMAKE_CUDA_COMPILER_TARGET); + vars.insert(kCMAKE_CUDA_RUNTIME_LIBRARY); vars.insert(kCMAKE_ENABLE_EXPORTS); vars.insert(kCMAKE_LINK_SEARCH_END_STATIC); vars.insert(kCMAKE_LINK_SEARCH_START_STATIC); diff --git a/Source/cmCryptoHash.cxx b/Source/cmCryptoHash.cxx index dc7d939..b1e63ba 100644 --- a/Source/cmCryptoHash.cxx +++ b/Source/cmCryptoHash.cxx @@ -4,10 +4,10 @@ #include <cm/memory> -#include "cmsys/FStream.hxx" +#include <cm3p/kwiml/int.h> +#include <cm3p/rhash.h> -#include "cm_kwiml.h" -#include "cm_rhash.h" +#include "cmsys/FStream.hxx" static unsigned int const cmCryptoHashAlgoToId[] = { /* clang-format needs this comment to break after the opening brace */ diff --git a/Source/cmCurl.h b/Source/cmCurl.h index cb73ce6..7bd036e 100644 --- a/Source/cmCurl.h +++ b/Source/cmCurl.h @@ -7,7 +7,7 @@ #include <string> -#include "cm_curl.h" +#include <cm3p/curl/curl.h> std::string cmCurlSetCAInfo(::CURL* curl, const char* cafile = nullptr); std::string cmCurlSetNETRCOption(::CURL* curl, const std::string& netrc_level, diff --git a/Source/cmELF.cxx b/Source/cmELF.cxx index 202b205..a8d81f7 100644 --- a/Source/cmELF.cxx +++ b/Source/cmELF.cxx @@ -3,6 +3,7 @@ #include "cmELF.h" #include <cstddef> +#include <cstdint> #include <map> #include <memory> #include <sstream> @@ -12,14 +13,13 @@ #include <cm/memory> #include <cmext/algorithm> -#include "cmsys/FStream.hxx" +#include <cm3p/kwiml/abi.h> -#include "cm_kwiml.h" +#include "cmsys/FStream.hxx" // Include the ELF format information system header. #if defined(__OpenBSD__) # include <elf_abi.h> -# include <stdint.h> #elif defined(__HAIKU__) # include <elf32.h> # include <elf64.h> diff --git a/Source/cmExportBuildAndroidMKGenerator.cxx b/Source/cmExportBuildAndroidMKGenerator.cxx index 0ee1259..3641cb2 100644 --- a/Source/cmExportBuildAndroidMKGenerator.cxx +++ b/Source/cmExportBuildAndroidMKGenerator.cxx @@ -47,7 +47,9 @@ void cmExportBuildAndroidMKGenerator::GenerateImportTargetCode( os << "LOCAL_MODULE := "; os << targetName << "\n"; os << "LOCAL_SRC_FILES := "; - std::string path = cmSystemTools::ConvertToOutputPath(target->GetFullPath()); + std::string const noConfig; // FIXME: What config to use here? + std::string path = + cmSystemTools::ConvertToOutputPath(target->GetFullPath(noConfig)); os << path << "\n"; } diff --git a/Source/cmExportFileGenerator.cxx b/Source/cmExportFileGenerator.cxx index 28037c6..ed0689a 100644 --- a/Source/cmExportFileGenerator.cxx +++ b/Source/cmExportFileGenerator.cxx @@ -923,12 +923,14 @@ void cmExportFileGenerator::GeneratePolicyHeaderCode(std::ostream& os) /* clang-format on */ // Isolate the file policy level. - // We use 2.6 here instead of the current version because newer - // versions of CMake should be able to export files imported by 2.6 - // until the import format changes. + // Support CMake versions as far back as 2.6 but also support using NEW + // policy settings for up to CMake 3.17 (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)\n"; + << "cmake_policy(VERSION 2.6...3.17)\n"; /* clang-format on */ } diff --git a/Source/cmExportTryCompileFileGenerator.cxx b/Source/cmExportTryCompileFileGenerator.cxx index 6212667..46056c1 100644 --- a/Source/cmExportTryCompileFileGenerator.cxx +++ b/Source/cmExportTryCompileFileGenerator.cxx @@ -71,7 +71,7 @@ std::string cmExportTryCompileFileGenerator::FindTargets( cmTarget dummyHead("try_compile_dummy_exe", cmStateEnums::EXECUTABLE, cmTarget::VisibilityNormal, tgt->Target->GetMakefile(), - true); + cmTarget::PerConfig::Yes); cmGeneratorTarget gDummyHead(&dummyHead, tgt->GetLocalGenerator()); diff --git a/Source/cmExprParserHelper.h b/Source/cmExprParserHelper.h index eaf5dc7..717acdc 100644 --- a/Source/cmExprParserHelper.h +++ b/Source/cmExprParserHelper.h @@ -8,7 +8,7 @@ #include <string> #include <vector> -#include "cm_kwiml.h" +#include <cm3p/kwiml/int.h> class cmExprParserHelper { diff --git a/Source/cmFileAPI.h b/Source/cmFileAPI.h index e183e0d..ae07612 100644 --- a/Source/cmFileAPI.h +++ b/Source/cmFileAPI.h @@ -11,9 +11,9 @@ #include <unordered_set> #include <vector> -#include "cm_jsoncpp_reader.h" -#include "cm_jsoncpp_value.h" -#include "cm_jsoncpp_writer.h" +#include <cm3p/json/reader.h> +#include <cm3p/json/value.h> +#include <cm3p/json/writer.h> class cmake; diff --git a/Source/cmFileAPICMakeFiles.cxx b/Source/cmFileAPICMakeFiles.cxx index 44ba96c..1e4f3b6 100644 --- a/Source/cmFileAPICMakeFiles.cxx +++ b/Source/cmFileAPICMakeFiles.cxx @@ -6,7 +6,7 @@ #include <string> #include <vector> -#include "cm_jsoncpp_value.h" +#include <cm3p/json/value.h> #include "cmFileAPI.h" #include "cmGlobalGenerator.h" diff --git a/Source/cmFileAPICMakeFiles.h b/Source/cmFileAPICMakeFiles.h index a851c32..1ae1e4f 100644 --- a/Source/cmFileAPICMakeFiles.h +++ b/Source/cmFileAPICMakeFiles.h @@ -5,7 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep -#include "cm_jsoncpp_value.h" +#include <cm3p/json/value.h> class cmFileAPI; diff --git a/Source/cmFileAPICache.cxx b/Source/cmFileAPICache.cxx index 5d2ddf9..25e5916 100644 --- a/Source/cmFileAPICache.cxx +++ b/Source/cmFileAPICache.cxx @@ -7,7 +7,7 @@ #include <utility> #include <vector> -#include "cm_jsoncpp_value.h" +#include <cm3p/json/value.h> #include "cmFileAPI.h" #include "cmState.h" diff --git a/Source/cmFileAPICache.h b/Source/cmFileAPICache.h index 09d9e1c..2f30c76 100644 --- a/Source/cmFileAPICache.h +++ b/Source/cmFileAPICache.h @@ -5,7 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep -#include "cm_jsoncpp_value.h" +#include <cm3p/json/value.h> class cmFileAPI; diff --git a/Source/cmFileAPICodemodel.cxx b/Source/cmFileAPICodemodel.cxx index 26beebf..b7daebe 100644 --- a/Source/cmFileAPICodemodel.cxx +++ b/Source/cmFileAPICodemodel.cxx @@ -17,7 +17,7 @@ #include <cmext/algorithm> -#include "cm_jsoncpp_value.h" +#include <cm3p/json/value.h> #include "cmCryptoHash.h" #include "cmFileAPI.h" diff --git a/Source/cmFileAPICodemodel.h b/Source/cmFileAPICodemodel.h index ffbd928..a6c6bdd 100644 --- a/Source/cmFileAPICodemodel.h +++ b/Source/cmFileAPICodemodel.h @@ -5,7 +5,7 @@ #include "cmConfigure.h" // IWYU pragma: keep -#include "cm_jsoncpp_value.h" +#include <cm3p/json/value.h> class cmFileAPI; diff --git a/Source/cmFileCommand.cxx b/Source/cmFileCommand.cxx index 161bbe8..268c5d1 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -19,11 +19,12 @@ #include <cmext/algorithm> #include <cmext/string_view> +#include <cm3p/kwiml/int.h> + #include "cmsys/FStream.hxx" #include "cmsys/Glob.hxx" #include "cmsys/RegularExpression.hxx" -#include "cm_kwiml.h" #include "cm_sys_stat.h" #include "cmAlgorithms.h" @@ -54,7 +55,7 @@ #include "cmake.h" #if !defined(CMAKE_BOOTSTRAP) -# include "cm_curl.h" +# include <cm3p/curl/curl.h> # include "cmCurl.h" # include "cmFileLockResult.h" @@ -676,12 +677,12 @@ bool HandleGlobImpl(std::vector<std::string> const& args, bool recurse, } } + cmake* cm = status.GetMakefile().GetCMakeInstance(); std::vector<std::string> files; bool configureDepends = false; bool warnConfigureLate = false; bool warnFollowedSymlinks = false; - const cmake::WorkingMode workingMode = - status.GetMakefile().GetCMakeInstance()->GetWorkingMode(); + const cmake::WorkingMode workingMode = cm->GetWorkingMode(); while (i != args.end()) { if (*i == "LIST_DIRECTORIES") { ++i; // skip LIST_DIRECTORIES @@ -769,12 +770,17 @@ bool HandleGlobImpl(std::vector<std::string> const& args, bool recurse, MessageType::AUTHOR_WARNING, "Cyclic recursion detected while globbing for '" + *i + "':\n" + globMessage.content); - } else { + } else if (globMessage.type == cmsys::Glob::error) { status.GetMakefile().IssueMessage( MessageType::FATAL_ERROR, "Error has occurred while globbing for '" + *i + "' - " + globMessage.content); shouldExit = true; + } else if (cm->GetDebugOutput() || cm->GetTrace()) { + status.GetMakefile().IssueMessage( + MessageType::LOG, + cmStrCat("Globbing for\n ", *i, "\nEncountered an error:\n ", + globMessage.content)); } } if (shouldExit) { @@ -794,7 +800,7 @@ bool HandleGlobImpl(std::vector<std::string> const& args, bool recurse, std::sort(foundFiles.begin(), foundFiles.end()); foundFiles.erase(std::unique(foundFiles.begin(), foundFiles.end()), foundFiles.end()); - status.GetMakefile().GetCMakeInstance()->AddGlobCacheEntry( + cm->AddGlobCacheEntry( recurse, (recurse ? g.GetRecurseListDirs() : g.GetListDirs()), (recurse ? g.GetRecurseThroughSymlinks() : false), (g.GetRelative() ? g.GetRelative() : ""), expr, foundFiles, variable, diff --git a/Source/cmFileMonitor.h b/Source/cmFileMonitor.h index b510a2c..fc75b0c 100644 --- a/Source/cmFileMonitor.h +++ b/Source/cmFileMonitor.h @@ -9,7 +9,7 @@ #include <string> #include <vector> -#include "cm_uv.h" +#include <cm3p/uv.h> class cmRootWatcher; diff --git a/Source/cmFindPackageCommand.h b/Source/cmFindPackageCommand.h index ae9ade7..7058a54 100644 --- a/Source/cmFindPackageCommand.h +++ b/Source/cmFindPackageCommand.h @@ -12,7 +12,7 @@ #include <string> #include <vector> -#include "cm_kwiml.h" +#include <cm3p/kwiml/int.h> #include "cmFindCommon.h" #include "cmPolicies.h" diff --git a/Source/cmGeneratedFileStream.cxx b/Source/cmGeneratedFileStream.cxx index f76e205..9cee0e6 100644 --- a/Source/cmGeneratedFileStream.cxx +++ b/Source/cmGeneratedFileStream.cxx @@ -8,8 +8,9 @@ #include "cmSystemTools.h" #if !defined(CMAKE_BOOTSTRAP) +# include <cm3p/zlib.h> + # include "cm_codecvt.hxx" -# include "cm_zlib.h" #endif cmGeneratedFileStream::cmGeneratedFileStream(Encoding encoding) diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 62427f6..f2a51ab 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -238,17 +238,23 @@ EvaluatedTargetPropertyEntry EvaluateTargetPropertyEntry( return ee; } -std::vector<EvaluatedTargetPropertyEntry> EvaluateTargetPropertyEntries( +struct EvaluatedTargetPropertyEntries +{ + std::vector<EvaluatedTargetPropertyEntry> Entries; + bool HadContextSensitiveCondition = false; +}; + +EvaluatedTargetPropertyEntries EvaluateTargetPropertyEntries( cmGeneratorTarget const* thisTarget, std::string const& config, std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker, std::vector<std::unique_ptr<cmGeneratorTarget::TargetPropertyEntry>> const& in) { - std::vector<EvaluatedTargetPropertyEntry> out; - out.reserve(in.size()); + EvaluatedTargetPropertyEntries out; + out.Entries.reserve(in.size()); for (auto& entry : in) { - out.emplace_back(EvaluateTargetPropertyEntry(thisTarget, config, lang, - dagChecker, *entry)); + out.Entries.emplace_back(EvaluateTargetPropertyEntry( + thisTarget, config, lang, dagChecker, *entry)); } return out; } @@ -687,6 +693,7 @@ const char* cmGeneratorTarget::GetFileSuffixInternal( void cmGeneratorTarget::ClearSourcesCache() { + this->AllConfigSources.clear(); this->KindedSourcesMap.clear(); this->LinkImplementationLanguageIsContextDependent = true; this->Objects.clear(); @@ -969,51 +976,12 @@ void cmGeneratorTarget::GetExternalObjects( IMPLEMENT_VISIT(SourceKindExternalObject); } -void cmGeneratorTarget::GetExpectedResxHeaders(std::set<std::string>& headers, - const std::string& config) const -{ - KindedSources const& kinded = this->GetKindedSources(config); - headers = kinded.ExpectedResxHeaders; -} - -void cmGeneratorTarget::GetResxSources(std::vector<cmSourceFile const*>& data, - const std::string& config) const -{ - IMPLEMENT_VISIT(SourceKindResx); -} - -void cmGeneratorTarget::GetAppManifest(std::vector<cmSourceFile const*>& data, - const std::string& config) const -{ - IMPLEMENT_VISIT(SourceKindAppManifest); -} - void cmGeneratorTarget::GetManifests(std::vector<cmSourceFile const*>& data, const std::string& config) const { IMPLEMENT_VISIT(SourceKindManifest); } -void cmGeneratorTarget::GetCertificates(std::vector<cmSourceFile const*>& data, - const std::string& config) const -{ - IMPLEMENT_VISIT(SourceKindCertificate); -} - -void cmGeneratorTarget::GetExpectedXamlHeaders(std::set<std::string>& headers, - const std::string& config) const -{ - KindedSources const& kinded = this->GetKindedSources(config); - headers = kinded.ExpectedXamlHeaders; -} - -void cmGeneratorTarget::GetExpectedXamlSources(std::set<std::string>& srcs, - const std::string& config) const -{ - KindedSources const& kinded = this->GetKindedSources(config); - srcs = kinded.ExpectedXamlSources; -} - std::set<cmLinkItem> const& cmGeneratorTarget::GetUtilityItems() const { if (!this->UtilityItemsDone) { @@ -1033,12 +1001,6 @@ std::set<cmLinkItem> const& cmGeneratorTarget::GetUtilityItems() const return this->UtilityItems; } -void cmGeneratorTarget::GetXamlSources(std::vector<cmSourceFile const*>& data, - const std::string& config) const -{ - IMPLEMENT_VISIT(SourceKindXaml); -} - const std::string& cmGeneratorTarget::GetLocation( const std::string& config) const { @@ -1090,7 +1052,8 @@ const std::string& cmGeneratorTarget::GetLocationForBuild() const } // Now handle the deprecated build-time configuration location. - location = this->GetDirectory(); + std::string const noConfig; + location = this->GetDirectory(noConfig); const char* cfgid = this->Makefile->GetDefinition("CMAKE_CFG_INTDIR"); if (cfgid && strcmp(cfgid, ".") != 0) { location += "/"; @@ -1246,6 +1209,9 @@ std::string cmGeneratorTarget::EvaluateInterfaceProperty( if (cmLinkInterfaceLibraries const* iface = this->GetLinkInterfaceLibraries( context->Config, headTarget, usage_requirements_only)) { + context->HadContextSensitiveCondition = + context->HadContextSensitiveCondition || + iface->HadContextSensitiveCondition; for (cmLinkItem const& lib : iface->Libraries) { // Broken code can have a target in its own link interface. // Don't follow such link interface entries so as not to create a @@ -1333,7 +1299,7 @@ std::string AddSwiftInterfaceIncludeDirectories( void AddSwiftImplicitIncludeDirectories( const cmGeneratorTarget* target, const std::string& config, - std::vector<EvaluatedTargetPropertyEntry>& entries) + EvaluatedTargetPropertyEntries& entries) { if (const auto* libraries = target->GetLinkImplementationLibraries(config)) { cmGeneratorExpressionDAGChecker dag{ target->GetBacktrace(), target, @@ -1357,7 +1323,7 @@ void AddSwiftImplicitIncludeDirectories( config, &dag), entry.Values); - entries.emplace_back(std::move(entry)); + entries.Entries.emplace_back(std::move(entry)); } } } @@ -1368,11 +1334,12 @@ void AddInterfaceEntries(cmGeneratorTarget const* headTarget, std::string const& config, std::string const& prop, std::string const& lang, cmGeneratorExpressionDAGChecker* dagChecker, - std::vector<EvaluatedTargetPropertyEntry>& entries, + EvaluatedTargetPropertyEntries& entries, bool usage_requirements_only = true) { if (cmLinkImplementationLibraries const* impl = headTarget->GetLinkImplementationLibraries(config)) { + entries.HadContextSensitiveCondition = impl->HadContextSensitiveCondition; for (cmLinkImplItem const& lib : impl->Libraries) { if (lib.Target) { EvaluatedTargetPropertyEntry ee(lib, lib.Backtrace); @@ -1386,7 +1353,7 @@ void AddInterfaceEntries(cmGeneratorTarget const* headTarget, prop, &context, dagChecker, usage_requirements_only), ee.Values); ee.ContextDependent = context.HadContextSensitiveCondition; - entries.emplace_back(std::move(ee)); + entries.Entries.emplace_back(std::move(ee)); } } } @@ -1395,10 +1362,11 @@ void AddInterfaceEntries(cmGeneratorTarget const* headTarget, void AddObjectEntries(cmGeneratorTarget const* headTarget, std::string const& config, cmGeneratorExpressionDAGChecker* dagChecker, - std::vector<EvaluatedTargetPropertyEntry>& entries) + EvaluatedTargetPropertyEntries& entries) { if (cmLinkImplementationLibraries const* impl = headTarget->GetLinkImplementationLibraries(config)) { + entries.HadContextSensitiveCondition = impl->HadContextSensitiveCondition; for (cmLinkImplItem const& lib : impl->Libraries) { if (lib.Target && lib.Target->GetType() == cmStateEnums::OBJECT_LIBRARY) { @@ -1417,23 +1385,23 @@ void AddObjectEntries(cmGeneratorTarget const* headTarget, if (cge->GetHadContextSensitiveCondition()) { ee.ContextDependent = true; } - entries.emplace_back(std::move(ee)); + entries.Entries.emplace_back(std::move(ee)); } } } } bool processSources(cmGeneratorTarget const* tgt, - std::vector<EvaluatedTargetPropertyEntry>& entries, + EvaluatedTargetPropertyEntries& entries, std::vector<BT<std::string>>& srcs, std::unordered_set<std::string>& uniqueSrcs, bool debugSources) { cmMakefile* mf = tgt->Target->GetMakefile(); - bool contextDependent = false; + bool contextDependent = entries.HadContextSensitiveCondition; - for (EvaluatedTargetPropertyEntry& entry : entries) { + for (EvaluatedTargetPropertyEntry& entry : entries.Entries) { if (entry.ContextDependent) { contextDependent = true; } @@ -1534,16 +1502,15 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths( cmGeneratorExpressionDAGChecker dagChecker(this, "SOURCES", nullptr, nullptr); - std::vector<EvaluatedTargetPropertyEntry> entries = - EvaluateTargetPropertyEntries(this, config, std::string(), &dagChecker, - this->SourceEntries); + EvaluatedTargetPropertyEntries entries = EvaluateTargetPropertyEntries( + this, config, std::string(), &dagChecker, this->SourceEntries); std::unordered_set<std::string> uniqueSrcs; bool contextDependentDirectSources = processSources(this, entries, files, uniqueSrcs, debugSources); // Collect INTERFACE_SOURCES of all direct link-dependencies. - std::vector<EvaluatedTargetPropertyEntry> linkInterfaceSourcesEntries; + EvaluatedTargetPropertyEntries linkInterfaceSourcesEntries; AddInterfaceEntries(this, config, "INTERFACE_SOURCES", std::string(), &dagChecker, linkInterfaceSourcesEntries); std::vector<std::string>::size_type numFilesBefore = files.size(); @@ -1554,7 +1521,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetSourceFilePaths( bool contextDependentObjects = false; std::vector<std::string>::size_type numFilesBefore2 = files.size(); if (this->GetType() != cmStateEnums::OBJECT_LIBRARY) { - std::vector<EvaluatedTargetPropertyEntry> linkObjectsEntries; + EvaluatedTargetPropertyEntries linkObjectsEntries; AddObjectEntries(this, config, &dagChecker, linkObjectsEntries); contextDependentObjects = processSources(this, linkObjectsEntries, files, uniqueSrcs, debugSources); @@ -1716,14 +1683,6 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files, } } else if (ext == "resx") { kind = SourceKindResx; - // Build and save the name of the corresponding .h file - // This relationship will be used later when building the project files. - // Both names would have been auto generated from Visual Studio - // where the user supplied the file name and Visual Studio - // appended the suffix. - std::string resx = sf->ResolveFullPath(); - std::string hFileName = resx.substr(0, resx.find_last_of('.')) + ".h"; - files.ExpectedResxHeaders.insert(hFileName); } else if (ext == "appxmanifest") { kind = SourceKindAppManifest; } else if (ext == "manifest") { @@ -1732,16 +1691,6 @@ void cmGeneratorTarget::ComputeKindedSources(KindedSources& files, kind = SourceKindCertificate; } else if (ext == "xaml") { kind = SourceKindXaml; - // Build and save the name of the corresponding .h and .cpp file - // This relationship will be used later when building the project files. - // Both names would have been auto generated from Visual Studio - // where the user supplied the file name and Visual Studio - // appended the suffix. - std::string xaml = sf->ResolveFullPath(); - std::string hFileName = xaml + ".h"; - std::string cppFileName = xaml + ".cpp"; - files.ExpectedXamlHeaders.insert(hFileName); - files.ExpectedXamlSources.insert(cppFileName); } else if (header_regex.find(sf->ResolveFullPath())) { kind = SourceKindHeader; } else { @@ -1799,6 +1748,18 @@ void cmGeneratorTarget::ComputeAllConfigSources() const } } +std::vector<cmGeneratorTarget::AllConfigSource> +cmGeneratorTarget::GetAllConfigSources(SourceKind kind) const +{ + std::vector<AllConfigSource> result; + for (AllConfigSource const& source : this->GetAllConfigSources()) { + if (source.Kind == kind) { + result.push_back(source); + } + } + return result; +} + std::set<std::string> cmGeneratorTarget::GetAllConfigCompileLanguages() const { std::set<std::string> languages; @@ -3169,6 +3130,20 @@ void cmGeneratorTarget::AddCUDAArchitectureFlags(std::string& flags) const flags += "]"; } + } else if (compiler == "Clang") { + for (CudaArchitecture& architecture : architectures) { + flags += " --cuda-gpu-arch=sm_" + architecture.name; + + if (!architecture.real) { + Makefile->IssueMessage( + MessageType::WARNING, + "Clang doesn't support disabling CUDA real code generation."); + } + + if (!architecture.virtual_) { + flags += " --no-cuda-include-ptx=sm_" + architecture.name; + } + } } } @@ -3216,13 +3191,13 @@ std::string cmGeneratorTarget::GetCreateRuleVariable( } namespace { -void processIncludeDirectories( - cmGeneratorTarget const* tgt, - std::vector<EvaluatedTargetPropertyEntry>& entries, - std::vector<BT<std::string>>& includes, - std::unordered_set<std::string>& uniqueIncludes, bool debugIncludes) +void processIncludeDirectories(cmGeneratorTarget const* tgt, + EvaluatedTargetPropertyEntries& entries, + std::vector<BT<std::string>>& includes, + std::unordered_set<std::string>& uniqueIncludes, + bool debugIncludes) { - for (EvaluatedTargetPropertyEntry& entry : entries) { + for (EvaluatedTargetPropertyEntry& entry : entries.Entries) { cmLinkImplItem const& item = entry.LinkImplItem; std::string const& targetName = item.AsStr(); bool const fromImported = item.Target && item.Target->IsImported(); @@ -3343,9 +3318,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories( this->DebugIncludesDone = true; } - std::vector<EvaluatedTargetPropertyEntry> entries = - EvaluateTargetPropertyEntries(this, config, lang, &dagChecker, - this->IncludeDirectoriesEntries); + EvaluatedTargetPropertyEntries entries = EvaluateTargetPropertyEntries( + this, config, lang, &dagChecker, this->IncludeDirectoriesEntries); if (lang == "Swift") { AddSwiftImplicitIncludeDirectories(this, config, entries); @@ -3371,7 +3345,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetIncludeDirectories( EvaluatedTargetPropertyEntry ee(lib, cmListFileBacktrace()); ee.Values.emplace_back(std::move(libDir)); - entries.emplace_back(std::move(ee)); + entries.Entries.emplace_back(std::move(ee)); } } @@ -3392,14 +3366,14 @@ const auto DL_BEGIN = "<DEVICE_LINK>"_s; const auto DL_END = "</DEVICE_LINK>"_s; void processOptions(cmGeneratorTarget const* tgt, - std::vector<EvaluatedTargetPropertyEntry> const& entries, + EvaluatedTargetPropertyEntries const& entries, std::vector<BT<std::string>>& options, std::unordered_set<std::string>& uniqueOptions, bool debugOptions, const char* logName, OptionsParse parse, bool processDeviceOptions = false) { bool splitOption = !processDeviceOptions; - for (EvaluatedTargetPropertyEntry const& entry : entries) { + for (EvaluatedTargetPropertyEntry const& entry : entries.Entries) { std::string usedOptions; for (std::string const& opt : entry.Values) { if (processDeviceOptions && (opt == DL_BEGIN || opt == DL_END)) { @@ -3531,9 +3505,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileOptions( this->DebugCompileOptionsDone = true; } - std::vector<EvaluatedTargetPropertyEntry> entries = - EvaluateTargetPropertyEntries(this, config, language, &dagChecker, - this->CompileOptionsEntries); + EvaluatedTargetPropertyEntries entries = EvaluateTargetPropertyEntries( + this, config, language, &dagChecker, this->CompileOptionsEntries); AddInterfaceEntries(this, config, "INTERFACE_COMPILE_OPTIONS", language, &dagChecker, entries); @@ -3577,9 +3550,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileFeatures( this->DebugCompileFeaturesDone = true; } - std::vector<EvaluatedTargetPropertyEntry> entries = - EvaluateTargetPropertyEntries(this, config, std::string(), &dagChecker, - this->CompileFeaturesEntries); + EvaluatedTargetPropertyEntries entries = EvaluateTargetPropertyEntries( + this, config, std::string(), &dagChecker, this->CompileFeaturesEntries); AddInterfaceEntries(this, config, "INTERFACE_COMPILE_FEATURES", std::string(), &dagChecker, entries); @@ -3625,9 +3597,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileDefinitions( this->DebugCompileDefinitionsDone = true; } - std::vector<EvaluatedTargetPropertyEntry> entries = - EvaluateTargetPropertyEntries(this, config, language, &dagChecker, - this->CompileDefinitionsEntries); + EvaluatedTargetPropertyEntries entries = EvaluateTargetPropertyEntries( + this, config, language, &dagChecker, this->CompileDefinitionsEntries); AddInterfaceEntries(this, config, "INTERFACE_COMPILE_DEFINITIONS", language, &dagChecker, entries); @@ -3647,7 +3618,7 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetCompileDefinitions( case cmPolicies::OLD: { std::unique_ptr<TargetPropertyEntry> entry = CreateTargetPropertyEntry(*configProp); - entries.emplace_back(EvaluateTargetPropertyEntry( + entries.Entries.emplace_back(EvaluateTargetPropertyEntry( this, config, language, &dagChecker, *entry)); } break; case cmPolicies::NEW: @@ -3687,9 +3658,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetPrecompileHeaders( this->DebugPrecompileHeadersDone = true; } - std::vector<EvaluatedTargetPropertyEntry> entries = - EvaluateTargetPropertyEntries(this, config, language, &dagChecker, - this->PrecompileHeadersEntries); + EvaluatedTargetPropertyEntries entries = EvaluateTargetPropertyEntries( + this, config, language, &dagChecker, this->PrecompileHeadersEntries); AddInterfaceEntries(this, config, "INTERFACE_PRECOMPILE_HEADERS", language, &dagChecker, entries); @@ -3894,6 +3864,10 @@ std::string cmGeneratorTarget::GetPchFileObject(const std::string& config, pchSource, false, cmSourceFileLocationKind::Known); filename = cmStrCat(this->ObjectDirectory, this->GetObjectName(pchSf)); + if (this->GetGlobalGenerator()->IsMultiConfig()) { + cmSystemTools::ReplaceString( + filename, this->GetGlobalGenerator()->GetCMakeCFGIntDir(), config); + } } return inserted.first->second; } @@ -4064,9 +4038,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkOptions( this->DebugLinkOptionsDone = true; } - std::vector<EvaluatedTargetPropertyEntry> entries = - EvaluateTargetPropertyEntries(this, config, language, &dagChecker, - this->LinkOptionsEntries); + EvaluatedTargetPropertyEntries entries = EvaluateTargetPropertyEntries( + this, config, language, &dagChecker, this->LinkOptionsEntries); AddInterfaceEntries(this, config, "INTERFACE_LINK_OPTIONS", language, &dagChecker, entries, @@ -4205,14 +4178,14 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetStaticLibraryLinkOptions( cmGeneratorExpressionDAGChecker dagChecker(this, "STATIC_LIBRARY_OPTIONS", nullptr, nullptr); - std::vector<EvaluatedTargetPropertyEntry> entries; + EvaluatedTargetPropertyEntries entries; if (cmProp linkOptions = this->GetProperty("STATIC_LIBRARY_OPTIONS")) { std::vector<std::string> options = cmExpandedList(*linkOptions); for (const auto& option : options) { std::unique_ptr<TargetPropertyEntry> entry = CreateTargetPropertyEntry(option); - entries.emplace_back(EvaluateTargetPropertyEntry(this, config, language, - &dagChecker, *entry)); + entries.Entries.emplace_back(EvaluateTargetPropertyEntry( + this, config, language, &dagChecker, *entry)); } } processOptions(this, entries, result, uniqueOptions, false, @@ -4223,12 +4196,12 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetStaticLibraryLinkOptions( namespace { void processLinkDirectories(cmGeneratorTarget const* tgt, - std::vector<EvaluatedTargetPropertyEntry>& entries, + EvaluatedTargetPropertyEntries& entries, std::vector<BT<std::string>>& directories, std::unordered_set<std::string>& uniqueDirectories, bool debugDirectories) { - for (EvaluatedTargetPropertyEntry& entry : entries) { + for (EvaluatedTargetPropertyEntry& entry : entries.Entries) { cmLinkImplItem const& item = entry.LinkImplItem; std::string const& targetName = item.AsStr(); @@ -4327,9 +4300,8 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDirectories( this->DebugLinkDirectoriesDone = true; } - std::vector<EvaluatedTargetPropertyEntry> entries = - EvaluateTargetPropertyEntries(this, config, language, &dagChecker, - this->LinkDirectoriesEntries); + EvaluatedTargetPropertyEntries entries = EvaluateTargetPropertyEntries( + this, config, language, &dagChecker, this->LinkDirectoriesEntries); AddInterfaceEntries(this, config, "INTERFACE_LINK_DIRECTORIES", language, &dagChecker, entries, @@ -4360,14 +4332,14 @@ std::vector<BT<std::string>> cmGeneratorTarget::GetLinkDepends( cmGeneratorExpressionDAGChecker dagChecker(this, "LINK_DEPENDS", nullptr, nullptr); - std::vector<EvaluatedTargetPropertyEntry> entries; + EvaluatedTargetPropertyEntries entries; if (cmProp linkDepends = this->GetProperty("LINK_DEPENDS")) { std::vector<std::string> depends = cmExpandedList(*linkDepends); for (const auto& depend : depends) { std::unique_ptr<TargetPropertyEntry> entry = CreateTargetPropertyEntry(depend); - entries.emplace_back(EvaluateTargetPropertyEntry(this, config, language, - &dagChecker, *entry)); + entries.Entries.emplace_back(EvaluateTargetPropertyEntry( + this, config, language, &dagChecker, *entry)); } } AddInterfaceEntries(this, config, "INTERFACE_LINK_DEPENDS", language, @@ -5738,6 +5710,25 @@ void cmGeneratorTarget::GetTargetVersion(const std::string& property, } } +std::string cmGeneratorTarget::GetRuntimeLinkLibrary( + std::string const& lang, std::string const& config) const +{ + // This is activated by the presence of a default selection whether or + // not it is overridden by a property. + cmProp runtimeLibraryDefault = this->Makefile->GetDef( + cmStrCat("CMAKE_", lang, "_RUNTIME_LIBRARY_DEFAULT")); + if (!runtimeLibraryDefault || runtimeLibraryDefault->empty()) { + return std::string(); + } + cmProp runtimeLibraryValue = + this->Target->GetProperty(cmStrCat(lang, "_RUNTIME_LIBRARY")); + if (!runtimeLibraryValue) { + runtimeLibraryValue = runtimeLibraryDefault; + } + return cmSystemTools::UpperCase(cmGeneratorExpression::Evaluate( + *runtimeLibraryValue, this->LocalGenerator, config, this)); +} + std::string cmGeneratorTarget::GetFortranModuleDirectory( std::string const& working_dir) const { @@ -5885,6 +5876,7 @@ void cmGeneratorTarget::ExpandLinkItems( std::string const& prop, std::string const& value, std::string const& config, cmGeneratorTarget const* headTarget, bool usage_requirements_only, std::vector<cmLinkItem>& items, bool& hadHeadSensitiveCondition, + bool& hadContextSensitiveCondition, bool& hadLinkLanguageSensitiveCondition) const { // Keep this logic in sync with ComputeLinkImplementationLibraries. @@ -5903,6 +5895,7 @@ void cmGeneratorTarget::ExpandLinkItems( libs); this->LookupLinkItems(libs, cge->GetBacktrace(), items); hadHeadSensitiveCondition = cge->GetHadHeadSensitiveCondition(); + hadContextSensitiveCondition = cge->GetHadContextSensitiveCondition(); hadLinkLanguageSensitiveCondition = cge->GetHadLinkLanguageSensitiveCondition(); } @@ -6407,6 +6400,7 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( this->ExpandLinkItems(linkIfaceProp, *explicitLibraries, config, headTarget, usage_requirements_only, iface.Libraries, iface.HadHeadSensitiveCondition, + iface.HadContextSensitiveCondition, iface.HadLinkLanguageSensitiveCondition); } else if (!cmp0022NEW) // If CMP0022 is NEW then the plain tll signature sets the @@ -6427,10 +6421,12 @@ void cmGeneratorTarget::ComputeLinkInterfaceLibraries( static const std::string newProp = "INTERFACE_LINK_LIBRARIES"; if (cmProp newExplicitLibraries = this->GetProperty(newProp)) { bool hadHeadSensitiveConditionDummy = false; + bool hadContextSensitiveConditionDummy = false; bool hadLinkLanguageSensitiveConditionDummy = false; this->ExpandLinkItems(newProp, *newExplicitLibraries, config, headTarget, usage_requirements_only, ifaceLibs, hadHeadSensitiveConditionDummy, + hadContextSensitiveConditionDummy, hadLinkLanguageSensitiveConditionDummy); } if (ifaceLibs != iface.Libraries) { @@ -6498,6 +6494,7 @@ const cmLinkInterface* cmGeneratorTarget::GetImportLinkInterface( this->ExpandLinkItems(info->LibrariesProp, info->Libraries, config, headTarget, usage_requirements_only, iface.Libraries, iface.HadHeadSensitiveCondition, + iface.HadContextSensitiveCondition, iface.HadLinkLanguageSensitiveCondition); std::vector<std::string> deps = cmExpandedList(info->SharedDeps); this->LookupLinkItems(deps, cmListFileBacktrace(), iface.SharedDeps); @@ -7020,6 +7017,9 @@ void cmGeneratorTarget::ComputeLinkImplementationLibraries( if (cge->GetHadHeadSensitiveCondition()) { impl.HadHeadSensitiveCondition = true; } + if (cge->GetHadContextSensitiveCondition()) { + impl.HadContextSensitiveCondition = true; + } if (cge->GetHadLinkLanguageSensitiveCondition()) { impl.HadLinkLanguageSensitiveCondition = true; } diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 2ef7b43..788fa23 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -117,9 +117,6 @@ public: struct KindedSources { std::vector<SourceAndKind> Sources; - std::set<std::string> ExpectedResxHeaders; - std::set<std::string> ExpectedXamlHeaders; - std::set<std::string> ExpectedXamlSources; bool Initialized = false; }; @@ -137,6 +134,9 @@ public: per-source configurations assigned. */ std::vector<AllConfigSource> const& GetAllConfigSources() const; + /** Get all sources needed for all configurations with given kind. */ + std::vector<AllConfigSource> GetAllConfigSources(SourceKind kind) const; + /** Get all languages used to compile sources in any configuration. This excludes the languages of objects from object libraries. */ std::set<std::string> GetAllConfigCompileLanguages() const; @@ -151,8 +151,6 @@ public: void GetModuleDefinitionSources(std::vector<cmSourceFile const*>&, const std::string& config) const; - void GetResxSources(std::vector<cmSourceFile const*>&, - const std::string& config) const; void GetExternalObjects(std::vector<cmSourceFile const*>&, const std::string& config) const; void GetHeaderSources(std::vector<cmSourceFile const*>&, @@ -161,20 +159,8 @@ public: const std::string& config) const; void GetCustomCommands(std::vector<cmSourceFile const*>&, const std::string& config) const; - void GetExpectedResxHeaders(std::set<std::string>&, - const std::string& config) const; - void GetAppManifest(std::vector<cmSourceFile const*>&, - const std::string& config) const; void GetManifests(std::vector<cmSourceFile const*>&, const std::string& config) const; - void GetCertificates(std::vector<cmSourceFile const*>&, - const std::string& config) const; - void GetXamlSources(std::vector<cmSourceFile const*>&, - const std::string& config) const; - void GetExpectedXamlHeaders(std::set<std::string>&, - const std::string& config) const; - void GetExpectedXamlSources(std::set<std::string>&, - const std::string& config) const; std::set<cmLinkItem> const& GetUtilityItems() const; @@ -245,7 +231,7 @@ public: /** Get the full path to the target according to the settings in its makefile and the configuration type. */ std::string GetFullPath( - const std::string& config = "", + const std::string& config, cmStateEnums::ArtifactType artifact = cmStateEnums::RuntimeBinaryArtifact, bool realname = false) const; std::string NormalGetFullPath(const std::string& config, @@ -283,7 +269,7 @@ public: /** Get the full name of the target according to the settings in its makefile. */ - std::string GetFullName(const std::string& config = "", + std::string GetFullName(const std::string& config, cmStateEnums::ArtifactType artifact = cmStateEnums::RuntimeBinaryArtifact) const; @@ -326,8 +312,7 @@ public: std::string GetSOName(const std::string& config) const; void GetFullNameComponents(std::string& prefix, std::string& base, - std::string& suffix, - const std::string& config = "", + std::string& suffix, const std::string& config, cmStateEnums::ArtifactType artifact = cmStateEnums::RuntimeBinaryArtifact) const; @@ -540,7 +525,7 @@ public: configuration name is given then the generator will add its subdirectory for that configuration. Otherwise just the canonical output directory is given. */ - std::string GetDirectory(const std::string& config = "", + std::string GetDirectory(const std::string& config, cmStateEnums::ArtifactType artifact = cmStateEnums::RuntimeBinaryArtifact) const; @@ -548,7 +533,7 @@ public: If the configuration name is given then the generator will add its subdirectory for that configuration. Otherwise just the canonical compiler pdb output directory is given. */ - std::string GetCompilePDBDirectory(const std::string& config = "") const; + std::string GetCompilePDBDirectory(const std::string& config) const; /** Get sources that must be built before the given source. */ std::vector<cmSourceFile*> const* GetSourceDepends( @@ -577,7 +562,7 @@ public: std::string GetPDBOutputName(const std::string& config) const; /** Get the name of the pdb file for the target. */ - std::string GetPDBName(const std::string& config = "") const; + std::string GetPDBName(const std::string& config) const; /** Whether this library has soname enabled and platform supports it. */ bool HasSOName(const std::string& config) const; @@ -595,10 +580,10 @@ public: bool IsNullImpliedByLinkLibraries(const std::string& p) const; /** Get the name of the compiler pdb file for the target. */ - std::string GetCompilePDBName(const std::string& config = "") const; + std::string GetCompilePDBName(const std::string& config) const; /** Get the path for the MSVC /Fd option for this target. */ - std::string GetCompilePDBPath(const std::string& config = "") const; + std::string GetCompilePDBPath(const std::string& config) const; // Get the target base name. std::string GetOutputName(const std::string& config, @@ -798,6 +783,9 @@ public: const std::string& fallback_property, int& major, int& minor, int& patch) const; + std::string GetRuntimeLinkLibrary(std::string const& lang, + std::string const& config) const; + std::string GetFortranModuleDirectory(std::string const& working_dir) const; const std::string& GetSourcesProperty() const; @@ -989,6 +977,7 @@ private: bool usage_requirements_only, std::vector<cmLinkItem>& items, bool& hadHeadSensitiveCondition, + bool& hadContextSensitiveCondition, bool& hadLinkLanguageSensitiveCondition) const; void LookupLinkItems(std::vector<std::string> const& names, cmListFileBacktrace const& bt, diff --git a/Source/cmGetPipes.cxx b/Source/cmGetPipes.cxx index 4eda1c5..a5b6469 100644 --- a/Source/cmGetPipes.cxx +++ b/Source/cmGetPipes.cxx @@ -2,10 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmGetPipes.h" +#include <cm3p/uv.h> #include <fcntl.h> -#include "cm_uv.h" - #if defined(_WIN32) && !defined(__CYGWIN__) # include <io.h> diff --git a/Source/cmGetPropertyCommand.cxx b/Source/cmGetPropertyCommand.cxx index c3ac672..851f426 100644 --- a/Source/cmGetPropertyCommand.cxx +++ b/Source/cmGetPropertyCommand.cxx @@ -11,6 +11,7 @@ #include "cmPolicies.h" #include "cmProperty.h" #include "cmPropertyDefinition.h" +#include "cmSetPropertyCommand.h" #include "cmSourceFile.h" #include "cmState.h" #include "cmStringAlgorithms.h" @@ -48,7 +49,9 @@ bool HandleTargetMode(cmExecutionStatus& status, const std::string& name, const std::string& propertyName); bool HandleSourceMode(cmExecutionStatus& status, const std::string& name, OutType infoType, const std::string& variable, - const std::string& propertyName); + const std::string& propertyName, + cmMakefile& directory_makefile, + bool source_file_paths_should_be_absolute); bool HandleTestMode(cmExecutionStatus& status, const std::string& name, OutType infoType, const std::string& variable, const std::string& propertyName); @@ -78,6 +81,11 @@ bool cmGetPropertyCommand(std::vector<std::string> const& args, std::string name; std::string propertyName; + std::vector<std::string> source_file_directories; + std::vector<std::string> source_file_target_directories; + bool source_file_directory_option_enabled = false; + bool source_file_target_option_enabled = false; + // Get the scope from which to get the property. cmProperty::ScopeType scope; if (args[1] == "GLOBAL") { @@ -111,7 +119,9 @@ bool cmGetPropertyCommand(std::vector<std::string> const& args, DoingNone, DoingName, DoingProperty, - DoingType + DoingType, + DoingSourceDirectory, + DoingSourceTargetDirectory }; Doing doing = DoingName; for (unsigned int i = 2; i < args.size(); ++i) { @@ -132,6 +142,20 @@ bool cmGetPropertyCommand(std::vector<std::string> const& args, } else if (doing == DoingName) { doing = DoingNone; name = args[i]; + } else if (doing == DoingNone && scope == cmProperty::SOURCE_FILE && + args[i] == "DIRECTORY") { + doing = DoingSourceDirectory; + source_file_directory_option_enabled = true; + } else if (doing == DoingNone && scope == cmProperty::SOURCE_FILE && + args[i] == "TARGET_DIRECTORY") { + doing = DoingSourceTargetDirectory; + source_file_target_option_enabled = true; + } else if (doing == DoingSourceDirectory) { + source_file_directories.push_back(args[i]); + doing = DoingNone; + } else if (doing == DoingSourceTargetDirectory) { + source_file_target_directories.push_back(args[i]); + doing = DoingNone; } else if (doing == DoingProperty) { doing = DoingNone; propertyName = args[i]; @@ -147,6 +171,16 @@ bool cmGetPropertyCommand(std::vector<std::string> const& args, return false; } + std::vector<cmMakefile*> source_file_directory_makefiles; + bool file_scopes_handled = + SetPropertyCommand::HandleAndValidateSourceFileDirectortoryScopes( + status, source_file_directory_option_enabled, + source_file_target_option_enabled, source_file_directories, + source_file_target_directories, source_file_directory_makefiles); + if (!file_scopes_handled) { + return false; + } + // Compute requested output. if (infoType == OutBriefDoc) { // Lookup brief documentation. @@ -180,6 +214,11 @@ bool cmGetPropertyCommand(std::vector<std::string> const& args, } } else { // Dispatch property getting. + cmMakefile& directory_scope_mf = *(source_file_directory_makefiles[0]); + bool source_file_paths_should_be_absolute = + source_file_directory_option_enabled || + source_file_target_option_enabled; + switch (scope) { case cmProperty::GLOBAL: return HandleGlobalMode(status, name, infoType, variable, @@ -191,8 +230,9 @@ bool cmGetPropertyCommand(std::vector<std::string> const& args, return HandleTargetMode(status, name, infoType, variable, propertyName); case cmProperty::SOURCE_FILE: - return HandleSourceMode(status, name, infoType, variable, - propertyName); + return HandleSourceMode(status, name, infoType, variable, propertyName, + directory_scope_mf, + source_file_paths_should_be_absolute); case cmProperty::TEST: return HandleTestMode(status, name, infoType, variable, propertyName); case cmProperty::VARIABLE: @@ -331,7 +371,9 @@ bool HandleTargetMode(cmExecutionStatus& status, const std::string& name, bool HandleSourceMode(cmExecutionStatus& status, const std::string& name, OutType infoType, const std::string& variable, - const std::string& propertyName) + const std::string& propertyName, + cmMakefile& directory_makefile, + const bool source_file_paths_should_be_absolute) { if (name.empty()) { status.SetError("not given name for SOURCE scope."); @@ -339,12 +381,17 @@ bool HandleSourceMode(cmExecutionStatus& status, const std::string& name, } // Get the source file. - if (cmSourceFile* sf = status.GetMakefile().GetOrCreateSource(name)) { + const std::string source_file_absolute_path = + SetPropertyCommand::MakeSourceFilePathAbsoluteIfNeeded( + status, name, source_file_paths_should_be_absolute); + if (cmSourceFile* sf = + directory_makefile.GetOrCreateSource(source_file_absolute_path)) { return StoreResult(infoType, status.GetMakefile(), variable, sf->GetPropertyForUser(propertyName)); } status.SetError( - cmStrCat("given SOURCE name that could not be found or created: ", name)); + cmStrCat("given SOURCE name that could not be found or created: ", + source_file_absolute_path)); return false; } diff --git a/Source/cmGetSourceFilePropertyCommand.cxx b/Source/cmGetSourceFilePropertyCommand.cxx index eefdc6c..5395bc8 100644 --- a/Source/cmGetSourceFilePropertyCommand.cxx +++ b/Source/cmGetSourceFilePropertyCommand.cxx @@ -4,35 +4,71 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmSetPropertyCommand.h" #include "cmSourceFile.h" bool cmGetSourceFilePropertyCommand(std::vector<std::string> const& args, cmExecutionStatus& status) { - if (args.size() != 3) { + std::vector<std::string>::size_type args_size = args.size(); + if (args_size != 3 && args_size != 5) { status.SetError("called with incorrect number of arguments"); return false; } + + std::vector<std::string> source_file_directories; + std::vector<std::string> source_file_target_directories; + bool source_file_directory_option_enabled = false; + bool source_file_target_option_enabled = false; + + int property_arg_index = 2; + if (args[2] == "DIRECTORY" && args_size == 5) { + property_arg_index = 4; + source_file_directory_option_enabled = true; + source_file_directories.push_back(args[3]); + } else if (args[2] == "TARGET_DIRECTORY" && args_size == 5) { + property_arg_index = 4; + source_file_target_option_enabled = true; + source_file_target_directories.push_back(args[3]); + } + + std::vector<cmMakefile*> source_file_directory_makefiles; + bool file_scopes_handled = + SetPropertyCommand::HandleAndValidateSourceFileDirectortoryScopes( + status, source_file_directory_option_enabled, + source_file_target_option_enabled, source_file_directories, + source_file_target_directories, source_file_directory_makefiles); + if (!file_scopes_handled) { + return false; + } + std::string const& var = args[0]; - std::string const& file = args[1]; - cmMakefile& mf = status.GetMakefile(); + bool source_file_paths_should_be_absolute = + source_file_directory_option_enabled || source_file_target_option_enabled; + std::string const file = + SetPropertyCommand::MakeSourceFilePathAbsoluteIfNeeded( + status, args[1], source_file_paths_should_be_absolute); + cmMakefile& mf = *source_file_directory_makefiles[0]; cmSourceFile* sf = mf.GetSource(file); // for the location we must create a source file first - if (!sf && args[2] == "LOCATION") { + if (!sf && args[property_arg_index] == "LOCATION") { sf = mf.CreateSource(file); } + if (sf) { const char* prop = nullptr; - if (!args[2].empty()) { - prop = sf->GetPropertyForUser(args[2]); + if (!args[property_arg_index].empty()) { + prop = sf->GetPropertyForUser(args[property_arg_index]); } if (prop) { - mf.AddDefinition(var, prop); + // Set the value on the original Makefile scope, not the scope of the + // requested directory. + status.GetMakefile().AddDefinition(var, prop); return true; } } - mf.AddDefinition(var, "NOTFOUND"); + status.GetMakefile().AddDefinition(var, "NOTFOUND"); return true; } diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index de6a649..0b7ba04 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -52,8 +52,8 @@ #include "cmake.h" #if !defined(CMAKE_BOOTSTRAP) -# include "cm_jsoncpp_value.h" -# include "cm_jsoncpp_writer.h" +# include <cm3p/json/value.h> +# include <cm3p/json/writer.h> # include "cmCryptoHash.h" # include "cmQtAutoGenGlobalInitializer.h" @@ -320,7 +320,7 @@ bool cmGlobalGenerator::CheckTargetsForMissingSources() const } else { for (std::string const& config : configs) { target->GetSourceFiles(srcs, config); - if (srcs.empty()) { + if (!srcs.empty()) { break; } } @@ -2535,7 +2535,7 @@ void cmGlobalGenerator::AddGlobalTarget_EditCache( } GlobalTargetInfo gti; gti.Name = editCacheTargetName; - gti.PerConfig = false; + gti.PerConfig = cmTarget::PerConfig::No; cmCustomCommandLine singleLine; // Use generator preference for the edit_cache rule if it is defined. @@ -2571,7 +2571,7 @@ void cmGlobalGenerator::AddGlobalTarget_RebuildCache( gti.Name = rebuildCacheTargetName; gti.Message = "Running CMake to regenerate build system..."; gti.UsesTerminal = true; - gti.PerConfig = false; + gti.PerConfig = cmTarget::PerConfig::No; cmCustomCommandLine singleLine; singleLine.push_back(cmSystemTools::GetCMakeCommand()); singleLine.push_back("--regenerate-during-build"); diff --git a/Source/cmGlobalGenerator.h b/Source/cmGlobalGenerator.h index a76ab3c..57c7808 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -28,7 +28,7 @@ #include "cmTargetDepend.h" #if !defined(CMAKE_BOOTSTRAP) -# include "cm_jsoncpp_value.h" +# include <cm3p/json/value.h> # include "cmFileLockPool.h" #endif @@ -553,7 +553,7 @@ protected: std::vector<std::string> Depends; std::string WorkingDir; bool UsesTerminal = false; - bool PerConfig = true; + cmTarget::PerConfig PerConfig = cmTarget::PerConfig::Yes; bool StdPipesUTF8 = false; }; diff --git a/Source/cmGlobalNinjaGenerator.cxx b/Source/cmGlobalNinjaGenerator.cxx index 8ef19cc..843b0f4 100644 --- a/Source/cmGlobalNinjaGenerator.cxx +++ b/Source/cmGlobalNinjaGenerator.cxx @@ -12,11 +12,11 @@ #include <cmext/algorithm> #include <cmext/memory> -#include "cmsys/FStream.hxx" +#include <cm3p/json/reader.h> +#include <cm3p/json/value.h> +#include <cm3p/json/writer.h> -#include "cm_jsoncpp_reader.h" -#include "cm_jsoncpp_value.h" -#include "cm_jsoncpp_writer.h" +#include "cmsys/FStream.hxx" #include "cmDocumentationEntry.h" #include "cmFortranParser.h" diff --git a/Source/cmGlobalNinjaGenerator.h b/Source/cmGlobalNinjaGenerator.h index b89fb8f..44e632f 100644 --- a/Source/cmGlobalNinjaGenerator.h +++ b/Source/cmGlobalNinjaGenerator.h @@ -415,6 +415,11 @@ public: std::set<std::string> GetCrossConfigs(const std::string& config) const; + const std::set<std::string>& GetDefaultConfigs() const + { + return this->DefaultConfigs; + } + protected: void Generate() override; diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 5166de6..5dac072 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -6,12 +6,12 @@ #include <cm/memory> +#include <cm3p/json/reader.h> + #include "cmsys/FStream.hxx" #include "cmsys/Glob.hxx" #include "cmsys/RegularExpression.hxx" -#include "cm_jsoncpp_reader.h" - #include "cmAlgorithms.h" #include "cmDocumentationEntry.h" #include "cmGeneratorTarget.h" diff --git a/Source/cmGlobalVisualStudioGenerator.cxx b/Source/cmGlobalVisualStudioGenerator.cxx index 28bd1ca..0932d06 100644 --- a/Source/cmGlobalVisualStudioGenerator.cxx +++ b/Source/cmGlobalVisualStudioGenerator.cxx @@ -112,6 +112,7 @@ void cmGlobalVisualStudioGenerator::WriteSLNHeader(std::ostream& fout) { char utf8bom[] = { char(0xEF), char(0xBB), char(0xBF) }; fout.write(utf8bom, 3); + fout << '\n'; switch (this->Version) { case cmGlobalVisualStudioGenerator::VS9: diff --git a/Source/cmGlobalWatcomWMakeGenerator.cxx b/Source/cmGlobalWatcomWMakeGenerator.cxx index 07e0793..d6a7afa 100644 --- a/Source/cmGlobalWatcomWMakeGenerator.cxx +++ b/Source/cmGlobalWatcomWMakeGenerator.cxx @@ -44,6 +44,16 @@ void cmGlobalWatcomWMakeGenerator::EnableLanguage( this->cmGlobalUnixMakefileGenerator3::EnableLanguage(l, mf, optional); } +bool cmGlobalWatcomWMakeGenerator::SetSystemName(std::string const& s, + cmMakefile* mf) +{ + if (mf->GetSafeDefinition("CMAKE_SYSTEM_PROCESSOR") == "I86") { + mf->AddDefinition("CMAKE_GENERATOR_CC", "wcl"); + mf->AddDefinition("CMAKE_GENERATOR_CXX", "wcl"); + } + return this->cmGlobalUnixMakefileGenerator3::SetSystemName(s, mf); +} + void cmGlobalWatcomWMakeGenerator::GetDocumentation( cmDocumentationEntry& entry) { diff --git a/Source/cmGlobalWatcomWMakeGenerator.h b/Source/cmGlobalWatcomWMakeGenerator.h index c0daf8a..c47127f 100644 --- a/Source/cmGlobalWatcomWMakeGenerator.h +++ b/Source/cmGlobalWatcomWMakeGenerator.h @@ -41,6 +41,9 @@ public: /** Get the documentation entry for this generator. */ static void GetDocumentation(cmDocumentationEntry& entry); + /** Tell the generator about the target system. */ + bool SetSystemName(std::string const& s, cmMakefile* mf) override; + /** * Try to determine system information such as shared library * extension, pthreads, byte order etc. diff --git a/Source/cmJsonObjects.h b/Source/cmJsonObjects.h index 64291cc..2fd4b26 100644 --- a/Source/cmJsonObjects.h +++ b/Source/cmJsonObjects.h @@ -8,7 +8,7 @@ #include <string> #include <vector> -#include "cm_jsoncpp_value.h" +#include <cm3p/json/value.h> class cmake; class cmGlobalGenerator; diff --git a/Source/cmLinkItem.h b/Source/cmLinkItem.h index f27648c..3d92935 100644 --- a/Source/cmLinkItem.h +++ b/Source/cmLinkItem.h @@ -54,6 +54,9 @@ struct cmLinkImplementationLibraries // Libraries linked directly in other configurations. // Needed only for OLD behavior of CMP0003. std::vector<cmLinkItem> WrongConfigLibraries; + + // Whether the list depends on a genex referencing the configuration. + bool HadContextSensitiveCondition = false; }; struct cmLinkInterfaceLibraries @@ -63,6 +66,9 @@ struct cmLinkInterfaceLibraries // Whether the list depends on a genex referencing the head target. bool HadHeadSensitiveCondition = false; + + // Whether the list depends on a genex referencing the configuration. + bool HadContextSensitiveCondition = false; }; struct cmLinkInterface : public cmLinkInterfaceLibraries diff --git a/Source/cmLocalGenerator.cxx b/Source/cmLocalGenerator.cxx index b862449..ad1cbd8 100644 --- a/Source/cmLocalGenerator.cxx +++ b/Source/cmLocalGenerator.cxx @@ -2633,7 +2633,9 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) // Exclude the pch files from linking if (this->Makefile->IsOn("CMAKE_LINK_PCH")) { if (!ReuseFrom) { - pch_sf->SetProperty("OBJECT_OUTPUTS", pchFile.c_str()); + pch_sf->AppendProperty( + "OBJECT_OUTPUTS", + cmStrCat("$<$<CONFIG:", config, ">:", pchFile, ">")); } else { auto reuseTarget = this->GlobalGenerator->FindGeneratorTarget(*ReuseFrom); @@ -2732,9 +2734,11 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) std::string pchSourceObj = reuseTarget->GetPchFileObject(config, lang, arch); + const std::string configUpper = cmSystemTools::UpperCase(config); + // Link to the pch object file target->Target->AppendProperty( - "LINK_FLAGS", + cmStrCat("LINK_FLAGS_", configUpper), cmStrCat(" ", this->ConvertToOutputFormat(pchSourceObj, SHELL)), true); @@ -2756,6 +2760,120 @@ void cmLocalGenerator::AddPchDependencies(cmGeneratorTarget* target) } } +namespace { + +inline void RegisterUnitySources(cmGeneratorTarget* target, cmSourceFile* sf, + std::string const& filename) +{ + target->AddSourceFileToUnityBatch(sf->ResolveFullPath()); + sf->SetProperty("UNITY_SOURCE_FILE", filename.c_str()); +} + +inline void IncludeFileInUnitySources(cmGeneratedFileStream& unity_file, + std::string const& sf_full_path, + cmProp beforeInclude, + cmProp afterInclude) +{ + if (beforeInclude) { + unity_file << *beforeInclude << "\n"; + } + + unity_file << "#include \"" << sf_full_path << "\"\n"; + + if (afterInclude) { + unity_file << *afterInclude << "\n"; + } +} + +std::vector<std::string> AddUnityFilesModeAuto( + cmGeneratorTarget* target, std::string const& lang, + std::vector<cmSourceFile*> const& filtered_sources, cmProp beforeInclude, + cmProp afterInclude, std::string const& filename_base, size_t batchSize) +{ + if (batchSize == 0) { + batchSize = filtered_sources.size(); + } + + std::vector<std::string> unity_files; + for (size_t itemsLeft = filtered_sources.size(), chunk, batch = 0; + itemsLeft > 0; itemsLeft -= chunk, ++batch) { + + chunk = std::min(itemsLeft, batchSize); + + std::string filename = cmStrCat(filename_base, "unity_", batch, + (lang == "C") ? "_c.c" : "_cxx.cxx"); + + const std::string filename_tmp = cmStrCat(filename, ".tmp"); + { + size_t begin = batch * batchSize; + size_t end = begin + chunk; + + cmGeneratedFileStream file( + filename_tmp, false, + target->GetGlobalGenerator()->GetMakefileEncoding()); + file << "/* generated by CMake */\n\n"; + + for (; begin != end; ++begin) { + cmSourceFile* sf = filtered_sources[begin]; + RegisterUnitySources(target, sf, filename); + IncludeFileInUnitySources(file, sf->ResolveFullPath(), beforeInclude, + afterInclude); + } + } + cmSystemTools::MoveFileIfDifferent(filename_tmp, filename); + unity_files.emplace_back(std::move(filename)); + } + return unity_files; +} + +std::vector<std::string> AddUnityFilesModeGroup( + cmGeneratorTarget* target, std::string const& lang, + std::vector<cmSourceFile*> const& filtered_sources, cmProp beforeInclude, + cmProp afterInclude, std::string const& filename_base) +{ + std::vector<std::string> unity_files; + + // sources organized by group name. Drop any source + // without a group + std::unordered_map<std::string, std::vector<cmSourceFile*>> explicit_mapping; + for (cmSourceFile* sf : filtered_sources) { + if (cmProp value = sf->GetProperty("UNITY_GROUP")) { + auto i = explicit_mapping.find(*value); + if (i == explicit_mapping.end()) { + std::vector<cmSourceFile*> sources{ sf }; + explicit_mapping.emplace(*value, sources); + } else { + i->second.emplace_back(sf); + } + } + } + + for (auto const& item : explicit_mapping) { + auto const& name = item.first; + std::string filename = cmStrCat(filename_base, "unity_", name, + (lang == "C") ? "_c.c" : "_cxx.cxx"); + + const std::string filename_tmp = cmStrCat(filename, ".tmp"); + { + cmGeneratedFileStream file( + filename_tmp, false, + target->GetGlobalGenerator()->GetMakefileEncoding()); + file << "/* generated by CMake */\n\n"; + + for (cmSourceFile* sf : item.second) { + RegisterUnitySources(target, sf, filename); + IncludeFileInUnitySources(file, sf->ResolveFullPath(), beforeInclude, + afterInclude); + } + } + cmSystemTools::MoveFileIfDifferent(filename_tmp, filename); + unity_files.emplace_back(std::move(filename)); + } + + return unity_files; +} +} + void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target) { if (!target->GetPropertyAsBool("UNITY_BUILD")) { @@ -2784,6 +2902,7 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target) cmProp beforeInclude = target->GetProperty("UNITY_BUILD_CODE_BEFORE_INCLUDE"); cmProp afterInclude = target->GetProperty("UNITY_BUILD_CODE_AFTER_INCLUDE"); + cmProp unityMode = target->GetProperty("UNITY_BUILD_MODE"); for (std::string lang : { "C", "CXX" }) { std::vector<cmSourceFile*> filtered_sources; @@ -2798,53 +2917,28 @@ void cmLocalGenerator::AddUnityBuild(cmGeneratorTarget* target) !sf->GetProperty("INCLUDE_DIRECTORIES"); }); - size_t batchSize = unityBatchSize; - if (unityBatchSize == 0) { - batchSize = filtered_sources.size(); + std::vector<std::string> unity_files; + if (!unityMode || *unityMode == "BATCH") { + unity_files = + AddUnityFilesModeAuto(target, lang, filtered_sources, beforeInclude, + afterInclude, filename_base, unityBatchSize); + } else if (unityMode && *unityMode == "GROUP") { + unity_files = + AddUnityFilesModeGroup(target, lang, filtered_sources, beforeInclude, + afterInclude, filename_base); + } else { + // unity mode is set to an unsupported value + std::string e("Invalid UNITY_BUILD_MODE value of " + *unityMode + + " assigned to target " + target->GetName() + + ". Acceptable values are BATCH and GROUP."); + this->IssueMessage(MessageType::FATAL_ERROR, e); } - for (size_t itemsLeft = filtered_sources.size(), chunk, batch = 0; - itemsLeft > 0; itemsLeft -= chunk, ++batch) { - - chunk = std::min(itemsLeft, batchSize); - - std::string filename = cmStrCat(filename_base, "unity_", batch, - (lang == "C") ? "_c.c" : "_cxx.cxx"); - - const std::string filename_tmp = cmStrCat(filename, ".tmp"); - { - size_t begin = batch * batchSize; - size_t end = begin + chunk; - - cmGeneratedFileStream file( - filename_tmp, false, - this->GetGlobalGenerator()->GetMakefileEncoding()); - file << "/* generated by CMake */\n\n"; - - for (; begin != end; ++begin) { - cmSourceFile* sf = filtered_sources[begin]; - - target->AddSourceFileToUnityBatch(sf->ResolveFullPath()); - sf->SetProperty("UNITY_SOURCE_FILE", filename.c_str()); - - if (beforeInclude) { - file << *beforeInclude << "\n"; - } - - file << "#include \"" << sf->ResolveFullPath() << "\"\n"; - - if (afterInclude) { - file << *afterInclude << "\n"; - } - } - } - cmSystemTools::MoveFileIfDifferent(filename_tmp, filename); - - target->AddSource(filename, true); - - auto unity = this->Makefile->GetOrCreateSource(filename); + for (auto const& file : unity_files) { + auto unity = this->GetMakefile()->GetOrCreateSource(file); + target->AddSource(file, true); unity->SetProperty("SKIP_UNITY_BUILD_INCLUSION", "ON"); - unity->SetProperty("UNITY_SOURCE_FILE", filename.c_str()); + unity->SetProperty("UNITY_SOURCE_FILE", file.c_str()); } } } diff --git a/Source/cmLocalGenerator.h b/Source/cmLocalGenerator.h index 1492304..9beae61 100644 --- a/Source/cmLocalGenerator.h +++ b/Source/cmLocalGenerator.h @@ -13,7 +13,7 @@ #include <unordered_map> #include <vector> -#include "cm_kwiml.h" +#include <cm3p/kwiml/int.h> #include "cmCustomCommandTypes.h" #include "cmListFileCache.h" diff --git a/Source/cmLocalNinjaGenerator.cxx b/Source/cmLocalNinjaGenerator.cxx index d1944a4..e52e0d3 100644 --- a/Source/cmLocalNinjaGenerator.cxx +++ b/Source/cmLocalNinjaGenerator.cxx @@ -97,6 +97,43 @@ void cmLocalNinjaGenerator::Generate() if (target->Target->IsPerConfig()) { for (auto const& config : this->GetConfigNames()) { tg->Generate(config); + if (target->GetType() == cmStateEnums::GLOBAL_TARGET && + this->GetGlobalGenerator()->IsMultiConfig()) { + cmNinjaBuild phonyAlias("phony"); + this->GetGlobalNinjaGenerator()->AppendTargetOutputs( + target.get(), phonyAlias.Outputs, ""); + this->GetGlobalNinjaGenerator()->AppendTargetOutputs( + target.get(), phonyAlias.ExplicitDeps, config); + this->GetGlobalNinjaGenerator()->WriteBuild( + *this->GetGlobalNinjaGenerator()->GetConfigFileStream(config), + phonyAlias); + } + } + if (target->GetType() == cmStateEnums::GLOBAL_TARGET && + this->GetGlobalGenerator()->IsMultiConfig()) { + if (!this->GetGlobalNinjaGenerator()->GetDefaultConfigs().empty()) { + cmNinjaBuild phonyAlias("phony"); + this->GetGlobalNinjaGenerator()->AppendTargetOutputs( + target.get(), phonyAlias.Outputs, ""); + for (auto const& config : + this->GetGlobalNinjaGenerator()->GetDefaultConfigs()) { + this->GetGlobalNinjaGenerator()->AppendTargetOutputs( + target.get(), phonyAlias.ExplicitDeps, config); + } + this->GetGlobalNinjaGenerator()->WriteBuild( + *this->GetGlobalNinjaGenerator()->GetDefaultFileStream(), + phonyAlias); + } + cmNinjaBuild phonyAlias("phony"); + this->GetGlobalNinjaGenerator()->AppendTargetOutputs( + target.get(), phonyAlias.Outputs, "all"); + for (auto const& config : this->GetConfigNames()) { + this->GetGlobalNinjaGenerator()->AppendTargetOutputs( + target.get(), phonyAlias.ExplicitDeps, config); + } + this->GetGlobalNinjaGenerator()->WriteBuild( + *this->GetGlobalNinjaGenerator()->GetDefaultFileStream(), + phonyAlias); } } else { tg->Generate(""); diff --git a/Source/cmLocalVisualStudio10Generator.cxx b/Source/cmLocalVisualStudio10Generator.cxx index 02e2c6d..9076e26 100644 --- a/Source/cmLocalVisualStudio10Generator.cxx +++ b/Source/cmLocalVisualStudio10Generator.cxx @@ -4,7 +4,7 @@ #include <cmext/algorithm> -#include "cm_expat.h" +#include <cm3p/expat.h> #include "cmAlgorithms.h" #include "cmGeneratorTarget.h" diff --git a/Source/cmLocalVisualStudio7Generator.cxx b/Source/cmLocalVisualStudio7Generator.cxx index e18fac3..5d50e2d 100644 --- a/Source/cmLocalVisualStudio7Generator.cxx +++ b/Source/cmLocalVisualStudio7Generator.cxx @@ -7,10 +7,9 @@ #include <windows.h> +#include <cm3p/expat.h> #include <ctype.h> // for isspace -#include "cm_expat.h" - #include "cmComputeLinkInformation.h" #include "cmCustomCommand.h" #include "cmCustomCommandGenerator.h" @@ -284,6 +283,7 @@ void cmLocalVisualStudio7Generator::WriteConfigurations( } cmVS7FlagTable cmLocalVisualStudio7GeneratorFortranFlagTable[] = { { "Preprocess", "fpp", "Run Preprocessor on files", "preprocessYes", 0 }, + { "Preprocess", "nofpp", "Run Preprocessor on files", "preprocessNo", 0 }, { "SuppressStartupBanner", "nologo", "SuppressStartupBanner", "true", 0 }, { "SourceFileFormat", "fixed", "Use Fixed Format", "fileFormatFixed", 0 }, { "SourceFileFormat", "free", "Use Free Format", "fileFormatFree", 0 }, @@ -682,6 +682,18 @@ void cmLocalVisualStudio7Generator::WriteConfiguration( default: break; } + + switch (cmOutputConverter::GetFortranPreprocess( + target->GetSafeProperty("Fortran_PREPROCESS"))) { + case cmOutputConverter::FortranPreprocess::Needed: + flags += " -fpp"; + break; + case cmOutputConverter::FortranPreprocess::NotNeeded: + flags += " -nofpp"; + break; + default: + break; + } } // Get preprocessor definitions for this directory. @@ -1474,6 +1486,20 @@ cmLocalVisualStudio7GeneratorFCInfo::cmLocalVisualStudio7GeneratorFCInfo( } if (lg->FortranProject) { + switch (cmOutputConverter::GetFortranPreprocess( + sf.GetSafeProperty("Fortran_PREPROCESS"))) { + case cmOutputConverter::FortranPreprocess::Needed: + fc.CompileFlags = cmStrCat("-fpp ", fc.CompileFlags); + needfc = true; + break; + case cmOutputConverter::FortranPreprocess::NotNeeded: + fc.CompileFlags = cmStrCat("-nofpp ", fc.CompileFlags); + needfc = true; + break; + default: + break; + } + switch (cmOutputConverter::GetFortranFormat( sf.GetSafeProperty("Fortran_FORMAT"))) { case cmOutputConverter::FortranFormatFixed: diff --git a/Source/cmMakefile.cxx b/Source/cmMakefile.cxx index 6c46353..154da50 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -20,11 +20,12 @@ #include <cmext/algorithm> #include <cmext/string_view> +#include <cm3p/json/value.h> +#include <cm3p/json/writer.h> + #include "cmsys/FStream.hxx" #include "cmsys/RegularExpression.hxx" -#include "cm_jsoncpp_value.h" -#include "cm_jsoncpp_writer.h" #include "cm_sys_stat.h" #include "cmCommandArgumentParserHelper.h" @@ -2080,11 +2081,11 @@ 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, true)) - .first; + auto it = this->Targets + .emplace(name, + cmTarget(name, type, cmTarget::VisibilityNormal, this, + cmTarget::PerConfig::Yes)) + .first; this->OrderedTargets.push_back(&it->second); this->GetGlobalGenerator()->IndexTarget(&it->second); this->GetStateSnapshot().GetDirectory().AddNormalTargetName(name); @@ -2403,11 +2404,11 @@ cmSourceGroup* cmMakefile::GetOrCreateSourceGroup( cmSourceGroup* cmMakefile::GetOrCreateSourceGroup(const std::string& name) { - const char* delimiter = this->GetDefinition("SOURCE_GROUP_DELIMITER"); - if (delimiter == nullptr) { - delimiter = "\\"; + const char* delimiters = this->GetDefinition("SOURCE_GROUP_DELIMITER"); + if (delimiters == nullptr) { + delimiters = "/\\"; } - return this->GetOrCreateSourceGroup(cmTokenize(name, delimiter)); + return this->GetOrCreateSourceGroup(cmTokenize(name, delimiters)); } /** @@ -4260,7 +4261,7 @@ cmTarget* cmMakefile::AddImportedTarget(const std::string& name, new cmTarget(name, type, global ? cmTarget::VisibilityImportedGlobally : cmTarget::VisibilityImported, - this, true)); + this, cmTarget::PerConfig::Yes)); // Add to the set of available imported targets. this->ImportedTargets[name] = target.get(); diff --git a/Source/cmMakefileProfilingData.cxx b/Source/cmMakefileProfilingData.cxx index adf4eee..e0150dc 100644 --- a/Source/cmMakefileProfilingData.cxx +++ b/Source/cmMakefileProfilingData.cxx @@ -6,12 +6,12 @@ #include <stdexcept> #include <vector> +#include <cm3p/json/value.h> +#include <cm3p/json/writer.h> + #include "cmsys/FStream.hxx" #include "cmsys/SystemInformation.hxx" -#include "cm_jsoncpp_value.h" -#include "cm_jsoncpp_writer.h" - #include "cmListFileCache.h" #include "cmStringAlgorithms.h" #include "cmSystemTools.h" diff --git a/Source/cmMakefileTargetGenerator.cxx b/Source/cmMakefileTargetGenerator.cxx index 5f0cfcf..c98e3a9 100644 --- a/Source/cmMakefileTargetGenerator.cxx +++ b/Source/cmMakefileTargetGenerator.cxx @@ -541,6 +541,7 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( // Add Fortran format flags. if (lang == "Fortran") { this->AppendFortranFormatFlags(flags, source); + this->AppendFortranPreprocessFlags(flags, source); } // Add flags from source file properties. @@ -895,9 +896,14 @@ void cmMakefileTargetGenerator::WriteObjectRuleFiles( // Check for extra outputs created by the compilation. std::vector<std::string> outputs(1, relativeObj); if (cmProp extra_outputs_str = source.GetProperty("OBJECT_OUTPUTS")) { - // Register these as extra files to clean. - cmExpandList(*extra_outputs_str, outputs); - this->CleanFiles.insert(outputs.begin() + 1, outputs.end()); + std::string evaluated_outputs = cmGeneratorExpression::Evaluate( + *extra_outputs_str, this->LocalGenerator, config); + + if (!evaluated_outputs.empty()) { + // Register these as extra files to clean. + cmExpandList(evaluated_outputs, outputs); + this->CleanFiles.insert(outputs.begin() + 1, outputs.end()); + } } // Write the rule. diff --git a/Source/cmMathCommand.cxx b/Source/cmMathCommand.cxx index f11b906..56221bf 100644 --- a/Source/cmMathCommand.cxx +++ b/Source/cmMathCommand.cxx @@ -4,7 +4,7 @@ #include <cstdio> -#include "cm_kwiml.h" +#include <cm3p/kwiml/int.h> #include "cmExecutionStatus.h" #include "cmExprParserHelper.h" diff --git a/Source/cmNinjaNormalTargetGenerator.cxx b/Source/cmNinjaNormalTargetGenerator.cxx index db069ed..f87eba7 100644 --- a/Source/cmNinjaNormalTargetGenerator.cxx +++ b/Source/cmNinjaNormalTargetGenerator.cxx @@ -1024,7 +1024,7 @@ void cmNinjaNormalTargetGenerator::WriteLinkStatement( std::string prefix; std::string base; std::string suffix; - gt->GetFullNameComponents(prefix, base, suffix); + gt->GetFullNameComponents(prefix, base, suffix, config); std::string dbg_suffix = ".dbg"; // TODO: Where to document? if (mf->GetDefinition("CMAKE_DEBUG_SYMBOL_SUFFIX")) { diff --git a/Source/cmNinjaTargetGenerator.cxx b/Source/cmNinjaTargetGenerator.cxx index 0606484..c77a85b 100644 --- a/Source/cmNinjaTargetGenerator.cxx +++ b/Source/cmNinjaTargetGenerator.cxx @@ -14,8 +14,8 @@ #include <cm/memory> #include <cmext/algorithm> -#include "cm_jsoncpp_value.h" -#include "cm_jsoncpp_writer.h" +#include <cm3p/json/value.h> +#include <cm3p/json/writer.h> #include "cmComputeLinkInformation.h" #include "cmCustomCommandGenerator.h" @@ -106,7 +106,16 @@ std::string cmNinjaTargetGenerator::LanguagePreprocessRule( std::string const& lang, const std::string& config) const { return cmStrCat( - lang, "_PREPROCESS__", + lang, "_PREPROCESS_SCAN__", + cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()), + '_', config); +} + +std::string cmNinjaTargetGenerator::LanguageDependencyRule( + std::string const& lang, const std::string& config) const +{ + return cmStrCat( + lang, "_SCAN__", cmGlobalNinjaGenerator::EncodeRuleName(this->GeneratorTarget->GetName()), '_', config); } @@ -183,6 +192,7 @@ std::string cmNinjaTargetGenerator::ComputeFlagsForObject( // Add Fortran format flags. if (language == "Fortran") { this->AppendFortranFormatFlags(flags, *source); + this->AppendFortranPreprocessFlags(flags, *source); } // Add source file specific flags. @@ -508,6 +518,91 @@ void cmNinjaTargetGenerator::WriteLanguageRules(const std::string& language, this->WriteCompileRule(language, config); } +namespace { +// Create the command to run the dependency scanner +std::string GetScanCommand(const std::string& cmakeCmd, const std::string& tdi, + const std::string& lang, const std::string& ppFile, + bool needDyndep, const std::string& ddiFile) +{ + std::string ccmd = + cmStrCat(cmakeCmd, " -E cmake_ninja_depends --tdi=", tdi, " --lang=", lang, + " --pp=", ppFile, " --dep=$DEP_FILE"); + if (needDyndep) { + ccmd = cmStrCat(ccmd, " --obj=$OBJ_FILE --ddi=", ddiFile); + } + return ccmd; +} + +// Helper function to create dependency scanning rule, with optional +// explicit preprocessing step if preprocessCommand is non-empty +cmNinjaRule GetPreprocessScanRule( + const std::string& ruleName, cmRulePlaceholderExpander::RuleVariables& vars, + const std::string& responseFlag, const std::string& flags, + const std::string& launcher, + cmRulePlaceholderExpander* const rulePlaceholderExpander, + std::string scanCommand, cmLocalNinjaGenerator* generator, + const std::string& preprocessCommand = "") +{ + cmNinjaRule rule(ruleName); + // Explicit preprocessing always uses a depfile. + rule.DepType = ""; // no deps= for multiple outputs + rule.DepFile = "$DEP_FILE"; + + cmRulePlaceholderExpander::RuleVariables ppVars; + ppVars.CMTargetName = vars.CMTargetName; + ppVars.CMTargetType = vars.CMTargetType; + ppVars.Language = vars.Language; + ppVars.Object = "$out"; // for RULE_LAUNCH_COMPILE + ppVars.PreprocessedSource = "$out"; + ppVars.DependencyFile = rule.DepFile.c_str(); + + // Preprocessing uses the original source, compilation uses + // preprocessed output or original source + ppVars.Source = vars.Source; + vars.Source = "$in"; + + // Copy preprocessor definitions to the preprocessor rule. + ppVars.Defines = vars.Defines; + + // Copy include directories to the preprocessor rule. The Fortran + // compilation rule still needs them for the INCLUDE directive. + ppVars.Includes = vars.Includes; + + // Preprocessing and compilation use the same flags. + std::string ppFlags = flags; + + // If using a response file, move defines, includes, and flags into it. + if (!responseFlag.empty()) { + rule.RspFile = "$RSP_FILE"; + rule.RspContent = + cmStrCat(' ', ppVars.Defines, ' ', ppVars.Includes, ' ', ppFlags); + ppFlags = cmStrCat(responseFlag, rule.RspFile); + ppVars.Defines = ""; + ppVars.Includes = ""; + } + + ppVars.Flags = ppFlags.c_str(); + + // Rule for preprocessing source file. + std::vector<std::string> ppCmds; + + if (!preprocessCommand.empty()) { + // Lookup the explicit preprocessing rule. + cmExpandList(preprocessCommand, ppCmds); + for (std::string& i : ppCmds) { + i = cmStrCat(launcher, i); + rulePlaceholderExpander->ExpandRuleVariables(generator, i, ppVars); + } + } + + // Run CMake dependency scanner on either preprocessed output or source file + ppCmds.emplace_back(std::move(scanCommand)); + rule.Command = generator->BuildCommandLine(ppCmds); + + return rule; +} +} + void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, const std::string& config) { @@ -565,82 +660,42 @@ void cmNinjaTargetGenerator::WriteCompileRule(const std::string& lang, cmSystemTools::GetCMakeCommand(), cmLocalGenerator::SHELL); if (explicitPP) { - cmNinjaRule rule(this->LanguagePreprocessRule(lang, config)); - // Explicit preprocessing always uses a depfile. - rule.DepType = ""; // no deps= for multiple outputs - rule.DepFile = "$DEP_FILE"; + // Combined preprocessing and dependency scanning + const auto ppScanCommand = GetScanCommand( + cmakeCmd, tdi, lang, "$out", needDyndep, "$DYNDEP_INTERMEDIATE_FILE"); + const auto ppVar = cmStrCat("CMAKE_", lang, "_PREPROCESS_SOURCE"); - cmRulePlaceholderExpander::RuleVariables ppVars; - ppVars.CMTargetName = vars.CMTargetName; - ppVars.CMTargetType = vars.CMTargetType; - ppVars.Language = vars.Language; - ppVars.Object = "$out"; // for RULE_LAUNCH_COMPILE - ppVars.PreprocessedSource = "$out"; - ppVars.DependencyFile = rule.DepFile.c_str(); + auto ppRule = GetPreprocessScanRule( + this->LanguagePreprocessRule(lang, config), vars, responseFlag, flags, + launcher, rulePlaceholderExpander.get(), ppScanCommand, + this->GetLocalGenerator(), mf->GetRequiredDefinition(ppVar)); - // Preprocessing uses the original source, - // compilation uses preprocessed output. - ppVars.Source = vars.Source; - vars.Source = "$in"; + // Write the rule for preprocessing file of the given language. + ppRule.Comment = cmStrCat("Rule for preprocessing ", lang, " files."); + ppRule.Description = cmStrCat("Building ", lang, " preprocessed $out"); - // Preprocessing and compilation use the same flags. - std::string ppFlags = flags; + this->GetGlobalGenerator()->AddRule(ppRule); if (!compilePPWithDefines) { - // Move preprocessor definitions to the preprocessor rule. - ppVars.Defines = vars.Defines; + // Remove preprocessor definitions from compilation step vars.Defines = ""; - } else { - // Copy preprocessor definitions to the preprocessor rule. - ppVars.Defines = vars.Defines; } - // Copy include directories to the preprocessor rule. The Fortran - // compilation rule still needs them for the INCLUDE directive. - ppVars.Includes = vars.Includes; - - // If using a response file, move defines, includes, and flags into it. - if (!responseFlag.empty()) { - rule.RspFile = "$RSP_FILE"; - rule.RspContent = - cmStrCat(' ', ppVars.Defines, ' ', ppVars.Includes, ' ', ppFlags); - ppFlags = cmStrCat(responseFlag, rule.RspFile); - ppVars.Defines = ""; - ppVars.Includes = ""; - } + // Just dependency scanning for files that have preprocessing turned off + const auto scanCommand = + GetScanCommand(cmakeCmd, tdi, lang, "$in", needDyndep, "$out"); - ppVars.Flags = ppFlags.c_str(); + auto scanRule = GetPreprocessScanRule( + this->LanguageDependencyRule(lang, config), vars, "", flags, launcher, + rulePlaceholderExpander.get(), scanCommand, this->GetLocalGenerator()); - // Rule for preprocessing source file. - std::vector<std::string> ppCmds; - { - // Lookup the explicit preprocessing rule. - std::string ppVar = cmStrCat("CMAKE_", lang, "_PREPROCESS_SOURCE"); - cmExpandList(this->GetMakefile()->GetRequiredDefinition(ppVar), ppCmds); - } + // Write the rule for generating dependencies for the given language. + scanRule.Comment = cmStrCat("Rule for generating ", lang, + " dependencies on non-preprocessed files."); + scanRule.Description = + cmStrCat("Generating ", lang, " dependencies for $in"); - for (std::string& i : ppCmds) { - i = cmStrCat(launcher, i); - rulePlaceholderExpander->ExpandRuleVariables(this->GetLocalGenerator(), - i, ppVars); - } - - // Run CMake dependency scanner on preprocessed output. - { - std::string ccmd = - cmStrCat(cmakeCmd, " -E cmake_ninja_depends --tdi=", tdi, - " --lang=", lang, " --pp=$out --dep=$DEP_FILE"); - if (needDyndep) { - ccmd += " --obj=$OBJ_FILE --ddi=$DYNDEP_INTERMEDIATE_FILE"; - } - ppCmds.emplace_back(std::move(ccmd)); - } - rule.Command = this->GetLocalGenerator()->BuildCommandLine(ppCmds); - - // Write the rule for preprocessing file of the given language. - rule.Comment = cmStrCat("Rule for preprocessing ", lang, " files."); - rule.Description = cmStrCat("Building ", lang, " preprocessed $out"); - this->GetGlobalGenerator()->AddRule(rule); + this->GetGlobalGenerator()->AddRule(scanRule); } if (needDyndep) { @@ -996,6 +1051,82 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatements( } } +namespace { +cmNinjaBuild GetPreprocessOrScanBuild( + const std::string& ruleName, const std::string& ppFileName, bool compilePP, + bool compilePPWithDefines, cmNinjaBuild& objBuild, cmNinjaVars& vars, + const std::string& depFileName, bool needDyndep, + const std::string& objectFileName) +{ + // Explicit preprocessing and dependency + cmNinjaBuild ppBuild(ruleName); + + if (!ppFileName.empty()) { + ppBuild.Outputs.push_back(ppFileName); + ppBuild.RspFile = cmStrCat(ppFileName, ".rsp"); + } else { + ppBuild.RspFile = "$out.rsp"; + } + + if (compilePP) { + // Move compilation dependencies to the preprocessing build statement. + std::swap(ppBuild.ExplicitDeps, objBuild.ExplicitDeps); + std::swap(ppBuild.ImplicitDeps, objBuild.ImplicitDeps); + std::swap(ppBuild.OrderOnlyDeps, objBuild.OrderOnlyDeps); + std::swap(ppBuild.Variables["IN_ABS"], vars["IN_ABS"]); + + // The actual compilation will now use the preprocessed source. + objBuild.ExplicitDeps.push_back(ppFileName); + } else { + // Copy compilation dependencies to the preprocessing build statement. + ppBuild.ExplicitDeps = objBuild.ExplicitDeps; + ppBuild.ImplicitDeps = objBuild.ImplicitDeps; + ppBuild.OrderOnlyDeps = objBuild.OrderOnlyDeps; + ppBuild.Variables["IN_ABS"] = vars["IN_ABS"]; + } + + // Preprocessing and compilation generally use the same flags. + ppBuild.Variables["FLAGS"] = vars["FLAGS"]; + + if (compilePP && !compilePPWithDefines) { + // Move preprocessor definitions to the preprocessor build statement. + std::swap(ppBuild.Variables["DEFINES"], vars["DEFINES"]); + } else { + // Copy preprocessor definitions to the preprocessor build statement. + ppBuild.Variables["DEFINES"] = vars["DEFINES"]; + } + + // Copy include directories to the preprocessor build statement. The + // Fortran compilation build statement still needs them for the INCLUDE + // directive. + ppBuild.Variables["INCLUDES"] = vars["INCLUDES"]; + + // Explicit preprocessing always uses a depfile. + ppBuild.Variables["DEP_FILE"] = depFileName; + if (compilePP) { + // The actual compilation does not need a depfile because it + // depends on the already-preprocessed source. + vars.erase("DEP_FILE"); + } + + if (needDyndep) { + // Tell dependency scanner the object file that will result from + // compiling the source. + ppBuild.Variables["OBJ_FILE"] = objectFileName; + + // Tell dependency scanner where to store dyndep intermediate results. + std::string const ddiFile = cmStrCat(objectFileName, ".ddi"); + if (ppFileName.empty()) { + ppBuild.Outputs.push_back(ddiFile); + } else { + ppBuild.Variables["DYNDEP_INTERMEDIATE_FILE"] = ddiFile; + ppBuild.ImplicitOuts.push_back(ddiFile); + } + } + return ppBuild; +} +} + void cmNinjaTargetGenerator::WriteObjectBuildStatement( cmSourceFile const* source, const std::string& config, const std::string& fileConfig, bool firstForConfig) @@ -1134,36 +1265,39 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( // For some cases we do an explicit preprocessor invocation. bool const explicitPP = this->NeedExplicitPreprocessing(language); if (explicitPP) { - cmNinjaBuild ppBuild(this->LanguagePreprocessRule(language, config)); - std::string const ppFileName = - this->ConvertToNinjaPath(this->GetPreprocessedFilePath(source, config)); - ppBuild.Outputs.push_back(ppFileName); - - ppBuild.RspFile = cmStrCat(ppFileName, ".rsp"); + // If source/target has preprocessing turned off, we still need to + // generate an explicit dependency step + const auto srcpp = source->GetSafeProperty("Fortran_PREPROCESS"); + cmOutputConverter::FortranPreprocess preprocess = + cmOutputConverter::GetFortranPreprocess(srcpp); + if (preprocess == cmOutputConverter::FortranPreprocess::Unset) { + const auto& tgtpp = + this->GeneratorTarget->GetSafeProperty("Fortran_PREPROCESS"); + preprocess = cmOutputConverter::GetFortranPreprocess(tgtpp); + } - bool const compilePP = this->UsePreprocessedSource(language); + bool const compilePP = this->UsePreprocessedSource(language) && + (preprocess != cmOutputConverter::FortranPreprocess::NotNeeded); bool const compilePPWithDefines = compilePP && this->CompilePreprocessedSourceWithDefines(language); - if (compilePP) { - // Move compilation dependencies to the preprocessing build statement. - std::swap(ppBuild.ExplicitDeps, objBuild.ExplicitDeps); - std::swap(ppBuild.ImplicitDeps, objBuild.ImplicitDeps); - std::swap(ppBuild.OrderOnlyDeps, objBuild.OrderOnlyDeps); - std::swap(ppBuild.Variables["IN_ABS"], vars["IN_ABS"]); - - // The actual compilation will now use the preprocessed source. - objBuild.ExplicitDeps.push_back(ppFileName); - } else { - // Copy compilation dependencies to the preprocessing build statement. - ppBuild.ExplicitDeps = objBuild.ExplicitDeps; - ppBuild.ImplicitDeps = objBuild.ImplicitDeps; - ppBuild.OrderOnlyDeps = objBuild.OrderOnlyDeps; - ppBuild.Variables["IN_ABS"] = vars["IN_ABS"]; - } - // Preprocessing and compilation generally use the same flags. - ppBuild.Variables["FLAGS"] = vars["FLAGS"]; + std::string const ppFileName = compilePP + ? this->ConvertToNinjaPath(this->GetPreprocessedFilePath(source, config)) + : ""; + + std::string const buildName = compilePP + ? this->LanguagePreprocessRule(language, config) + : this->LanguageDependencyRule(language, config); + + const auto depExtension = compilePP ? ".pp.d" : ".d"; + const std::string depFileName = + this->GetLocalGenerator()->ConvertToOutputFormat( + cmStrCat(objectFileName, depExtension), cmOutputConverter::SHELL); + + cmNinjaBuild ppBuild = GetPreprocessOrScanBuild( + buildName, ppFileName, compilePP, compilePPWithDefines, objBuild, vars, + depFileName, needDyndep, objectFileName); if (compilePP) { // In case compilation requires flags that are incompatible with @@ -1171,22 +1305,7 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( std::string const& postFlag = this->Makefile->GetSafeDefinition( cmStrCat("CMAKE_", language, "_POSTPROCESS_FLAG")); this->LocalGenerator->AppendFlags(vars["FLAGS"], postFlag); - } - - if (compilePP && !compilePPWithDefines) { - // Move preprocessor definitions to the preprocessor build statement. - std::swap(ppBuild.Variables["DEFINES"], vars["DEFINES"]); - } else { - // Copy preprocessor definitions to the preprocessor build statement. - ppBuild.Variables["DEFINES"] = vars["DEFINES"]; - } - - // Copy include directories to the preprocessor build statement. The - // Fortran compilation build statement still needs them for the INCLUDE - // directive. - ppBuild.Variables["INCLUDES"] = vars["INCLUDES"]; - if (compilePP) { // Prepend source file's original directory as an include directory // so e.g. Fortran INCLUDE statements can look for files in it. std::vector<std::string> sourceDirectory; @@ -1200,28 +1319,9 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( vars["INCLUDES"] = cmStrCat(sourceDirectoryFlag, ' ', vars["INCLUDES"]); } - // Explicit preprocessing always uses a depfile. - ppBuild.Variables["DEP_FILE"] = - this->GetLocalGenerator()->ConvertToOutputFormat( - cmStrCat(objectFileName, ".pp.d"), cmOutputConverter::SHELL); - if (compilePP) { - // The actual compilation does not need a depfile because it - // depends on the already-preprocessed source. - vars.erase("DEP_FILE"); - } - - if (needDyndep) { - // Tell dependency scanner the object file that will result from - // compiling the source. - ppBuild.Variables["OBJ_FILE"] = objectFileName; - - // Tell dependency scanner where to store dyndep intermediate results. + if (firstForConfig && needDyndep) { std::string const ddiFile = cmStrCat(objectFileName, ".ddi"); - ppBuild.Variables["DYNDEP_INTERMEDIATE_FILE"] = ddiFile; - ppBuild.ImplicitOuts.push_back(ddiFile); - if (firstForConfig) { - this->Configs[config].DDIFiles[language].push_back(ddiFile); - } + this->Configs[config].DDIFiles[language].push_back(ddiFile); } this->addPoolNinjaVariable("JOB_POOL_COMPILE", this->GetGeneratorTarget(), @@ -1266,14 +1366,19 @@ void cmNinjaTargetGenerator::WriteObjectBuildStatement( } if (cmProp objectOutputs = source->GetProperty("OBJECT_OUTPUTS")) { - cmNinjaBuild build("phony"); - build.Comment = "Additional output files."; - build.Outputs = cmExpandedList(*objectOutputs); - std::transform(build.Outputs.begin(), build.Outputs.end(), - build.Outputs.begin(), MapToNinjaPath()); - build.ExplicitDeps = objBuild.Outputs; - this->GetGlobalGenerator()->WriteBuild(this->GetImplFileStream(fileConfig), - build); + std::string evaluatedObjectOutputs = cmGeneratorExpression::Evaluate( + *objectOutputs, this->LocalGenerator, config); + + if (!evaluatedObjectOutputs.empty()) { + cmNinjaBuild build("phony"); + build.Comment = "Additional output files."; + build.Outputs = cmExpandedList(evaluatedObjectOutputs); + std::transform(build.Outputs.begin(), build.Outputs.end(), + build.Outputs.begin(), MapToNinjaPath()); + build.ExplicitDeps = objBuild.Outputs; + this->GetGlobalGenerator()->WriteBuild( + this->GetImplFileStream(fileConfig), build); + } } } diff --git a/Source/cmNinjaTargetGenerator.h b/Source/cmNinjaTargetGenerator.h index 8678dc3..8d4372e 100644 --- a/Source/cmNinjaTargetGenerator.h +++ b/Source/cmNinjaTargetGenerator.h @@ -12,7 +12,7 @@ #include <utility> #include <vector> -#include "cm_jsoncpp_value.h" +#include <cm3p/json/value.h> #include "cmCommonTargetGenerator.h" #include "cmGlobalNinjaGenerator.h" @@ -70,6 +70,8 @@ protected: const std::string& config) const; std::string LanguagePreprocessRule(std::string const& lang, const std::string& config) const; + std::string LanguageDependencyRule(std::string const& lang, + const std::string& config) const; bool NeedExplicitPreprocessing(std::string const& lang) const; std::string LanguageDyndepRule(std::string const& lang, const std::string& config) const; diff --git a/Source/cmNinjaUtilityTargetGenerator.cxx b/Source/cmNinjaUtilityTargetGenerator.cxx index 134924e..b0b7953 100644 --- a/Source/cmNinjaUtilityTargetGenerator.cxx +++ b/Source/cmNinjaUtilityTargetGenerator.cxx @@ -160,10 +160,5 @@ void cmNinjaUtilityTargetGenerator::Generate(const std::string& config) // be per-directory and have one at the top-level anyway. if (genTarget->GetType() != cmStateEnums::GLOBAL_TARGET) { gg->AddTargetAlias(this->GetTargetName(), genTarget, config); - } else if (gg->IsMultiConfig() && genTarget->Target->IsPerConfig()) { - cmNinjaBuild phonyAlias("phony"); - gg->AppendTargetOutputs(genTarget, phonyAlias.Outputs, ""); - phonyAlias.ExplicitDeps = phonyBuild.Outputs; - gg->WriteBuild(this->GetImplFileStream(config), phonyAlias); } } diff --git a/Source/cmOutputConverter.cxx b/Source/cmOutputConverter.cxx index dc324cc..359e9f5 100644 --- a/Source/cmOutputConverter.cxx +++ b/Source/cmOutputConverter.cxx @@ -170,6 +170,17 @@ cmOutputConverter::FortranFormat cmOutputConverter::GetFortranFormat( return format; } +cmOutputConverter::FortranPreprocess cmOutputConverter::GetFortranPreprocess( + cm::string_view value) +{ + if (value.empty()) { + return FortranPreprocess::Unset; + } + + return cmIsOn(value) ? FortranPreprocess::Needed + : FortranPreprocess::NotNeeded; +} + void cmOutputConverter::SetLinkScriptShell(bool linkScriptShell) { this->LinkScriptShell = linkScriptShell; diff --git a/Source/cmOutputConverter.h b/Source/cmOutputConverter.h index 28582df..a8b4528 100644 --- a/Source/cmOutputConverter.h +++ b/Source/cmOutputConverter.h @@ -95,6 +95,14 @@ public: }; static FortranFormat GetFortranFormat(cm::string_view value); + enum class FortranPreprocess + { + Unset, + NotNeeded, + Needed + }; + static FortranPreprocess GetFortranPreprocess(cm::string_view value); + private: cmState* GetState() const; diff --git a/Source/cmPipeConnection.h b/Source/cmPipeConnection.h index 81f8a49..1215716 100644 --- a/Source/cmPipeConnection.h +++ b/Source/cmPipeConnection.h @@ -6,7 +6,7 @@ #include <string> -#include "cm_uv.h" +#include <cm3p/uv.h> #include "cmConnection.h" #include "cmUVHandlePtr.h" diff --git a/Source/cmPropertyDefinition.cxx b/Source/cmPropertyDefinition.cxx index c8efaf6..1796bb8 100644 --- a/Source/cmPropertyDefinition.cxx +++ b/Source/cmPropertyDefinition.cxx @@ -2,17 +2,38 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmPropertyDefinition.h" -#include <utility> +#include <tuple> -cmPropertyDefinition::cmPropertyDefinition(std::string name, - cmProperty::ScopeType scope, - std::string shortDescription, +cmPropertyDefinition::cmPropertyDefinition(std::string shortDescription, std::string fullDescription, - bool chain) - : Name(std::move(name)) - , ShortDescription(std::move(shortDescription)) + bool chained) + : ShortDescription(std::move(shortDescription)) , FullDescription(std::move(fullDescription)) - , Scope(scope) - , Chained(chain) + , Chained(chained) { } + +void cmPropertyDefinitionMap::DefineProperty( + const std::string& name, cmProperty::ScopeType scope, + const std::string& ShortDescription, const std::string& FullDescription, + bool chain) +{ + auto it = this->Map_.find(key_type(name, scope)); + if (it == this->Map_.end()) { + // try_emplace() since C++17 + this->Map_.emplace( + std::piecewise_construct, std::forward_as_tuple(name, scope), + std::forward_as_tuple(ShortDescription, FullDescription, chain)); + } +} + +cmPropertyDefinition const* cmPropertyDefinitionMap::GetPropertyDefinition( + const std::string& name, cmProperty::ScopeType scope) const +{ + auto it = this->Map_.find(key_type(name, scope)); + if (it != this->Map_.end()) { + return &it->second; + } + + return nullptr; +} diff --git a/Source/cmPropertyDefinition.h b/Source/cmPropertyDefinition.h index d2e4467..f83bc4f 100644 --- a/Source/cmPropertyDefinition.h +++ b/Source/cmPropertyDefinition.h @@ -5,7 +5,9 @@ #include "cmConfigure.h" // IWYU pragma: keep +#include <map> #include <string> +#include <utility> #include "cmProperty.h" @@ -13,25 +15,19 @@ * \brief Property meta-information * * This class contains the following meta-information about property: - * - Name; * - Various documentation strings; - * - The scope of the property; * - If the property is chained. */ class cmPropertyDefinition { public: /// Constructor - cmPropertyDefinition(std::string name, cmProperty::ScopeType scope, - std::string ShortDescription, - std::string FullDescription, bool chained = false); + cmPropertyDefinition(std::string shortDescription, + std::string fullDescription, bool chained); /// Is the property chained? bool IsChained() const { return this->Chained; } - /// Get the scope - cmProperty::ScopeType GetScope() const { return this->Scope; } - /// Get the documentation (short version) const std::string& GetShortDescription() const { @@ -44,12 +40,30 @@ public: return this->FullDescription; } -protected: - std::string Name; +private: std::string ShortDescription; std::string FullDescription; - cmProperty::ScopeType Scope; bool Chained; }; +/** \class cmPropertyDefinitionMap + * \brief Map property name and scope to their definition + */ +class cmPropertyDefinitionMap +{ +public: + // define the property + void DefineProperty(const std::string& name, cmProperty::ScopeType scope, + const std::string& ShortDescription, + const std::string& FullDescription, bool chain); + + // get the property definition if present, otherwise nullptr + cmPropertyDefinition const* GetPropertyDefinition( + const std::string& name, cmProperty::ScopeType scope) const; + +private: + using key_type = std::pair<std::string, cmProperty::ScopeType>; + std::map<key_type, cmPropertyDefinition> Map_; +}; + #endif diff --git a/Source/cmPropertyDefinitionMap.cxx b/Source/cmPropertyDefinitionMap.cxx deleted file mode 100644 index 614d5a4..0000000 --- a/Source/cmPropertyDefinitionMap.cxx +++ /dev/null @@ -1,35 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#include "cmPropertyDefinitionMap.h" - -#include <tuple> -#include <utility> - -void cmPropertyDefinitionMap::DefineProperty( - const std::string& name, cmProperty::ScopeType scope, - const std::string& ShortDescription, const std::string& FullDescription, - bool chain) -{ - auto it = this->find(name); - if (it == this->end()) { - // try_emplace() since C++17 - this->emplace(std::piecewise_construct, std::forward_as_tuple(name), - std::forward_as_tuple(name, scope, ShortDescription, - FullDescription, chain)); - } -} - -bool cmPropertyDefinitionMap::IsPropertyDefined(const std::string& name) const -{ - return this->find(name) != this->end(); -} - -bool cmPropertyDefinitionMap::IsPropertyChained(const std::string& name) const -{ - auto it = this->find(name); - if (it == this->end()) { - return false; - } - - return it->second.IsChained(); -} diff --git a/Source/cmPropertyDefinitionMap.h b/Source/cmPropertyDefinitionMap.h deleted file mode 100644 index 2ae6efb..0000000 --- a/Source/cmPropertyDefinitionMap.h +++ /dev/null @@ -1,30 +0,0 @@ -/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying - file Copyright.txt or https://cmake.org/licensing for details. */ -#ifndef cmPropertyDefinitionMap_h -#define cmPropertyDefinitionMap_h - -#include "cmConfigure.h" // IWYU pragma: keep - -#include <map> -#include <string> - -#include "cmProperty.h" -#include "cmPropertyDefinition.h" - -class cmPropertyDefinitionMap - : public std::map<std::string, cmPropertyDefinition> -{ -public: - // define the property - void DefineProperty(const std::string& name, cmProperty::ScopeType scope, - const std::string& ShortDescription, - const std::string& FullDescription, bool chain); - - // has a named property been defined - bool IsPropertyDefined(const std::string& name) const; - - // is a named property set to chain - bool IsPropertyChained(const std::string& name) const; -}; - -#endif diff --git a/Source/cmQtAutoGenInitializer.cxx b/Source/cmQtAutoGenInitializer.cxx index 235ee38..003a300 100644 --- a/Source/cmQtAutoGenInitializer.cxx +++ b/Source/cmQtAutoGenInitializer.cxx @@ -18,10 +18,10 @@ #include <cm/memory> #include <cmext/algorithm> -#include "cmsys/SystemInformation.hxx" +#include <cm3p/json/value.h> +#include <cm3p/json/writer.h> -#include "cm_jsoncpp_value.h" -#include "cm_jsoncpp_writer.h" +#include "cmsys/SystemInformation.hxx" #include "cmCustomCommand.h" #include "cmCustomCommandLines.h" diff --git a/Source/cmQtAutoGenerator.cxx b/Source/cmQtAutoGenerator.cxx index da96305..ee2bc09 100644 --- a/Source/cmQtAutoGenerator.cxx +++ b/Source/cmQtAutoGenerator.cxx @@ -2,9 +2,9 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmQtAutoGenerator.h" -#include "cmsys/FStream.hxx" +#include <cm3p/json/reader.h> -#include "cm_jsoncpp_reader.h" +#include "cmsys/FStream.hxx" #include "cmQtAutoGen.h" #include "cmStringAlgorithms.h" diff --git a/Source/cmQtAutoGenerator.h b/Source/cmQtAutoGenerator.h index bbe6dd0..83fb3ed 100644 --- a/Source/cmQtAutoGenerator.h +++ b/Source/cmQtAutoGenerator.h @@ -13,7 +13,7 @@ #include <cm/string_view> -#include "cm_jsoncpp_value.h" +#include <cm3p/json/value.h> #include "cmFileTime.h" #include "cmQtAutoGen.h" diff --git a/Source/cmQtAutoMocUic.cxx b/Source/cmQtAutoMocUic.cxx index 36dd627..9adcabb 100644 --- a/Source/cmQtAutoMocUic.cxx +++ b/Source/cmQtAutoMocUic.cxx @@ -18,11 +18,11 @@ #include <cm/string_view> #include <cmext/algorithm> +#include <cm3p/json/value.h> + #include "cmsys/FStream.hxx" #include "cmsys/RegularExpression.hxx" -#include "cm_jsoncpp_value.h" - #include "cmCryptoHash.h" #include "cmFileTime.h" #include "cmGccDepfileReader.h" diff --git a/Source/cmServer.cxx b/Source/cmServer.cxx index 434fb68..7f97406 100644 --- a/Source/cmServer.cxx +++ b/Source/cmServer.cxx @@ -4,6 +4,7 @@ #include <algorithm> #include <cassert> +#include <csignal> #include <cstdint> #include <iostream> #include <mutex> @@ -12,10 +13,10 @@ #include <cm/memory> #include <cm/shared_mutex> -#include "cmsys/FStream.hxx" +#include <cm3p/json/reader.h> +#include <cm3p/json/writer.h> -#include "cm_jsoncpp_reader.h" -#include "cm_jsoncpp_writer.h" +#include "cmsys/FStream.hxx" #include "cmConnection.h" #include "cmFileMonitor.h" diff --git a/Source/cmServer.h b/Source/cmServer.h index ec40738..9543329 100644 --- a/Source/cmServer.h +++ b/Source/cmServer.h @@ -10,8 +10,8 @@ #include <cm/shared_mutex> -#include "cm_jsoncpp_value.h" -#include "cm_uv.h" +#include <cm3p/json/value.h> +#include <cm3p/uv.h> #include "cmUVHandlePtr.h" diff --git a/Source/cmServerConnection.cxx b/Source/cmServerConnection.cxx index 2791972..b4f41a0 100644 --- a/Source/cmServerConnection.cxx +++ b/Source/cmServerConnection.cxx @@ -4,7 +4,7 @@ #include "cmServerConnection.h" -#include "cm_uv.h" +#include <cm3p/uv.h> #include "cmServer.h" #include "cmServerDictionary.h" diff --git a/Source/cmServerProtocol.cxx b/Source/cmServerProtocol.cxx index f6154eb..6b32de3 100644 --- a/Source/cmServerProtocol.cxx +++ b/Source/cmServerProtocol.cxx @@ -12,7 +12,7 @@ #include <cm/memory> #include <cmext/algorithm> -#include "cm_uv.h" +#include <cm3p/uv.h> #include "cmExternalMakefileProjectGenerator.h" #include "cmFileMonitor.h" diff --git a/Source/cmServerProtocol.h b/Source/cmServerProtocol.h index 8446c3e..c71b7bf 100644 --- a/Source/cmServerProtocol.h +++ b/Source/cmServerProtocol.h @@ -8,7 +8,7 @@ #include <string> #include <utility> -#include "cm_jsoncpp_value.h" +#include <cm3p/json/value.h> #include "cmake.h" diff --git a/Source/cmSetDirectoryPropertiesCommand.cxx b/Source/cmSetDirectoryPropertiesCommand.cxx index 35daca6..07ad246 100644 --- a/Source/cmSetDirectoryPropertiesCommand.cxx +++ b/Source/cmSetDirectoryPropertiesCommand.cxx @@ -5,12 +5,6 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" -namespace { -bool RunCommand(cmMakefile& mf, std::vector<std::string>::const_iterator ait, - std::vector<std::string>::const_iterator aitend, - std::string& errors); -} - // cmSetDirectoryPropertiesCommand bool cmSetDirectoryPropertiesCommand(std::vector<std::string> const& args, cmExecutionStatus& status) @@ -20,38 +14,26 @@ bool cmSetDirectoryPropertiesCommand(std::vector<std::string> const& args, return false; } - std::string errors; - bool ret = - RunCommand(status.GetMakefile(), args.begin() + 1, args.end(), errors); - if (!ret) { - status.SetError(errors); + // PROPERTIES followed by prop value pairs + if (args.size() % 2 != 1) { + status.SetError("Wrong number of arguments"); + return false; } - return ret; -} -namespace { -bool RunCommand(cmMakefile& mf, std::vector<std::string>::const_iterator ait, - std::vector<std::string>::const_iterator aitend, - std::string& errors) -{ - for (; ait != aitend; ait += 2) { - if (ait + 1 == aitend) { - errors = "Wrong number of arguments"; - return false; - } - const std::string& prop = *ait; - const std::string& value = *(ait + 1); + for (auto iter = args.begin() + 1; iter != args.end(); iter += 2) { + const std::string& prop = *iter; if (prop == "VARIABLES") { - errors = "Variables and cache variables should be set using SET command"; + status.SetError( + "Variables and cache variables should be set using SET command"); return false; } if (prop == "MACROS") { - errors = "Commands and macros cannot be set using SET_CMAKE_PROPERTIES"; + status.SetError( + "Commands and macros cannot be set using SET_CMAKE_PROPERTIES"); return false; } - mf.SetProperty(prop, value.c_str()); + status.GetMakefile().SetProperty(prop, (iter + 1)->c_str()); } return true; } -} diff --git a/Source/cmSetPropertyCommand.cxx b/Source/cmSetPropertyCommand.cxx index 4dbbbd7..07cb7c9 100644 --- a/Source/cmSetPropertyCommand.cxx +++ b/Source/cmSetPropertyCommand.cxx @@ -43,7 +43,9 @@ bool HandleSourceMode(cmExecutionStatus& status, const std::set<std::string>& names, const std::string& propertyName, const std::string& propertyValue, bool appendAsString, - bool appendMode, bool remove); + bool appendMode, bool remove, + const std::vector<cmMakefile*>& directory_makefiles, + bool source_file_paths_should_be_absolute); bool HandleSource(cmSourceFile* sf, const std::string& propertyName, const std::string& propertyValue, bool appendAsString, bool appendMode, bool remove); @@ -74,6 +76,131 @@ bool HandleInstall(cmInstalledFile* file, cmMakefile& makefile, bool appendMode, bool remove); } +namespace SetPropertyCommand { +bool HandleSourceFileDirectoryScopes( + cmExecutionStatus& status, std::vector<std::string>& source_file_directories, + std::vector<std::string>& source_file_target_directories, + std::vector<cmMakefile*>& directory_makefiles) +{ + cmMakefile* current_dir_mf = &status.GetMakefile(); + if (!source_file_directories.empty()) { + for (const std::string& dir_path : source_file_directories) { + const std::string absolute_dir_path = cmSystemTools::CollapseFullPath( + dir_path, current_dir_mf->GetCurrentSourceDirectory()); + cmMakefile* dir_mf = + status.GetMakefile().GetGlobalGenerator()->FindMakefile( + absolute_dir_path); + if (!dir_mf) { + status.SetError(cmStrCat("given non-existent DIRECTORY ", dir_path)); + return false; + } + directory_makefiles.push_back(dir_mf); + } + } else if (!source_file_target_directories.empty()) { + for (const std::string& target_name : source_file_target_directories) { + cmTarget* target = current_dir_mf->FindTargetToUse(target_name); + if (!target) { + status.SetError(cmStrCat( + "given non-existent target for DIRECTORY_TARGET ", target_name)); + return false; + } + cmProp target_source_dir = target->GetProperty("SOURCE_DIR"); + cmMakefile* target_dir_mf = + status.GetMakefile().GetGlobalGenerator()->FindMakefile( + *target_source_dir); + directory_makefiles.push_back(target_dir_mf); + } + } else { + directory_makefiles.push_back(current_dir_mf); + } + return true; +} + +bool HandleSourceFileDirectoryScopeValidation( + cmExecutionStatus& status, bool source_file_directory_option_enabled, + bool source_file_target_option_enabled, + std::vector<std::string>& source_file_directories, + std::vector<std::string>& source_file_target_directories) +{ + // Validate source file directory scopes. + if (source_file_directory_option_enabled && + source_file_directories.empty()) { + std::string errors = "called with incorrect number of arguments " + "no value provided to the DIRECTORY option"; + status.SetError(errors); + return false; + } + if (source_file_target_option_enabled && + source_file_target_directories.empty()) { + std::string errors = "called with incorrect number of arguments " + "no value provided to the TARGET_DIRECTORY option"; + status.SetError(errors); + return false; + } + return true; +} + +bool HandleAndValidateSourceFileDirectortoryScopes( + cmExecutionStatus& status, bool source_file_directory_option_enabled, + bool source_file_target_option_enabled, + std::vector<std::string>& source_file_directories, + std::vector<std::string>& source_file_target_directories, + std::vector<cmMakefile*>& source_file_directory_makefiles) +{ + bool scope_options_valid = + SetPropertyCommand::HandleSourceFileDirectoryScopeValidation( + status, source_file_directory_option_enabled, + source_file_target_option_enabled, source_file_directories, + source_file_target_directories); + if (!scope_options_valid) { + return false; + } + + scope_options_valid = SetPropertyCommand::HandleSourceFileDirectoryScopes( + status, source_file_directories, source_file_target_directories, + source_file_directory_makefiles); + return scope_options_valid; +} + +std::string MakeSourceFilePathAbsoluteIfNeeded( + cmExecutionStatus& status, const std::string& source_file_path, + const bool needed) +{ + if (!needed) { + return source_file_path; + } + const std::string absolute_file_path = cmSystemTools::CollapseFullPath( + source_file_path, status.GetMakefile().GetCurrentSourceDirectory()); + return absolute_file_path; +} + +void MakeSourceFilePathsAbsoluteIfNeeded( + cmExecutionStatus& status, + std::vector<std::string>& source_files_absolute_paths, + std::vector<std::string>::const_iterator files_it_begin, + std::vector<std::string>::const_iterator files_it_end, const bool needed) +{ + + // Make the file paths absolute, so that relative source file paths are + // picked up relative to the command calling site, regardless of the + // directory scope. + std::vector<std::string>::difference_type num_files = + files_it_end - files_it_begin; + source_files_absolute_paths.reserve(num_files); + + if (!needed) { + source_files_absolute_paths.assign(files_it_begin, files_it_end); + return; + } + + for (; files_it_begin != files_it_end; ++files_it_begin) { + const std::string absolute_file_path = + MakeSourceFilePathAbsoluteIfNeeded(status, *files_it_begin, true); + source_files_absolute_paths.push_back(absolute_file_path); + } +} +} + bool cmSetPropertyCommand(std::vector<std::string> const& args, cmExecutionStatus& status) { @@ -114,13 +241,20 @@ bool cmSetPropertyCommand(std::vector<std::string> const& args, std::string propertyName; std::string propertyValue; + std::vector<std::string> source_file_directories; + std::vector<std::string> source_file_target_directories; + bool source_file_directory_option_enabled = false; + bool source_file_target_option_enabled = false; + // Parse the rest of the arguments up to the values. enum Doing { DoingNone, DoingNames, DoingProperty, - DoingValues + DoingValues, + DoingSourceDirectory, + DoingSourceTargetDirectory }; Doing doing = DoingNames; const char* sep = ""; @@ -137,8 +271,20 @@ bool cmSetPropertyCommand(std::vector<std::string> const& args, appendMode = true; remove = false; appendAsString = true; + } else if (doing == DoingNames && scope == cmProperty::SOURCE_FILE && + arg == "DIRECTORY") { + doing = DoingSourceDirectory; + source_file_directory_option_enabled = true; + } else if (doing == DoingNames && scope == cmProperty::SOURCE_FILE && + arg == "TARGET_DIRECTORY") { + doing = DoingSourceTargetDirectory; + source_file_target_option_enabled = true; } else if (doing == DoingNames) { names.insert(arg); + } else if (doing == DoingSourceDirectory) { + source_file_directories.push_back(arg); + } else if (doing == DoingSourceTargetDirectory) { + source_file_target_directories.push_back(arg); } else if (doing == DoingProperty) { propertyName = arg; doing = DoingValues; @@ -159,6 +305,18 @@ bool cmSetPropertyCommand(std::vector<std::string> const& args, return false; } + std::vector<cmMakefile*> source_file_directory_makefiles; + bool file_scopes_handled = + SetPropertyCommand::HandleAndValidateSourceFileDirectortoryScopes( + status, source_file_directory_option_enabled, + source_file_target_option_enabled, source_file_directories, + source_file_target_directories, source_file_directory_makefiles); + if (!file_scopes_handled) { + return false; + } + bool source_file_paths_should_be_absolute = + source_file_directory_option_enabled || source_file_target_option_enabled; + // Dispatch property setting. switch (scope) { case cmProperty::GLOBAL: @@ -172,7 +330,9 @@ bool cmSetPropertyCommand(std::vector<std::string> const& args, appendAsString, appendMode, remove); case cmProperty::SOURCE_FILE: return HandleSourceMode(status, names, propertyName, propertyValue, - appendAsString, appendMode, remove); + appendAsString, appendMode, remove, + source_file_directory_makefiles, + source_file_paths_should_be_absolute); case cmProperty::TEST: return HandleTestMode(status, names, propertyName, propertyValue, appendAsString, appendMode, remove); @@ -315,21 +475,32 @@ bool HandleSourceMode(cmExecutionStatus& status, const std::set<std::string>& names, const std::string& propertyName, const std::string& propertyValue, bool appendAsString, - bool appendMode, bool remove) + bool appendMode, bool remove, + const std::vector<cmMakefile*>& directory_makefiles, + const bool source_file_paths_should_be_absolute) { - for (std::string const& name : names) { - // Get the source file. - if (cmSourceFile* sf = status.GetMakefile().GetOrCreateSource(name)) { - if (!HandleSource(sf, propertyName, propertyValue, appendAsString, - appendMode, remove)) { + std::vector<std::string> files_absolute; + std::vector<std::string> unique_files(names.begin(), names.end()); + SetPropertyCommand::MakeSourceFilePathsAbsoluteIfNeeded( + status, files_absolute, unique_files.begin(), unique_files.end(), + source_file_paths_should_be_absolute); + + for (const auto mf : directory_makefiles) { + for (std::string const& name : files_absolute) { + // Get the source file. + if (cmSourceFile* sf = mf->GetOrCreateSource(name)) { + if (!HandleSource(sf, propertyName, propertyValue, appendAsString, + appendMode, remove)) { + return false; + } + } else { + status.SetError(cmStrCat( + "given SOURCE name that could not be found or created: ", name)); return false; } - } else { - status.SetError(cmStrCat( - "given SOURCE name that could not be found or created: ", name)); - return false; } } + return true; } diff --git a/Source/cmSetPropertyCommand.h b/Source/cmSetPropertyCommand.h index ec36f84..af566a3 100644 --- a/Source/cmSetPropertyCommand.h +++ b/Source/cmSetPropertyCommand.h @@ -8,9 +8,38 @@ #include <string> #include <vector> +class cmMakefile; class cmExecutionStatus; bool cmSetPropertyCommand(std::vector<std::string> const& args, cmExecutionStatus& status); +namespace SetPropertyCommand { +bool HandleSourceFileDirectoryScopes( + cmExecutionStatus& status, std::vector<std::string>& source_file_directories, + std::vector<std::string>& source_file_target_directories, + std::vector<cmMakefile*>& directory_makefiles); + +bool HandleSourceFileDirectoryScopeValidation( + cmExecutionStatus& status, bool source_file_directory_option_enabled, + bool source_file_target_option_enabled, + std::vector<std::string>& source_file_directories, + std::vector<std::string>& source_file_target_directories); + +bool HandleAndValidateSourceFileDirectortoryScopes( + cmExecutionStatus& status, bool source_directories_option_encountered, + bool source_target_directories_option_encountered, + std::vector<std::string>& source_directories, + std::vector<std::string>& source_target_directories, + std::vector<cmMakefile*>& source_file_directory_makefiles); + +std::string MakeSourceFilePathAbsoluteIfNeeded( + cmExecutionStatus& status, const std::string& source_file_path, bool needed); +void MakeSourceFilePathsAbsoluteIfNeeded( + cmExecutionStatus& status, + std::vector<std::string>& source_files_absolute_paths, + std::vector<std::string>::const_iterator files_it_begin, + std::vector<std::string>::const_iterator files_it_end, bool needed); +} + #endif diff --git a/Source/cmSetSourceFilesPropertiesCommand.cxx b/Source/cmSetSourceFilesPropertiesCommand.cxx index 7ff604b..3135a06 100644 --- a/Source/cmSetSourceFilesPropertiesCommand.cxx +++ b/Source/cmSetSourceFilesPropertiesCommand.cxx @@ -2,17 +2,23 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmSetSourceFilesPropertiesCommand.h" +#include <algorithm> +#include <iterator> + +#include <cm/string_view> +#include <cmext/algorithm> + #include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmSetPropertyCommand.h" #include "cmSourceFile.h" #include "cmStringAlgorithms.h" -static bool RunCommand(cmMakefile* mf, - std::vector<std::string>::const_iterator filebeg, - std::vector<std::string>::const_iterator fileend, - std::vector<std::string>::const_iterator propbeg, - std::vector<std::string>::const_iterator propend, - std::string& errors); +static bool RunCommandForScope( + cmMakefile* mf, std::vector<std::string>::const_iterator file_begin, + std::vector<std::string>::const_iterator file_end, + std::vector<std::string>::const_iterator prop_begin, + std::vector<std::string>::const_iterator prop_end, std::string& errors); bool cmSetSourceFilesPropertiesCommand(std::vector<std::string> const& args, cmExecutionStatus& status) @@ -23,56 +29,95 @@ bool cmSetSourceFilesPropertiesCommand(std::vector<std::string> const& args, } // break the arguments into source file names and properties - int numFiles = 0; - std::vector<std::string>::const_iterator j; - j = args.begin(); // old style allows for specifier before PROPERTIES keyword - while (j != args.end() && *j != "ABSTRACT" && *j != "WRAP_EXCLUDE" && - *j != "GENERATED" && *j != "COMPILE_FLAGS" && - *j != "OBJECT_DEPENDS" && *j != "PROPERTIES") { - numFiles++; - ++j; + static const cm::string_view prop_names[] = { + "ABSTRACT", "GENERATED", "WRAP_EXCLUDE", "COMPILE_FLAGS", + "OBJECT_DEPENDS", "PROPERTIES", "DIRECTORY", "TARGET_DIRECTORY" + }; + + auto isNotAPropertyKeyword = + [](const std::vector<std::string>::const_iterator& arg_it) { + return std::all_of( + std::begin(prop_names), std::end(prop_names), + [&arg_it](cm::string_view prop_name) { return *arg_it != prop_name; }); + }; + + auto options_begin = std::find_first_of( + args.begin(), args.end(), std::begin(prop_names), std::end(prop_names)); + auto options_it = options_begin; + + // Handle directory options. + std::vector<std::string> source_file_directories; + std::vector<std::string> source_file_target_directories; + bool source_file_directory_option_enabled = false; + bool source_file_target_option_enabled = false; + std::vector<cmMakefile*> source_file_directory_makefiles; + + if (options_it != args.end() && *options_it == "DIRECTORY") { + source_file_directory_option_enabled = true; + ++options_it; + while (options_it != args.end() && isNotAPropertyKeyword(options_it)) { + source_file_directories.push_back(*options_it); + ++options_it; + } + } else if (options_it != args.end() && *options_it == "TARGET_DIRECTORY") { + source_file_target_option_enabled = true; + ++options_it; + while (options_it != args.end() && isNotAPropertyKeyword(options_it)) { + source_file_target_directories.push_back(*options_it); + ++options_it; + } + } + const auto props_begin = options_it; + + bool file_scopes_handled = + SetPropertyCommand::HandleAndValidateSourceFileDirectortoryScopes( + status, source_file_directory_option_enabled, + source_file_target_option_enabled, source_file_directories, + source_file_target_directories, source_file_directory_makefiles); + if (!file_scopes_handled) { + return false; } - cmMakefile& mf = status.GetMakefile(); + std::vector<std::string> files; + bool source_file_paths_should_be_absolute = + source_file_directory_option_enabled || source_file_target_option_enabled; + SetPropertyCommand::MakeSourceFilePathsAbsoluteIfNeeded( + status, files, args.begin(), options_begin, + source_file_paths_should_be_absolute); - // now call the worker function + // Now call the worker function for each directory scope represented by a + // cmMakefile instance. std::string errors; - bool ret = RunCommand(&mf, args.begin(), args.begin() + numFiles, - args.begin() + numFiles, args.end(), errors); - if (!ret) { - status.SetError(errors); + for (const auto mf : source_file_directory_makefiles) { + bool ret = RunCommandForScope(mf, files.begin(), files.end(), props_begin, + args.end(), errors); + if (!ret) { + status.SetError(errors); + return ret; + } } - return ret; + + return true; } -static bool RunCommand(cmMakefile* mf, - std::vector<std::string>::const_iterator filebeg, - std::vector<std::string>::const_iterator fileend, - std::vector<std::string>::const_iterator propbeg, - std::vector<std::string>::const_iterator propend, - std::string& errors) +static bool RunCommandForScope( + cmMakefile* mf, std::vector<std::string>::const_iterator file_begin, + std::vector<std::string>::const_iterator file_end, + std::vector<std::string>::const_iterator prop_begin, + std::vector<std::string>::const_iterator prop_end, std::string& errors) { std::vector<std::string> propertyPairs; - bool generated = false; - std::vector<std::string>::const_iterator j; // build the property pairs - for (j = propbeg; j != propend; ++j) { - // old style allows for specifier before PROPERTIES keyword - if (*j == "ABSTRACT") { - propertyPairs.emplace_back("ABSTRACT"); - propertyPairs.emplace_back("1"); - } else if (*j == "WRAP_EXCLUDE") { - propertyPairs.emplace_back("WRAP_EXCLUDE"); - propertyPairs.emplace_back("1"); - } else if (*j == "GENERATED") { - generated = true; - propertyPairs.emplace_back("GENERATED"); + for (auto j = prop_begin; j != prop_end; ++j) { + // consume old style options + if (*j == "ABSTRACT" || *j == "GENERATED" || *j == "WRAP_EXCLUDE") { + propertyPairs.emplace_back(*j); propertyPairs.emplace_back("1"); } else if (*j == "COMPILE_FLAGS") { propertyPairs.emplace_back("COMPILE_FLAGS"); ++j; - if (j == propend) { + if (j == prop_end) { errors = "called with incorrect number of arguments " "COMPILE_FLAGS with no flags"; return false; @@ -81,33 +126,22 @@ static bool RunCommand(cmMakefile* mf, } else if (*j == "OBJECT_DEPENDS") { propertyPairs.emplace_back("OBJECT_DEPENDS"); ++j; - if (j == propend) { + if (j == prop_end) { errors = "called with incorrect number of arguments " "OBJECT_DEPENDS with no dependencies"; return false; } propertyPairs.push_back(*j); } else if (*j == "PROPERTIES") { - // now loop through the rest of the arguments, new style - ++j; - while (j != propend) { - propertyPairs.push_back(*j); - if (*j == "GENERATED") { - ++j; - if (j != propend && cmIsOn(*j)) { - generated = true; - } - } else { - ++j; - } - if (j == propend) { - errors = "called with incorrect number of arguments."; - return false; - } - propertyPairs.push_back(*j); - ++j; + // PROPERTIES is followed by new style prop value pairs + cmStringRange newStyleProps{ j + 1, prop_end }; + if (newStyleProps.size() % 2 != 0) { + errors = "called with incorrect number of arguments."; + return false; } - // break out of the loop because j is already == end + // set newStyleProps as is. + cm::append(propertyPairs, newStyleProps); + // break out of the loop. break; } else { errors = "called with illegal arguments, maybe missing a " @@ -116,15 +150,13 @@ static bool RunCommand(cmMakefile* mf, } } - // now loop over all the files - for (j = filebeg; j != fileend; ++j) { + // loop over all the files + for (const std::string& sfname : cmStringRange{ file_begin, file_end }) { // get the source file - cmSourceFile* sf = mf->GetOrCreateSource(*j, generated); - if (sf) { - // now loop through all the props and set them - unsigned int k; - for (k = 0; k < propertyPairs.size(); k = k + 2) { - sf->SetProperty(propertyPairs[k], propertyPairs[k + 1].c_str()); + if (cmSourceFile* sf = mf->GetOrCreateSource(sfname)) { + // loop through the props and set them + for (auto k = propertyPairs.begin(); k != propertyPairs.end(); k += 2) { + sf->SetProperty(*k, (k + 1)->c_str()); } } } diff --git a/Source/cmSetTargetPropertiesCommand.cxx b/Source/cmSetTargetPropertiesCommand.cxx index cd0fa40..bdc84af 100644 --- a/Source/cmSetTargetPropertiesCommand.cxx +++ b/Source/cmSetTargetPropertiesCommand.cxx @@ -2,19 +2,14 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmSetTargetPropertiesCommand.h" +#include <algorithm> #include <iterator> -#include <cmext/algorithm> - #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmStringAlgorithms.h" #include "cmTarget.h" -static bool SetOneTarget(const std::string& tname, - std::vector<std::string>& propertyPairs, - cmMakefile* mf); - bool cmSetTargetPropertiesCommand(std::vector<std::string> const& args, cmExecutionStatus& status) { @@ -23,61 +18,38 @@ bool cmSetTargetPropertiesCommand(std::vector<std::string> const& args, return false; } - // first collect up the list of files - std::vector<std::string> propertyPairs; - int numFiles = 0; - for (auto j = args.begin(); j != args.end(); ++j) { - if (*j == "PROPERTIES") { - // now loop through the rest of the arguments, new style - ++j; - if (std::distance(j, args.end()) % 2 != 0) { - status.SetError("called with incorrect number of arguments."); - return false; - } - cm::append(propertyPairs, j, args.end()); - break; - } - numFiles++; + // first identify the properties arguments + auto propsIter = std::find(args.begin(), args.end(), "PROPERTIES"); + if (propsIter == args.end() || propsIter + 1 == args.end()) { + status.SetError("called with illegal arguments, maybe missing a " + "PROPERTIES specifier?"); + return false; } - if (propertyPairs.empty()) { - status.SetError("called with illegal arguments, maybe missing " - "a PROPERTIES specifier?"); + + if (std::distance(propsIter, args.end()) % 2 != 1) { + status.SetError("called with incorrect number of arguments."); return false; } cmMakefile& mf = status.GetMakefile(); - // now loop over all the targets - for (int i = 0; i < numFiles; ++i) { - if (mf.IsAlias(args[i])) { + // loop over all the targets + for (const std::string& tname : cmStringRange{ args.begin(), propsIter }) { + if (mf.IsAlias(tname)) { status.SetError("can not be used on an ALIAS target."); return false; } - bool ret = SetOneTarget(args[i], propertyPairs, &mf); - if (!ret) { + if (cmTarget* target = mf.FindTargetToUse(tname)) { + // loop through all the props and set them + for (auto k = propsIter + 1; k != args.end(); k += 2) { + target->SetProperty(*k, *(k + 1)); + target->CheckProperty(*k, &mf); + } + } else { status.SetError( - cmStrCat("Can not find target to add properties to: ", args[i])); + cmStrCat("Can not find target to add properties to: ", tname)); return false; } } return true; } - -static bool SetOneTarget(const std::string& tname, - std::vector<std::string>& propertyPairs, - cmMakefile* mf) -{ - if (cmTarget* target = mf->FindTargetToUse(tname)) { - // now loop through all the props and set them - unsigned int k; - for (k = 0; k < propertyPairs.size(); k = k + 2) { - target->SetProperty(propertyPairs[k], propertyPairs[k + 1]); - target->CheckProperty(propertyPairs[k], mf); - } - } - // if file is not already in the makefile, then add it - else { - return false; - } - return true; -} diff --git a/Source/cmSetTestsPropertiesCommand.cxx b/Source/cmSetTestsPropertiesCommand.cxx index 2e7aeca..c4bff76 100644 --- a/Source/cmSetTestsPropertiesCommand.cxx +++ b/Source/cmSetTestsPropertiesCommand.cxx @@ -2,19 +2,14 @@ file Copyright.txt or https://cmake.org/licensing for details. */ #include "cmSetTestsPropertiesCommand.h" +#include <algorithm> #include <iterator> -#include <cmext/algorithm> - #include "cmExecutionStatus.h" #include "cmMakefile.h" #include "cmStringAlgorithms.h" #include "cmTest.h" -static bool SetOneTest(const std::string& tname, - std::vector<std::string>& propertyPairs, cmMakefile* mf, - std::string& errors); - bool cmSetTestsPropertiesCommand(std::vector<std::string> const& args, cmExecutionStatus& status) { @@ -23,61 +18,33 @@ bool cmSetTestsPropertiesCommand(std::vector<std::string> const& args, return false; } - cmMakefile& mf = status.GetMakefile(); - - // first collect up the list of files - std::vector<std::string> propertyPairs; - int numFiles = 0; - std::vector<std::string>::const_iterator j; - for (j = args.begin(); j != args.end(); ++j) { - if (*j == "PROPERTIES") { - // now loop through the rest of the arguments, new style - ++j; - if (std::distance(j, args.end()) % 2 != 0) { - status.SetError("called with incorrect number of arguments."); - return false; - } - cm::append(propertyPairs, j, args.end()); - break; - } - numFiles++; - } - if (propertyPairs.empty()) { - status.SetError("called with illegal arguments, maybe " - "missing a PROPERTIES specifier?"); + // first identify the properties arguments + auto propsIter = std::find(args.begin(), args.end(), "PROPERTIES"); + if (propsIter == args.end() || propsIter + 1 == args.end()) { + status.SetError("called with illegal arguments, maybe missing a " + "PROPERTIES specifier?"); return false; } - // now loop over all the targets - int i; - for (i = 0; i < numFiles; ++i) { - std::string errors; - bool ret = SetOneTest(args[i], propertyPairs, &mf, errors); - if (!ret) { - status.SetError(errors); - return ret; - } + if (std::distance(propsIter, args.end()) % 2 != 1) { + status.SetError("called with incorrect number of arguments."); + return false; } - return true; -} - -static bool SetOneTest(const std::string& tname, - std::vector<std::string>& propertyPairs, cmMakefile* mf, - std::string& errors) -{ - if (cmTest* test = mf->GetTest(tname)) { - // now loop through all the props and set them - unsigned int k; - for (k = 0; k < propertyPairs.size(); k = k + 2) { - if (!propertyPairs[k].empty()) { - test->SetProperty(propertyPairs[k], propertyPairs[k + 1].c_str()); + // loop over all the tests + for (const std::string& tname : cmStringRange{ args.begin(), propsIter }) { + if (cmTest* test = status.GetMakefile().GetTest(tname)) { + // loop through all the props and set them + for (auto k = propsIter + 1; k != args.end(); k += 2) { + if (!k->empty()) { + test->SetProperty(*k, (k + 1)->c_str()); + } } + } else { + status.SetError( + cmStrCat("Can not find test to add properties to: ", tname)); + return false; } - } else { - errors = cmStrCat("Can not find test to add properties to: ", tname); - return false; } - return true; } diff --git a/Source/cmStandardLexer.h b/Source/cmStandardLexer.h index 55d23c1..cc67ac2 100644 --- a/Source/cmStandardLexer.h +++ b/Source/cmStandardLexer.h @@ -63,7 +63,7 @@ #define YY_NO_UNPUT 1 #define ECHO -#include "cm_kwiml.h" +#include <cm3p/kwiml/int.h> typedef KWIML_INT_int8_t flex_int8_t; typedef KWIML_INT_uint8_t flex_uint8_t; typedef KWIML_INT_int16_t flex_int16_t; diff --git a/Source/cmState.cxx b/Source/cmState.cxx index df013f4..18d8537 100644 --- a/Source/cmState.cxx +++ b/Source/cmState.cxx @@ -265,7 +265,7 @@ void cmState::RemoveCacheEntryProperty(std::string const& key, cmStateSnapshot cmState::Reset() { this->GlobalProperties.Clear(); - this->PropertyDefinitions.clear(); + this->PropertyDefinitions = {}; this->GlobVerificationManager->Reset(); cmStateDetail::PositionType pos = this->SnapshotData.Truncate(); @@ -331,39 +331,23 @@ void cmState::DefineProperty(const std::string& name, const std::string& ShortDescription, const std::string& FullDescription, bool chained) { - this->PropertyDefinitions[scope].DefineProperty( - name, scope, ShortDescription, FullDescription, chained); + this->PropertyDefinitions.DefineProperty(name, scope, ShortDescription, + FullDescription, chained); } cmPropertyDefinition const* cmState::GetPropertyDefinition( const std::string& name, cmProperty::ScopeType scope) const { - if (this->IsPropertyDefined(name, scope)) { - cmPropertyDefinitionMap const& defs = - this->PropertyDefinitions.find(scope)->second; - return &defs.find(name)->second; - } - return nullptr; -} - -bool cmState::IsPropertyDefined(const std::string& name, - cmProperty::ScopeType scope) const -{ - auto it = this->PropertyDefinitions.find(scope); - if (it == this->PropertyDefinitions.end()) { - return false; - } - return it->second.IsPropertyDefined(name); + return this->PropertyDefinitions.GetPropertyDefinition(name, scope); } bool cmState::IsPropertyChained(const std::string& name, cmProperty::ScopeType scope) const { - auto it = this->PropertyDefinitions.find(scope); - if (it == this->PropertyDefinitions.end()) { - return false; + if (auto def = this->GetPropertyDefinition(name, scope)) { + return def->IsChained(); } - return it->second.IsPropertyChained(name); + return false; } void cmState::SetLanguageEnabled(std::string const& l) diff --git a/Source/cmState.h b/Source/cmState.h index e966935..f2bd32a 100644 --- a/Source/cmState.h +++ b/Source/cmState.h @@ -17,7 +17,7 @@ #include "cmListFileCache.h" #include "cmPolicies.h" #include "cmProperty.h" -#include "cmPropertyDefinitionMap.h" +#include "cmPropertyDefinition.h" #include "cmPropertyMap.h" #include "cmStatePrivate.h" #include "cmStateTypes.h" @@ -25,7 +25,6 @@ class cmCacheManager; class cmCommand; class cmGlobVerificationManager; -class cmPropertyDefinition; class cmStateSnapshot; class cmMessenger; class cmExecutionStatus; @@ -131,9 +130,6 @@ public: cmPropertyDefinition const* GetPropertyDefinition( const std::string& name, cmProperty::ScopeType scope) const; - // Is a property defined? - bool IsPropertyDefined(const std::string& name, - cmProperty::ScopeType scope) const; bool IsPropertyChained(const std::string& name, cmProperty::ScopeType scope) const; @@ -225,7 +221,7 @@ private: const std::string& variable, cmListFileBacktrace const& bt); - std::map<cmProperty::ScopeType, cmPropertyDefinitionMap> PropertyDefinitions; + cmPropertyDefinitionMap PropertyDefinitions; std::vector<std::string> EnabledLanguages; std::map<std::string, Command> BuiltinCommands; std::map<std::string, Command> ScriptedCommands; diff --git a/Source/cmSystemTools.cxx b/Source/cmSystemTools.cxx index 23b099a..be799b0 100644 --- a/Source/cmSystemTools.cxx +++ b/Source/cmSystemTools.cxx @@ -14,7 +14,7 @@ #include <cmext/algorithm> -#include "cm_uv.h" +#include <cm3p/uv.h> #include "cmDuration.h" #include "cmProcessOutput.h" @@ -22,7 +22,8 @@ #include "cmStringAlgorithms.h" #if !defined(CMAKE_BOOTSTRAP) -# include "cm_libarchive.h" +# include <cm3p/archive.h> +# include <cm3p/archive_entry.h> # include "cmArchiveWrite.h" # include "cmLocale.h" diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index a776398..4bb48fb 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -215,7 +215,7 @@ public: }; cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, - Visibility vis, cmMakefile* mf, bool perConfig) + Visibility vis, cmMakefile* mf, PerConfig perConfig) : impl(cm::make_unique<cmTargetInternals>()) { assert(mf); @@ -231,7 +231,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, (vis == VisibilityImported || vis == VisibilityImportedGlobally); impl->ImportedGloballyVisible = vis == VisibilityImportedGlobally; impl->BuildInterfaceIncludesAppended = false; - impl->PerConfig = perConfig; + impl->PerConfig = (perConfig == PerConfig::Yes); // Check whether this is a DLL platform. impl->IsDLLPlatform = @@ -307,6 +307,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("Fortran_FORMAT"); initProp("Fortran_MODULE_DIRECTORY"); initProp("Fortran_COMPILER_LAUNCHER"); + initProp("Fortran_PREPROCESS"); initProp("GNUtoMS"); initProp("OSX_ARCHITECTURES"); initProp("IOS_INSTALL_COMBINED"); @@ -372,6 +373,7 @@ cmTarget::cmTarget(std::string const& name, cmStateEnums::TargetType type, initProp("DISABLE_PRECOMPILE_HEADERS"); initProp("UNITY_BUILD"); initPropValue("UNITY_BUILD_BATCH_SIZE", "8"); + initPropValue("UNITY_BUILD_MODE", "BATCH"); initPropValue("PCH_WARN_INVALID", "ON"); #ifdef __APPLE__ if (this->GetGlobalGenerator()->IsXcode()) { diff --git a/Source/cmTarget.h b/Source/cmTarget.h index 8fecd41..6bd47f7 100644 --- a/Source/cmTarget.h +++ b/Source/cmTarget.h @@ -45,8 +45,14 @@ public: VisibilityImportedGlobally }; + enum class PerConfig + { + Yes, + No + }; + cmTarget(std::string const& name, cmStateEnums::TargetType type, - Visibility vis, cmMakefile* mf, bool perConfig); + Visibility vis, cmMakefile* mf, PerConfig perConfig); cmTarget(cmTarget const&) = delete; cmTarget(cmTarget&&) noexcept; diff --git a/Source/cmTestGenerator.cxx b/Source/cmTestGenerator.cxx index 025a7b3..4e41993 100644 --- a/Source/cmTestGenerator.cxx +++ b/Source/cmTestGenerator.cxx @@ -76,7 +76,7 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, cmGeneratorExpression ge(this->Test->GetBacktrace()); // Start the test command. - os << indent << "add_test(" << this->Test->GetName() << " "; + os << indent << "add_test(\"" << this->Test->GetName() << "\" "; // Evaluate command line arguments std::vector<std::string> argv = @@ -126,8 +126,8 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, os << ")\n"; // Output properties for the test. - os << indent << "set_tests_properties(" << this->Test->GetName() - << " PROPERTIES "; + os << indent << "set_tests_properties(\"" << this->Test->GetName() + << "\" PROPERTIES "; for (auto const& i : this->Test->GetProperties().GetList()) { os << " " << i.first << " " << cmOutputConverter::EscapeForCMake( @@ -139,7 +139,8 @@ void cmTestGenerator::GenerateScriptForConfig(std::ostream& os, void cmTestGenerator::GenerateScriptNoConfig(std::ostream& os, Indent indent) { - os << indent << "add_test(" << this->Test->GetName() << " NOT_AVAILABLE)\n"; + os << indent << "add_test(\"" << this->Test->GetName() + << "\" NOT_AVAILABLE)\n"; } bool cmTestGenerator::NeedsScriptNoConfig() const @@ -159,9 +160,8 @@ void cmTestGenerator::GenerateOldStyle(std::ostream& fout, Indent indent) std::string exe = command[0]; cmSystemTools::ConvertToUnixSlashes(exe); - fout << indent; - fout << "add_test("; - fout << this->Test->GetName() << " \"" << exe << "\""; + fout << indent << "add_test(\"" << this->Test->GetName() << "\" \"" << exe + << "\""; for (std::string const& arg : cmMakeRange(command).advance(1)) { // Just double-quote all arguments so they are re-parsed diff --git a/Source/cmUVHandlePtr.cxx b/Source/cmUVHandlePtr.cxx index 23dabb7..df2f64e 100644 --- a/Source/cmUVHandlePtr.cxx +++ b/Source/cmUVHandlePtr.cxx @@ -7,7 +7,7 @@ #include <cstdlib> #include <mutex> -#include "cm_uv.h" +#include <cm3p/uv.h> namespace cm { diff --git a/Source/cmUVHandlePtr.h b/Source/cmUVHandlePtr.h index 3083b60..d9de7f3 100644 --- a/Source/cmUVHandlePtr.h +++ b/Source/cmUVHandlePtr.h @@ -8,7 +8,7 @@ #include <memory> #include <type_traits> -#include "cm_uv.h" +#include <cm3p/uv.h> #if defined(__SUNPRO_CC) diff --git a/Source/cmUVProcessChain.cxx b/Source/cmUVProcessChain.cxx index 543c330..6040fd8 100644 --- a/Source/cmUVProcessChain.cxx +++ b/Source/cmUVProcessChain.cxx @@ -9,7 +9,7 @@ #include <cm/memory> -#include "cm_uv.h" +#include <cm3p/uv.h> #include "cmGetPipes.h" #include "cmUVHandlePtr.h" diff --git a/Source/cmUVProcessChain.h b/Source/cmUVProcessChain.h index cd7397e..b5ccb19 100644 --- a/Source/cmUVProcessChain.h +++ b/Source/cmUVProcessChain.h @@ -11,7 +11,7 @@ #include <string> #include <vector> -#include "cm_uv.h" +#include <cm3p/uv.h> class cmUVProcessChain; diff --git a/Source/cmUVSignalHackRAII.h b/Source/cmUVSignalHackRAII.h index 63599db..60e4ca8 100644 --- a/Source/cmUVSignalHackRAII.h +++ b/Source/cmUVSignalHackRAII.h @@ -3,7 +3,7 @@ #pragma once #include "cmConfigure.h" // IWYU pragma: keep -#include "cm_uv.h" +#include <cm3p/uv.h> #if defined(CMAKE_USE_SYSTEM_LIBUV) && !defined(_WIN32) && \ UV_VERSION_MAJOR == 1 && UV_VERSION_MINOR < 19 diff --git a/Source/cmUVStreambuf.h b/Source/cmUVStreambuf.h index 1c8a771..50faede 100644 --- a/Source/cmUVStreambuf.h +++ b/Source/cmUVStreambuf.h @@ -8,7 +8,7 @@ #include <streambuf> #include <vector> -#include "cm_uv.h" +#include <cm3p/uv.h> #include "cmUVHandlePtr.h" diff --git a/Source/cmVSSetupHelper.h b/Source/cmVSSetupHelper.h index 0980cef..a2fd3d5 100644 --- a/Source/cmVSSetupHelper.h +++ b/Source/cmVSSetupHelper.h @@ -8,13 +8,12 @@ #endif // Published by Visual Studio Setup team +#include <cm3p/Setup.Configuration.h> #include <string> #include <vector> #include <windows.h> -#include "cmvssetup/Setup.Configuration.h" - template <class T> class SmartCOMPtr { diff --git a/Source/cmVersion.h b/Source/cmVersion.h index bfd994d..932ef04 100644 --- a/Source/cmVersion.h +++ b/Source/cmVersion.h @@ -3,7 +3,7 @@ #ifndef cmVersion_h #define cmVersion_h -#include "cm_kwiml.h" +#include <cm3p/kwiml/int.h> /** \class cmVersion * \brief Helper class for providing CMake and CTest version information. diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 2b20a00..de88182 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -248,6 +248,7 @@ cmVisualStudio10TargetGenerator::cmVisualStudio10TargetGenerator( this->LocalGenerator->GetTargetDirectory(this->GeneratorTarget); this->InSourceBuild = (this->Makefile->GetCurrentSourceDirectory() == this->Makefile->GetCurrentBinaryDirectory()); + this->ClassifyAllConfigSources(); } cmVisualStudio10TargetGenerator::~cmVisualStudio10TargetGenerator() @@ -921,13 +922,11 @@ void cmVisualStudio10TargetGenerator::WriteDotNetDocumentationFile(Elem& e0) void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0) { - std::vector<cmSourceFile const*> resxObjs; - this->GeneratorTarget->GetResxSources(resxObjs, ""); - if (!resxObjs.empty()) { + if (!this->ResxObjs.empty()) { Elem e1(e0, "ItemGroup"); std::string srcDir = this->Makefile->GetCurrentSourceDirectory(); ConvertToWindowsSlash(srcDir); - for (cmSourceFile const* oi : resxObjs) { + for (cmSourceFile const* oi : this->ResxObjs) { std::string obj = oi->GetFullPath(); ConvertToWindowsSlash(obj); bool useRelativePath = false; @@ -1016,11 +1015,9 @@ void cmVisualStudio10TargetGenerator::WriteEmbeddedResourceGroup(Elem& e0) void cmVisualStudio10TargetGenerator::WriteXamlFilesGroup(Elem& e0) { - std::vector<cmSourceFile const*> xamlObjs; - this->GeneratorTarget->GetXamlSources(xamlObjs, ""); - if (!xamlObjs.empty()) { + if (!this->XamlObjs.empty()) { Elem e1(e0, "ItemGroup"); - for (cmSourceFile const* oi : xamlObjs) { + for (cmSourceFile const* oi : this->XamlObjs) { std::string obj = oi->GetFullPath(); std::string xamlType; cmProp xamlTypeProperty = oi->GetProperty("VS_XAML_TYPE"); @@ -1329,21 +1326,27 @@ void cmVisualStudio10TargetGenerator::WriteNsightTegraConfigurationValues( void cmVisualStudio10TargetGenerator::WriteCustomCommands(Elem& e0) { this->CSharpCustomCommandNames.clear(); - std::vector<cmSourceFile const*> customCommands; - this->GeneratorTarget->GetCustomCommands(customCommands, ""); - for (cmSourceFile const* si : customCommands) { - this->WriteCustomCommand(e0, si); + + cmSourceFile const* srcCMakeLists = + this->LocalGenerator->CreateVCProjBuildRule(); + + for (cmGeneratorTarget::AllConfigSource const& si : + this->GeneratorTarget->GetAllConfigSources()) { + if (si.Source == srcCMakeLists) { + // Skip explicit reference to CMakeLists.txt source. + continue; + } + this->WriteCustomCommand(e0, si.Source); } // Add CMakeLists.txt file with rule to re-run CMake for user convenience. if (this->GeneratorTarget->GetType() != cmStateEnums::GLOBAL_TARGET && this->GeneratorTarget->GetName() != CMAKE_CHECK_BUILD_SYSTEM_TARGET) { - if (cmSourceFile const* sf = - this->LocalGenerator->CreateVCProjBuildRule()) { + if (srcCMakeLists) { // Write directly rather than through WriteCustomCommand because // we do not want the de-duplication and it has no dependencies. - if (cmCustomCommand const* command = sf->GetCustomCommand()) { - this->WriteCustomRule(e0, sf, *command); + if (cmCustomCommand const* command = srcCMakeLists->GetCustomCommand()) { + this->WriteCustomRule(e0, srcCMakeLists, *command); } } } @@ -1624,11 +1627,9 @@ void cmVisualStudio10TargetGenerator::WriteGroups() } } - std::vector<cmSourceFile const*> resxObjs; - this->GeneratorTarget->GetResxSources(resxObjs, ""); - if (!resxObjs.empty()) { + if (!this->ResxObjs.empty()) { Elem e1(e0, "ItemGroup"); - for (cmSourceFile const* oi : resxObjs) { + for (cmSourceFile const* oi : this->ResxObjs) { std::string obj = oi->GetFullPath(); ConvertToWindowsSlash(obj); Elem e2(e1, "EmbeddedResource"); @@ -1656,7 +1657,7 @@ void cmVisualStudio10TargetGenerator::WriteGroups() } } - if (!resxObjs.empty() || !this->AddedFiles.empty()) { + if (!this->ResxObjs.empty() || !this->AddedFiles.empty()) { std::string guidName = "SG_Filter_Resource Files"; std::string guid = this->GlobalGenerator->GetGUID(guidName); Elem e2(e1, "Filter"); @@ -2209,10 +2210,10 @@ void cmVisualStudio10TargetGenerator::WriteAllSources(Elem& e0) } } break; case cmGeneratorTarget::SourceKindResx: - // Handled elsewhere. + this->ResxObjs.push_back(si.Source); break; case cmGeneratorTarget::SourceKindXaml: - // Handled elsewhere. + this->XamlObjs.push_back(si.Source); break; } @@ -2317,21 +2318,13 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( cmGeneratorExpression::Find(*cincludes) != std::string::npos; includes += *cincludes; } - std::string lang = - this->GlobalGenerator->GetLanguageFromExtension(sf.GetExtension().c_str()); - std::string sourceLang = this->LocalGenerator->GetSourceFileLanguage(sf); - const std::string& linkLanguage = - this->GeneratorTarget->GetLinkerLanguage(""); - bool needForceLang = false; - // source file does not match its extension language - if (lang != sourceLang) { - needForceLang = true; - lang = sourceLang; - } - // if the source file does not match the linker language - // then force c or c++ + + // Force language if the file extension does not match. + std::string lang = this->LocalGenerator->GetSourceFileLanguage(sf); const char* compileAs = 0; - if (needForceLang || (linkLanguage != lang)) { + if (lang != + this->GlobalGenerator->GetLanguageFromExtension( + sf.GetExtension().c_str())) { if (lang == "CXX") { // force a C++ file type compileAs = "CompileAsCpp"; @@ -2340,6 +2333,7 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( compileAs = "CompileAsC"; } } + bool noWinRT = this->TargetCompileAsWinRT && lang == "C"; // for the first time we need a new line if there is something // produced here. @@ -2376,7 +2370,7 @@ void cmVisualStudio10TargetGenerator::OutputSourceSpecificFlags( pchOptions = this->GeneratorTarget->GetPchUseCompileOptions(config, lang); } - customAndPchOptions += pchOptions; + customAndPchOptions = cmStrCat(customAndPchOptions, ';', pchOptions); } // if we have flags or defines for this config then @@ -2736,13 +2730,6 @@ bool cmVisualStudio10TargetGenerator::ComputeClOptions( this->LocalGenerator->AddCompileOptions(flags, this->GeneratorTarget, langForClCompile, configName); } - // set the correct language - if (linkLanguage == "C") { - clOptions.AddFlag("CompileAs", "CompileAsC"); - } - if (linkLanguage == "CXX") { - clOptions.AddFlag("CompileAs", "CompileAsCpp"); - } // Put the IPO enabled configurations into a set. if (this->GeneratorTarget->IsIPOEnabled(linkLanguage, configName)) { @@ -3143,6 +3130,17 @@ bool cmVisualStudio10TargetGenerator::ComputeCudaOptions( cudaOptions.AddIncludes(this->GetIncludes(configName, "CUDA")); cudaOptions.AddFlag("UseHostInclude", "false"); + // Add runtime library selection flag. + std::string const& cudaRuntime = + this->GeneratorTarget->GetRuntimeLinkLibrary("CUDA", configName); + if (cudaRuntime == "STATIC") { + cudaOptions.AddFlag("CudaRuntime", "Static"); + } else if (cudaRuntime == "SHARED") { + cudaOptions.AddFlag("CudaRuntime", "Shared"); + } else if (cudaRuntime == "NONE") { + cudaOptions.AddFlag("CudaRuntime", "None"); + } + this->CudaOptions[configName] = std::move(pOptions); return true; } @@ -3493,12 +3491,12 @@ void cmVisualStudio10TargetGenerator::WriteAntBuildOptions( // its location as the root source directory. std::string rootDir = this->LocalGenerator->GetCurrentSourceDirectory(); { - std::vector<cmSourceFile const*> extraSources; - this->GeneratorTarget->GetExtraSources(extraSources, ""); - for (cmSourceFile const* si : extraSources) { - if ("androidmanifest.xml" == - cmSystemTools::LowerCase(si->GetLocation().GetName())) { - rootDir = si->GetLocation().GetDirectory(); + for (cmGeneratorTarget::AllConfigSource const& source : + this->GeneratorTarget->GetAllConfigSources()) { + if (source.Kind == cmGeneratorTarget::SourceKindExtra && + "androidmanifest.xml" == + cmSystemTools::LowerCase(source.Source->GetLocation().GetName())) { + rootDir = source.Source->GetLocation().GetDirectory(); break; } } @@ -3657,10 +3655,6 @@ bool cmVisualStudio10TargetGenerator::ComputeLinkOptions( std::vector<std::string> libVec; std::vector<std::string> vsTargetVec; this->AddLibraries(cli, libVec, vsTargetVec, config); - if (cm::contains(linkClosure->Languages, "CUDA") && - this->CudaOptions[config] != nullptr) { - this->CudaOptions[config]->FixCudaRuntime(this->GeneratorTarget); - } std::string standardLibsVar = cmStrCat("CMAKE_", linkLanguage, "_STANDARD_LIBRARIES"); std::string const& libs = this->Makefile->GetSafeDefinition(standardLibsVar); @@ -4133,7 +4127,8 @@ void cmVisualStudio10TargetGenerator::WriteProjectReferences(Elem& e0) } // Don't reference targets that don't produce any output. - if (dt->GetManagedType("") == cmGeneratorTarget::ManagedType::Undefined) { + if (dt->GetManagedType(this->Configurations[0]) == + cmGeneratorTarget::ManagedType::Undefined) { e2.Element("ReferenceOutputAssembly", "false"); e2.Element("CopyToOutputDirectory", "Never"); } @@ -4234,12 +4229,13 @@ void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile( this->GlobalGenerator->TargetsWindowsPhone()) && (cmStateEnums::EXECUTABLE == this->GeneratorTarget->GetType())) { std::string pfxFile; - std::vector<cmSourceFile const*> certificates; - this->GeneratorTarget->GetCertificates(certificates, ""); - for (cmSourceFile const* si : certificates) { - pfxFile = this->ConvertPath(si->GetFullPath(), false); - ConvertToWindowsSlash(pfxFile); - break; + for (cmGeneratorTarget::AllConfigSource const& source : + this->GeneratorTarget->GetAllConfigSources()) { + if (source.Kind == cmGeneratorTarget::SourceKindCertificate) { + pfxFile = this->ConvertPath(source.Source->GetFullPath(), false); + ConvertToWindowsSlash(pfxFile); + break; + } } if (this->IsMissingFiles && @@ -4285,28 +4281,61 @@ void cmVisualStudio10TargetGenerator::WriteWinRTPackageCertificateKeyFile( } } +void cmVisualStudio10TargetGenerator::ClassifyAllConfigSources() +{ + for (cmGeneratorTarget::AllConfigSource const& source : + this->GeneratorTarget->GetAllConfigSources()) { + this->ClassifyAllConfigSource(source); + } +} + +void cmVisualStudio10TargetGenerator::ClassifyAllConfigSource( + cmGeneratorTarget::AllConfigSource const& acs) +{ + switch (acs.Kind) { + case cmGeneratorTarget::SourceKindResx: { + // Build and save the name of the corresponding .h file + // This relationship will be used later when building the project files. + // Both names would have been auto generated from Visual Studio + // where the user supplied the file name and Visual Studio + // appended the suffix. + std::string resx = acs.Source->ResolveFullPath(); + std::string hFileName = resx.substr(0, resx.find_last_of('.')) + ".h"; + this->ExpectedResxHeaders.insert(hFileName); + } break; + case cmGeneratorTarget::SourceKindXaml: { + // Build and save the name of the corresponding .h and .cpp file + // This relationship will be used later when building the project files. + // Both names would have been auto generated from Visual Studio + // where the user supplied the file name and Visual Studio + // appended the suffix. + std::string xaml = acs.Source->ResolveFullPath(); + std::string hFileName = xaml + ".h"; + std::string cppFileName = xaml + ".cpp"; + this->ExpectedXamlHeaders.insert(hFileName); + this->ExpectedXamlSources.insert(cppFileName); + } break; + default: + break; + } +} + bool cmVisualStudio10TargetGenerator::IsResxHeader( const std::string& headerFile) { - std::set<std::string> expectedResxHeaders; - this->GeneratorTarget->GetExpectedResxHeaders(expectedResxHeaders, ""); - return expectedResxHeaders.count(headerFile) > 0; + return this->ExpectedResxHeaders.count(headerFile) > 0; } bool cmVisualStudio10TargetGenerator::IsXamlHeader( const std::string& headerFile) { - std::set<std::string> expectedXamlHeaders; - this->GeneratorTarget->GetExpectedXamlHeaders(expectedXamlHeaders, ""); - return expectedXamlHeaders.count(headerFile) > 0; + return this->ExpectedXamlHeaders.count(headerFile) > 0; } bool cmVisualStudio10TargetGenerator::IsXamlSource( const std::string& sourceFile) { - std::set<std::string> expectedXamlSources; - this->GeneratorTarget->GetExpectedXamlSources(expectedXamlSources, ""); - return expectedXamlSources.count(sourceFile) > 0; + return this->ExpectedXamlSources.count(sourceFile) > 0; } void cmVisualStudio10TargetGenerator::WriteApplicationTypeSettings(Elem& e1) @@ -4387,39 +4416,38 @@ void cmVisualStudio10TargetGenerator::VerifyNecessaryFiles() // For Windows and Windows Phone executables, we will assume that if a // manifest is not present that we need to add all the necessary files if (this->GeneratorTarget->GetType() == cmStateEnums::EXECUTABLE) { - std::vector<cmSourceFile const*> manifestSources; - this->GeneratorTarget->GetAppManifest(manifestSources, ""); - { - std::string const& v = this->GlobalGenerator->GetSystemVersion(); - if (this->GlobalGenerator->TargetsWindowsPhone()) { - if (v == "8.0") { - // Look through the sources for WMAppManifest.xml - std::vector<cmSourceFile const*> extraSources; - this->GeneratorTarget->GetExtraSources(extraSources, ""); - bool foundManifest = false; - for (cmSourceFile const* si : extraSources) { - // Need to do a lowercase comparison on the filename - if ("wmappmanifest.xml" == - cmSystemTools::LowerCase(si->GetLocation().GetName())) { - foundManifest = true; - break; - } - } - if (!foundManifest) { - this->IsMissingFiles = true; - } - } else if (v == "8.1") { - if (manifestSources.empty()) { - this->IsMissingFiles = true; + std::vector<cmGeneratorTarget::AllConfigSource> manifestSources = + this->GeneratorTarget->GetAllConfigSources( + cmGeneratorTarget::SourceKindAppManifest); + std::string const& v = this->GlobalGenerator->GetSystemVersion(); + if (this->GlobalGenerator->TargetsWindowsPhone()) { + if (v == "8.0") { + // Look through the sources for WMAppManifest.xml + bool foundManifest = false; + for (cmGeneratorTarget::AllConfigSource const& source : + this->GeneratorTarget->GetAllConfigSources()) { + if (source.Kind == cmGeneratorTarget::SourceKindExtra && + "wmappmanifest.xml" == + cmSystemTools::LowerCase( + source.Source->GetLocation().GetName())) { + foundManifest = true; + break; } } - } else if (this->GlobalGenerator->TargetsWindowsStore()) { + if (!foundManifest) { + this->IsMissingFiles = true; + } + } else if (v == "8.1") { if (manifestSources.empty()) { - if (v == "8.0") { - this->IsMissingFiles = true; - } else if (v == "8.1" || cmHasLiteralPrefix(v, "10.0")) { - this->IsMissingFiles = true; - } + this->IsMissingFiles = true; + } + } + } else if (this->GlobalGenerator->TargetsWindowsStore()) { + if (manifestSources.empty()) { + if (v == "8.0") { + this->IsMissingFiles = true; + } else if (v == "8.1" || cmHasLiteralPrefix(v, "10.0")) { + this->IsMissingFiles = true; } } } diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index e3782f4..7c71de3 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -13,10 +13,11 @@ #include <unordered_map> #include <vector> +#include "cmGeneratorTarget.h" + class cmComputeLinkInformation; class cmCustomCommand; class cmGeneratedFileStream; -class cmGeneratorTarget; class cmGlobalVisualStudio10Generator; class cmLocalVisualStudio10Generator; class cmMakefile; @@ -238,6 +239,14 @@ private: using ToolSourceMap = std::map<std::string, ToolSources>; ToolSourceMap Tools; + std::set<std::string> ExpectedResxHeaders; + std::set<std::string> ExpectedXamlHeaders; + std::set<std::string> ExpectedXamlSources; + std::vector<cmSourceFile const*> ResxObjs; + std::vector<cmSourceFile const*> XamlObjs; + void ClassifyAllConfigSources(); + void ClassifyAllConfigSource(cmGeneratorTarget::AllConfigSource const& acs); + using ConfigToSettings = std::unordered_map<std::string, std::unordered_map<std::string, std::string>>; diff --git a/Source/cmVisualStudioGeneratorOptions.cxx b/Source/cmVisualStudioGeneratorOptions.cxx index 7775f62..937b4ce 100644 --- a/Source/cmVisualStudioGeneratorOptions.cxx +++ b/Source/cmVisualStudioGeneratorOptions.cxx @@ -151,34 +151,6 @@ bool cmVisualStudioGeneratorOptions::UsingSBCS() const return false; } -void cmVisualStudioGeneratorOptions::FixCudaRuntime(cmGeneratorTarget* target) -{ - std::map<std::string, FlagValue>::const_iterator i = - this->FlagMap.find("CudaRuntime"); - if (i == this->FlagMap.end()) { - // User didn't provide am override so get the property value - cmProp runtimeLibraryValue = target->GetProperty("CUDA_RUNTIME_LIBRARY"); - if (runtimeLibraryValue) { - std::string cudaRuntime = - cmSystemTools::UpperCase(cmGeneratorExpression::Evaluate( - *runtimeLibraryValue, this->LocalGenerator, this->Configuration, - target)); - if (cudaRuntime == "STATIC") { - this->AddFlag("CudaRuntime", "Static"); - } - if (cudaRuntime == "SHARED") { - this->AddFlag("CudaRuntime", "Shared"); - } - if (cudaRuntime == "NONE") { - this->AddFlag("CudaRuntime", "None"); - } - } else { - // nvcc default is static - this->AddFlag("CudaRuntime", "Static"); - } - } -} - void cmVisualStudioGeneratorOptions::FixCudaCodeGeneration() { // Extract temporary values stored by our flag table. diff --git a/Source/cmVisualStudioGeneratorOptions.h b/Source/cmVisualStudioGeneratorOptions.h index b335694..f9b50a7 100644 --- a/Source/cmVisualStudioGeneratorOptions.h +++ b/Source/cmVisualStudioGeneratorOptions.h @@ -63,7 +63,6 @@ public: bool UsingSBCS() const; void FixCudaCodeGeneration(); - void FixCudaRuntime(cmGeneratorTarget* target); void FixManifestUACFlags(); diff --git a/Source/cmWorkerPool.cxx b/Source/cmWorkerPool.cxx index aa0d6b3..12aba4f 100644 --- a/Source/cmWorkerPool.cxx +++ b/Source/cmWorkerPool.cxx @@ -13,7 +13,7 @@ #include <cm/memory> -#include "cm_uv.h" +#include <cm3p/uv.h> #include "cmRange.h" #include "cmStringAlgorithms.h" @@ -469,11 +469,9 @@ void cmWorkerPoolWorker::UVProcessStart(uv_async_t* handle) void cmWorkerPoolWorker::UVProcessFinished() { - { - std::lock_guard<std::mutex> lock(Proc_.Mutex); - if (Proc_.ROP && (Proc_.ROP->IsFinished() || !Proc_.ROP->IsStarted())) { - Proc_.ROP.reset(); - } + std::lock_guard<std::mutex> lock(Proc_.Mutex); + if (Proc_.ROP && (Proc_.ROP->IsFinished() || !Proc_.ROP->IsStarted())) { + Proc_.ROP.reset(); } // Notify idling thread Proc_.Condition.notify_one(); @@ -532,6 +530,7 @@ public: unsigned int JobsProcessing = 0; std::deque<cmWorkerPool::JobHandleT> Queue; std::condition_variable Condition; + std::condition_variable ConditionFence; std::vector<std::unique_ptr<cmWorkerPoolWorker>> Workers; // -- References @@ -593,19 +592,12 @@ bool cmWorkerPoolInternal::Process() void cmWorkerPoolInternal::Abort() { - bool notifyThreads = false; // Clear all jobs and set abort flag - { - std::lock_guard<std::mutex> guard(Mutex); - if (Processing && !Aborting) { - // Register abort and clear queue - Aborting = true; - Queue.clear(); - notifyThreads = true; - } - } - if (notifyThreads) { - // Wake threads + std::lock_guard<std::mutex> guard(Mutex); + if (!Aborting) { + // Register abort and clear queue + Aborting = true; + Queue.clear(); Condition.notify_all(); } } @@ -669,7 +661,7 @@ void cmWorkerPoolInternal::Work(unsigned int workerIndex) if (Aborting) { break; } - // Wait for new jobs + // Wait for new jobs on the main CV if (Queue.empty()) { ++WorkersIdle; Condition.wait(uLock); @@ -677,20 +669,34 @@ void cmWorkerPoolInternal::Work(unsigned int workerIndex) continue; } - // Check for fence jobs - if (FenceProcessing || Queue.front()->IsFence()) { - if (JobsProcessing != 0) { - Condition.wait(uLock); - continue; - } - // No jobs get processed. Set the fence job processing flag. - FenceProcessing = true; + // If there is a fence currently active or waiting, + // sleep on the main CV and try again. + if (FenceProcessing) { + Condition.wait(uLock); + continue; } // Pop next job from queue jobHandle = std::move(Queue.front()); Queue.pop_front(); + // Check for fence jobs + bool raisedFence = false; + if (jobHandle->IsFence()) { + FenceProcessing = true; + raisedFence = true; + // Wait on the Fence CV until all pending jobs are done. + while (JobsProcessing != 0 && !Aborting) { + ConditionFence.wait(uLock); + } + // When aborting, explicitly kick all threads alive once more. + if (Aborting) { + FenceProcessing = false; + Condition.notify_all(); + break; + } + } + // Unlocked scope for job processing ++JobsProcessing; { @@ -701,11 +707,18 @@ void cmWorkerPoolInternal::Work(unsigned int workerIndex) } --JobsProcessing; - // Was this a fence job? - if (FenceProcessing) { + // If this was the thread that entered fence processing + // originally, notify all idling workers that the fence + // is done. + if (raisedFence) { FenceProcessing = false; Condition.notify_all(); } + // If fence processing is still not done, notify the + // the fencing worker when all active jobs are done. + if (FenceProcessing && JobsProcessing == 0) { + ConditionFence.notify_all(); + } } // Decrement running workers count diff --git a/Source/cmXCodeScheme.cxx b/Source/cmXCodeScheme.cxx index 9ac1457..f4c2f2d 100644 --- a/Source/cmXCodeScheme.cxx +++ b/Source/cmXCodeScheme.cxx @@ -396,7 +396,8 @@ void cmXCodeScheme::WriteBuildableReference(cmXMLWriter& xout, xout.BreakAttributes(); xout.Attribute("BuildableIdentifier", "primary"); xout.Attribute("BlueprintIdentifier", xcObj->GetId()); - xout.Attribute("BuildableName", xcObj->GetTarget()->GetFullName()); + std::string const noConfig; // FIXME: What config to use here? + xout.Attribute("BuildableName", xcObj->GetTarget()->GetFullName(noConfig)); xout.Attribute("BlueprintName", xcObj->GetTarget()->GetName()); xout.Attribute("ReferencedContainer", "container:" + container); xout.EndElement(); diff --git a/Source/cmXMLParser.cxx b/Source/cmXMLParser.cxx index ad5c4ba..24da8c6 100644 --- a/Source/cmXMLParser.cxx +++ b/Source/cmXMLParser.cxx @@ -7,9 +7,9 @@ #include <iostream> #include <sstream> -#include "cmsys/FStream.hxx" +#include <cm3p/expat.h> -#include "cm_expat.h" +#include "cmsys/FStream.hxx" cmXMLParser::cmXMLParser() { diff --git a/Source/cmake.cxx b/Source/cmake.cxx index c95cf4f..65d5f10 100644 --- a/Source/cmake.cxx +++ b/Source/cmake.cxx @@ -57,7 +57,7 @@ #if !defined(CMAKE_BOOTSTRAP) # include <unordered_map> -# include "cm_jsoncpp_writer.h" +# include <cm3p/json/writer.h> # include "cmFileAPI.h" # include "cmGraphVizWriter.h" @@ -138,6 +138,7 @@ using JsonValueMapType = std::unordered_map<std::string, Json::Value>; static bool cmakeCheckStampFile(const std::string& stampName); static bool cmakeCheckStampList(const std::string& stampList); +#ifndef CMAKE_BOOTSTRAP static void cmWarnUnusedCliWarning(const std::string& variable, int /*unused*/, void* ctx, const char* /*unused*/, const cmMakefile* /*unused*/) @@ -145,6 +146,7 @@ static void cmWarnUnusedCliWarning(const std::string& variable, int /*unused*/, cmake* cm = reinterpret_cast<cmake*>(ctx); cm->MarkCliAsUsed(variable); } +#endif cmake::cmake(Role role, cmState::Mode mode) : FileTimeCache(cm::make_unique<cmFileTimeCache>()) @@ -289,7 +291,8 @@ void cmake::CleanupCommandsAndMacros() // Parse the args bool cmake::SetCacheArgs(const std::vector<std::string>& args) { - bool findPackageMode = false; + auto findPackageMode = false; + auto seenScriptOption = false; for (unsigned int i = 1; i < args.size(); ++i) { std::string const& arg = args[i]; if (cmHasLiteralPrefix(arg, "-D")) { @@ -444,6 +447,11 @@ bool cmake::SetCacheArgs(const std::vector<std::string>& args) this->SetHomeOutputDirectory( cmSystemTools::GetCurrentWorkingDirectory()); this->ReadListFile(args, path); + seenScriptOption = true; + } else if (arg == "--" && seenScriptOption) { + // Stop processing CMake args and avoid possible errors + // when arbitrary args are given to CMake script. + break; } else if (cmHasLiteralPrefix(arg, "--find-package")) { findPackageMode = true; } diff --git a/Source/cmake.h b/Source/cmake.h index cfcd264..cd152cb 100644 --- a/Source/cmake.h +++ b/Source/cmake.h @@ -27,7 +27,7 @@ #include "cmStateTypes.h" #if !defined(CMAKE_BOOTSTRAP) -# include "cm_jsoncpp_value.h" +# include <cm3p/json/value.h> #endif class cmExternalMakefileProjectGeneratorFactory; diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index 84d0538..b12990b 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -1,6 +1,8 @@ /* Distributed under the OSI-approved BSD 3-Clause License. See accompanying file Copyright.txt or https://cmake.org/licensing for details. */ +#include "cmConfigure.h" // IWYU pragma: keep + #include <cassert> #include <cctype> #include <climits> @@ -11,6 +13,8 @@ #include <cmext/algorithm> +#include <cm3p/uv.h> + #include "cmDocumentationEntry.h" // IWYU pragma: keep #include "cmGlobalGenerator.h" #include "cmMakefile.h" @@ -27,8 +31,6 @@ #endif #include "cmsys/Encoding.hxx" - -#include "cm_uv.h" #if defined(_WIN32) && !defined(CMAKE_BOOTSTRAP) # include "cmsys/ConsoleBuf.hxx" #endif @@ -318,6 +320,7 @@ int do_cmake(int ac, char const* const* av) return 0; } +#ifndef CMAKE_BOOTSTRAP int extract_job_number(int& index, char const* current, char const* next, int len_of_flag) { @@ -347,6 +350,7 @@ int extract_job_number(int& index, char const* current, char const* next, } return jobs; } +#endif int do_build(int ac, char const* const* av) { diff --git a/Source/cmcmd.cxx b/Source/cmcmd.cxx index a8e07e4..de76d73 100644 --- a/Source/cmcmd.cxx +++ b/Source/cmcmd.cxx @@ -4,10 +4,9 @@ #include <cmext/algorithm> +#include <cm3p/uv.h> #include <fcntl.h> -#include "cm_uv.h" - #include "cmDuration.h" #include "cmGlobalGenerator.h" #include "cmLocalGenerator.h" diff --git a/Source/kwsys/CommandLineArguments.cxx b/Source/kwsys/CommandLineArguments.cxx index a2ed874..e45db36 100644 --- a/Source/kwsys/CommandLineArguments.cxx +++ b/Source/kwsys/CommandLineArguments.cxx @@ -20,9 +20,9 @@ #include <sstream> #include <vector> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> +#include <cstdio> +#include <cstdlib> +#include <cstring> #ifdef _MSC_VER # pragma warning(disable : 4786) diff --git a/Source/kwsys/Directory.cxx b/Source/kwsys/Directory.cxx index d640948..be9158e 100644 --- a/Source/kwsys/Directory.cxx +++ b/Source/kwsys/Directory.cxx @@ -103,7 +103,7 @@ void Directory::Clear() namespace KWSYS_NAMESPACE { -bool Directory::Load(const std::string& name) +bool Directory::Load(const std::string& name, std::string* errorMessage) { this->Clear(); # if (defined(_MSC_VER) && _MSC_VER < 1300) || defined(__BORLANDC__) @@ -146,7 +146,8 @@ bool Directory::Load(const std::string& name) return _findclose(srchHandle) != -1; } -unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name) +unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name, + std::string* errorMessage) { # if (defined(_MSC_VER) && _MSC_VER < 1300) || defined(__BORLANDC__) // Older Visual C++ and Embarcadero compilers. @@ -192,6 +193,8 @@ unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name) # include <sys/types.h> # include <dirent.h> +# include <errno.h> +# include <string.h> // PGI with glibc has trouble with dirent and large file support: // http://www.pgroup.com/userforum/viewtopic.php? @@ -209,29 +212,46 @@ unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name) namespace KWSYS_NAMESPACE { -bool Directory::Load(const std::string& name) +bool Directory::Load(const std::string& name, std::string* errorMessage) { this->Clear(); + errno = 0; DIR* dir = opendir(name.c_str()); if (!dir) { + if (errorMessage != nullptr) { + *errorMessage = std::string(strerror(errno)); + } return false; } + errno = 0; for (kwsys_dirent* d = readdir(dir); d; d = readdir(dir)) { this->Internal->Files.emplace_back(d->d_name); } + if (errno != 0) { + if (errorMessage != nullptr) { + *errorMessage = std::string(strerror(errno)); + } + return false; + } + this->Internal->Path = name; closedir(dir); return true; } -unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name) +unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name, + std::string* errorMessage) { + errno = 0; DIR* dir = opendir(name.c_str()); if (!dir) { + if (errorMessage != nullptr) { + *errorMessage = std::string(strerror(errno)); + } return 0; } @@ -239,6 +259,13 @@ unsigned long Directory::GetNumberOfFilesInDirectory(const std::string& name) for (kwsys_dirent* d = readdir(dir); d; d = readdir(dir)) { count++; } + if (errno != 0) { + if (errorMessage != nullptr) { + *errorMessage = std::string(strerror(errno)); + } + return false; + } + closedir(dir); return count; } diff --git a/Source/kwsys/Directory.hxx.in b/Source/kwsys/Directory.hxx.in index 9b0f4c3..7bc9db0 100644 --- a/Source/kwsys/Directory.hxx.in +++ b/Source/kwsys/Directory.hxx.in @@ -35,7 +35,7 @@ public: * in that directory. 0 is returned if the directory can not be * opened, 1 if it is opened. */ - bool Load(const std::string&); + bool Load(const std::string&, std::string* errorMessage = nullptr); /** * Return the number of files in the current directory. @@ -46,7 +46,8 @@ public: * Return the number of files in the specified directory. * A higher performance static method. */ - static unsigned long GetNumberOfFilesInDirectory(const std::string&); + static unsigned long GetNumberOfFilesInDirectory( + const std::string&, std::string* errorMessage = nullptr); /** * Return the file at the given index, the indexing is 0 based diff --git a/Source/kwsys/EncodingCXX.cxx b/Source/kwsys/EncodingCXX.cxx index 5cad934..c68c73c 100644 --- a/Source/kwsys/EncodingCXX.cxx +++ b/Source/kwsys/EncodingCXX.cxx @@ -17,8 +17,8 @@ # include "Encoding.hxx.in" #endif -#include <stdlib.h> -#include <string.h> +#include <cstdlib> +#include <cstring> #include <vector> #ifdef _MSC_VER diff --git a/Source/kwsys/Glob.cxx b/Source/kwsys/Glob.cxx index 8e30f92..5452f73 100644 --- a/Source/kwsys/Glob.cxx +++ b/Source/kwsys/Glob.cxx @@ -23,9 +23,9 @@ #include <string> #include <vector> -#include <ctype.h> -#include <stdio.h> -#include <string.h> +#include <cctype> +#include <cstdio> +#include <cstring> namespace KWSYS_NAMESPACE { #if defined(_WIN32) || defined(__APPLE__) || defined(__CYGWIN__) // On Windows and Apple, no difference between lower and upper case @@ -182,7 +182,15 @@ bool Glob::RecurseDirectory(std::string::size_type start, const std::string& dir, GlobMessages* messages) { kwsys::Directory d; - if (!d.Load(dir)) { + std::string errorMessage; + if (!d.Load(dir, &errorMessage)) { + if (messages) { + if (!errorMessage.empty()) { + messages->push_back(Message(Glob::warning, + "Error listing directory '" + dir + + "'! Reason: '" + errorMessage + "'")); + } + } return true; } unsigned long cc; @@ -278,7 +286,9 @@ void Glob::ProcessDirectory(std::string::size_type start, // std::cout << "ProcessDirectory: " << dir << std::endl; bool last = (start == this->Internals->Expressions.size() - 1); if (last && this->Recurse) { - this->RecurseDirectory(start, dir, messages); + if (kwsys::SystemTools::FileIsDirectory(dir)) { + this->RecurseDirectory(start, dir, messages); + } return; } diff --git a/Source/kwsys/Glob.hxx.in b/Source/kwsys/Glob.hxx.in index 170766f..b5a34d5 100644 --- a/Source/kwsys/Glob.hxx.in +++ b/Source/kwsys/Glob.hxx.in @@ -28,6 +28,7 @@ public: enum MessageType { error, + warning, cyclicRecursion }; diff --git a/Source/kwsys/RegularExpression.cxx b/Source/kwsys/RegularExpression.cxx index 5e6f8da..4f74eba 100644 --- a/Source/kwsys/RegularExpression.cxx +++ b/Source/kwsys/RegularExpression.cxx @@ -28,8 +28,8 @@ # include "RegularExpression.hxx.in" #endif -#include <stdio.h> -#include <string.h> +#include <cstdio> +#include <cstring> namespace KWSYS_NAMESPACE { @@ -367,8 +367,7 @@ bool RegularExpression::compile(const char* exp) // Allocate space. //#ifndef _WIN32 - if (this->program != nullptr) - delete[] this->program; + delete[] this->program; //#endif this->program = new char[comp.regsize]; this->progsize = static_cast<int>(comp.regsize); diff --git a/Source/kwsys/SystemInformation.cxx b/Source/kwsys/SystemInformation.cxx index ba9fa67..c565823 100644 --- a/Source/kwsys/SystemInformation.cxx +++ b/Source/kwsys/SystemInformation.cxx @@ -64,9 +64,9 @@ typedef int siginfo_t; #else # include <sys/types.h> -# include <errno.h> // extern int errno; +# include <cerrno> // extern int errno; +# include <csignal> # include <fcntl.h> -# include <signal.h> # include <sys/resource.h> // getrlimit # include <sys/time.h> # include <sys/utsname.h> // int uname(struct utsname *buf); @@ -163,11 +163,11 @@ typedef struct rlimit ResourceLimitType; # undef KWSYS_SYSTEMINFORMATION_HAS_SYMBOL_LOOKUP #endif -#include <ctype.h> // int isdigit(int c); +#include <cctype> // int isdigit(int c); +#include <cstdio> +#include <cstdlib> +#include <cstring> #include <memory.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> #if defined(KWSYS_USE_LONG_LONG) # if defined(KWSYS_IOS_HAS_OSTREAM_LONG_LONG) @@ -1366,7 +1366,7 @@ std::string SymbolProperties::GetFileName(const std::string& path) const { std::string file(path); if (!this->ReportPath) { - size_t at = file.rfind("/"); + size_t at = file.rfind('/'); if (at != std::string::npos) { file.erase(0, at + 1); } @@ -3387,8 +3387,8 @@ std::string SystemInformationImplementation::ExtractValueFromCpuInfoFile( size_t pos = buffer.find(word, init); if (pos != std::string::npos) { this->CurrentPositionInFile = pos; - pos = buffer.find(":", pos); - size_t pos2 = buffer.find("\n", pos); + pos = buffer.find(':', pos); + size_t pos2 = buffer.find('\n', pos); if (pos != std::string::npos && pos2 != std::string::npos) { // It may happen that the beginning matches, but this is still not the // requested key. @@ -3937,7 +3937,7 @@ std::string SystemInformationImplementation::GetProgramStack(int firstFrame, int wholePath) { std::ostringstream oss; - std::string programStack = ""; + std::string programStack; #ifdef KWSYS_SYSTEMINFORMATION_HAS_DBGHELP (void)wholePath; @@ -4688,7 +4688,7 @@ std::string SystemInformationImplementation::ExtractValueFromSysCtl( size_t pos = this->SysCtlBuffer.find(word); if (pos != std::string::npos) { pos = this->SysCtlBuffer.find(": ", pos); - size_t pos2 = this->SysCtlBuffer.find("\n", pos); + size_t pos2 = this->SysCtlBuffer.find('\n', pos); if (pos != std::string::npos && pos2 != std::string::npos) { return this->SysCtlBuffer.substr(pos + 2, pos2 - pos - 2); } @@ -5500,13 +5500,13 @@ void SystemInformationImplementation::TrimNewline(std::string& output) { // remove \r std::string::size_type pos = 0; - while ((pos = output.find("\r", pos)) != std::string::npos) { + while ((pos = output.find('\r', pos)) != std::string::npos) { output.erase(pos); } // remove \n pos = 0; - while ((pos = output.find("\n", pos)) != std::string::npos) { + while ((pos = output.find('\n', pos)) != std::string::npos) { output.erase(pos); } } diff --git a/Source/kwsys/SystemTools.cxx b/Source/kwsys/SystemTools.cxx index 3a6ceec..a6d210f 100644 --- a/Source/kwsys/SystemTools.cxx +++ b/Source/kwsys/SystemTools.cxx @@ -24,6 +24,7 @@ #include KWSYS_HEADER(Encoding.h) #include KWSYS_HEADER(Encoding.hxx) +#include <algorithm> #include <fstream> #include <iostream> #include <set> @@ -49,15 +50,15 @@ # pragma set woff 1375 /* base class destructor not virtual */ #endif -#include <ctype.h> -#include <errno.h> +#include <cctype> +#include <cerrno> #ifdef __QNX__ # include <malloc.h> /* for malloc/free on QNX */ #endif -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> +#include <cstdio> +#include <cstdlib> +#include <cstring> +#include <ctime> #if defined(_WIN32) && !defined(_MSC_VER) && defined(__GNUC__) # include <strings.h> /* for strcasecmp */ @@ -69,7 +70,7 @@ // support for realpath call #ifndef _WIN32 -# include <limits.h> +# include <climits> # include <pwd.h> # include <sys/ioctl.h> # include <sys/time.h> @@ -80,7 +81,7 @@ # include <sys/param.h> # include <termios.h> # endif -# include <signal.h> /* sigprocmask */ +# include <csignal> /* sigprocmask */ #endif #ifdef __linux @@ -892,8 +893,12 @@ const char* SystemTools::GetExecutableExtension() FILE* SystemTools::Fopen(const std::string& file, const char* mode) { #ifdef _WIN32 + // Remove any 'e', which is supported on UNIX, but not Windows. + std::wstring trimmedMode = Encoding::ToWide(mode); + trimmedMode.erase(std::remove(trimmedMode.begin(), trimmedMode.end(), L'e'), + trimmedMode.end()); return _wfopen(Encoding::ToWindowsExtendedPath(file).c_str(), - Encoding::ToWide(mode).c_str()); + trimmedMode.c_str()); #else return fopen(file.c_str(), mode); #endif @@ -2113,7 +2118,7 @@ std::string SystemTools::ConvertToUnixOutputPath(const std::string& path) ret.erase(pos, 1); } // escape spaces and () in the path - if (ret.find_first_of(" ") != std::string::npos) { + if (ret.find_first_of(' ') != std::string::npos) { std::string result; char lastch = 1; for (const char* ch = ret.c_str(); *ch != '\0'; ++ch) { @@ -2511,8 +2516,8 @@ bool SystemTools::CopyADirectory(const std::string& source, return false; } for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) { - if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), ".") && - strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), "..")) { + if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), ".") != 0 && + strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), "..") != 0) { std::string fullPath = source; fullPath += "/"; fullPath += dir.GetFile(static_cast<unsigned long>(fileNum)); @@ -2674,8 +2679,8 @@ bool SystemTools::RemoveADirectory(const std::string& source) dir.Load(source); size_t fileNum; for (fileNum = 0; fileNum < dir.GetNumberOfFiles(); ++fileNum) { - if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), ".") && - strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), "..")) { + if (strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), ".") != 0 && + strcmp(dir.GetFile(static_cast<unsigned long>(fileNum)), "..") != 0) { std::string fullPath = source; fullPath += "/"; fullPath += dir.GetFile(static_cast<unsigned long>(fileNum)); @@ -3153,7 +3158,7 @@ bool SystemTools::SplitProgramPath(const std::string& in_name, SystemTools::ConvertToUnixSlashes(dir); if (!SystemTools::FileIsDirectory(dir)) { - std::string::size_type slashPos = dir.rfind("/"); + std::string::size_type slashPos = dir.rfind('/'); if (slashPos != std::string::npos) { file = dir.substr(slashPos + 1); dir.resize(slashPos); @@ -3711,7 +3716,7 @@ std::string SystemTools::GetFilenamePath(const std::string& filename) std::string fn = filename; SystemTools::ConvertToUnixSlashes(fn); - std::string::size_type slash_pos = fn.rfind("/"); + std::string::size_type slash_pos = fn.rfind('/'); if (slash_pos == 0) { return "/"; } diff --git a/Source/kwsys/SystemTools.hxx.in b/Source/kwsys/SystemTools.hxx.in index cd7b728..ae08e57 100644 --- a/Source/kwsys/SystemTools.hxx.in +++ b/Source/kwsys/SystemTools.hxx.in @@ -549,7 +549,8 @@ public: */ /** - * Open a file considering unicode. + * Open a file considering unicode. On Windows, if 'e' is present in + * mode it is first discarded. */ static FILE* Fopen(const std::string& file, const char* mode); diff --git a/Source/kwsys/testCommandLineArguments.cxx b/Source/kwsys/testCommandLineArguments.cxx index 79ebe1a..0786751 100644 --- a/Source/kwsys/testCommandLineArguments.cxx +++ b/Source/kwsys/testCommandLineArguments.cxx @@ -12,8 +12,8 @@ #include <iostream> #include <vector> -#include <stddef.h> /* size_t */ -#include <string.h> /* strcmp */ +#include <cstddef> /* size_t */ +#include <cstring> /* strcmp */ static void* random_ptr = reinterpret_cast<void*>(0x123); diff --git a/Source/kwsys/testCommandLineArguments1.cxx b/Source/kwsys/testCommandLineArguments1.cxx index cbc3002..2f6b735 100644 --- a/Source/kwsys/testCommandLineArguments1.cxx +++ b/Source/kwsys/testCommandLineArguments1.cxx @@ -12,8 +12,8 @@ #include <iostream> #include <vector> -#include <assert.h> /* assert */ -#include <string.h> /* strcmp */ +#include <cassert> /* assert */ +#include <cstring> /* strcmp */ int testCommandLineArguments1(int argc, char* argv[]) { @@ -51,9 +51,7 @@ int testCommandLineArguments1(int argc, char* argv[]) std::cout << "Value of N: " << n << std::endl; std::cout << "Value of M: " << m << std::endl; std::cout << "Value of P: " << p << std::endl; - if (m) { - delete[] m; - } + delete[] m; char** newArgv = nullptr; int newArgc = 0; diff --git a/Source/kwsys/testDirectory.cxx b/Source/kwsys/testDirectory.cxx index b1ab0c8..eb3ca32 100644 --- a/Source/kwsys/testDirectory.cxx +++ b/Source/kwsys/testDirectory.cxx @@ -57,7 +57,11 @@ int _doLongPathTest() Directory testdir; // Set res to failure if the directory doesn't load - res += !testdir.Load(testdirpath); + std::string errorMessage = ""; + res += !testdir.Load(testdirpath, &errorMessage); + if (errorMessage != "") { + std::cerr << "Failed to list directory: " << errorMessage << std::endl; + } // Increment res failure if the directory appears empty res += testdir.GetNumberOfFiles() == 0; // Increment res failures if the path has changed from @@ -73,6 +77,34 @@ int _doLongPathTest() return res; } +int _nonExistentDirectoryTest() +{ + using namespace kwsys; + int res = 0; + std::string testdirpath(TEST_SYSTEMTOOLS_BINARY_DIR + "/directory_testing/doesnt_exist/"); + std::string errorMessage; + Directory testdir; + + errorMessage = "foo"; + // Increment res failure if directory lists + res += testdir.Load(testdirpath, &errorMessage); +#if !defined(_WIN32) || defined(__CYGWIN__) + // Increment res failure if errorMessage is unmodified + res += (errorMessage == "foo"); +#endif + + errorMessage = "foo"; + // Increment res failure if directory has files + res += (testdir.GetNumberOfFilesInDirectory(testdirpath, &errorMessage) > 0); +#if !defined(_WIN32) || defined(__CYGWIN__) + // Increment res failure if errorMessage is unmodified + res += (errorMessage == "foo"); +#endif + + return res; +} + int _copyDirectoryTest() { using namespace kwsys; @@ -106,5 +138,6 @@ int _copyDirectoryTest() int testDirectory(int, char* []) { - return _doLongPathTest() + _copyDirectoryTest(); + return _doLongPathTest() + _nonExistentDirectoryTest() + + _copyDirectoryTest(); } diff --git a/Source/kwsys/testDynload.c b/Source/kwsys/testDynload.c index c49f747..33a431e 100644 --- a/Source/kwsys/testDynload.c +++ b/Source/kwsys/testDynload.c @@ -8,6 +8,6 @@ DL_EXPORT int TestDynamicLoaderData = 0; -DL_EXPORT void TestDynamicLoaderSymbolPointer() +DL_EXPORT void TestDynamicLoaderSymbolPointer(void) { } diff --git a/Source/kwsys/testEncoding.cxx b/Source/kwsys/testEncoding.cxx index d672aed..ee93e8d 100644 --- a/Source/kwsys/testEncoding.cxx +++ b/Source/kwsys/testEncoding.cxx @@ -10,10 +10,10 @@ #include KWSYS_HEADER(Encoding.h) #include <algorithm> +#include <clocale> +#include <cstdlib> +#include <cstring> #include <iostream> -#include <locale.h> -#include <stdlib.h> -#include <string.h> // Work-around CMake dependency scanning limitation. This must // duplicate the above list of headers. @@ -59,7 +59,7 @@ static int testHelloWorldEncoding() std::string str2 = kwsys::Encoding::ToNarrow(wstr); wchar_t* c_wstr = kwsysEncoding_DupToWide(str.c_str()); char* c_str2 = kwsysEncoding_DupToNarrow(c_wstr); - if (!wstr.empty() && (str != str2 || strcmp(c_str2, str.c_str()))) { + if (!wstr.empty() && (str != str2 || strcmp(c_str2, str.c_str()) != 0)) { std::cout << "converted string was different: " << str2 << std::endl; std::cout << "converted string was different: " << c_str2 << std::endl; ret++; diff --git a/Source/kwsys/testFStream.cxx b/Source/kwsys/testFStream.cxx index 5009e98..5762378 100644 --- a/Source/kwsys/testFStream.cxx +++ b/Source/kwsys/testFStream.cxx @@ -7,7 +7,7 @@ #endif #include KWSYS_HEADER(FStream.hxx) -#include <string.h> +#include <cstring> #ifdef __BORLANDC__ # include <mem.h> /* memcmp */ #endif diff --git a/Source/kwsys/testSystemTools.cxx b/Source/kwsys/testSystemTools.cxx index 8909b49..ff8e2b2 100644 --- a/Source/kwsys/testSystemTools.cxx +++ b/Source/kwsys/testSystemTools.cxx @@ -20,10 +20,10 @@ // left on disk. #include <testSystemTools.h> +#include <cstdlib> /* free */ +#include <cstring> /* strcmp */ #include <iostream> #include <sstream> -#include <stdlib.h> /* free */ -#include <string.h> /* strcmp */ #if defined(_WIN32) && !defined(__CYGWIN__) # include <io.h> /* _umask (MSVC) / umask (Borland) */ # ifdef _MSC_VER @@ -507,7 +507,7 @@ static bool CheckStringOperations() char* cres = kwsys::SystemTools::AppendStrings("Mary Had A", " Little Lamb."); - if (strcmp(cres, "Mary Had A Little Lamb.")) { + if (strcmp(cres, "Mary Had A Little Lamb.") != 0) { std::cerr << "Problem with AppendStrings " << "\"Mary Had A\" \" Little Lamb.\"" << std::endl; res = false; @@ -515,7 +515,7 @@ static bool CheckStringOperations() delete[] cres; cres = kwsys::SystemTools::AppendStrings("Mary Had", " A ", "Little Lamb."); - if (strcmp(cres, "Mary Had A Little Lamb.")) { + if (strcmp(cres, "Mary Had A Little Lamb.") != 0) { std::cerr << "Problem with AppendStrings " << "\"Mary Had\" \" A \" \"Little Lamb.\"" << std::endl; res = false; @@ -529,7 +529,7 @@ static bool CheckStringOperations() } cres = kwsys::SystemTools::RemoveChars("Mary Had A Little Lamb.", "aeiou"); - if (strcmp(cres, "Mry Hd A Lttl Lmb.")) { + if (strcmp(cres, "Mry Hd A Lttl Lmb.") != 0) { std::cerr << "Problem with RemoveChars " << "\"Mary Had A Little Lamb.\"" << std::endl; res = false; @@ -537,7 +537,7 @@ static bool CheckStringOperations() delete[] cres; cres = kwsys::SystemTools::RemoveCharsButUpperHex("Mary Had A Little Lamb."); - if (strcmp(cres, "A")) { + if (strcmp(cres, "A") != 0) { std::cerr << "Problem with RemoveCharsButUpperHex " << "\"Mary Had A Little Lamb.\"" << std::endl; res = false; @@ -546,7 +546,7 @@ static bool CheckStringOperations() char* cres2 = strdup("Mary Had A Little Lamb."); kwsys::SystemTools::ReplaceChars(cres2, "aeiou", 'X'); - if (strcmp(cres2, "MXry HXd A LXttlX LXmb.")) { + if (strcmp(cres2, "MXry HXd A LXttlX LXmb.") != 0) { std::cerr << "Problem with ReplaceChars " << "\"Mary Had A Little Lamb.\"" << std::endl; res = false; @@ -568,7 +568,7 @@ static bool CheckStringOperations() } cres = kwsys::SystemTools::DuplicateString("Mary Had A Little Lamb."); - if (strcmp(cres, "Mary Had A Little Lamb.")) { + if (strcmp(cres, "Mary Had A Little Lamb.") != 0) { std::cerr << "Problem with DuplicateString " << "\"Mary Had A Little Lamb.\"" << std::endl; res = false; |