diff options
Diffstat (limited to 'Source')
40 files changed, 810 insertions, 396 deletions
diff --git a/Source/CMakeLists.txt b/Source/CMakeLists.txt index ec473d2..6d585ee 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 diff --git a/Source/CMakeVersion.cmake b/Source/CMakeVersion.cmake index b820d73..f283497 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 20200515) +set(CMake_VERSION_PATCH 20200521) #set(CMake_VERSION_RC 0) set(CMake_VERSION_IS_DIRTY 0) 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/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/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/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/cmFileCommand.cxx b/Source/cmFileCommand.cxx index f3d49c3..268c5d1 100644 --- a/Source/cmFileCommand.cxx +++ b/Source/cmFileCommand.cxx @@ -677,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 @@ -770,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) { @@ -795,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/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index a44126c..2f9da1c 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -693,6 +693,7 @@ const char* cmGeneratorTarget::GetFileSuffixInternal( void cmGeneratorTarget::ClearSourcesCache() { + this->AllConfigSources.clear(); this->KindedSourcesMap.clear(); this->LinkImplementationLanguageIsContextDependent = true; this->Objects.clear(); @@ -975,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) { @@ -1039,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 { @@ -1096,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 += "/"; @@ -1726,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") { @@ -1742,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 { @@ -1809,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; @@ -3179,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; + } + } } } diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index ff03914..c8732bc 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, 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 6370ed2..0b7ba04 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -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 dcd5a66..57c7808 100644 --- a/Source/cmGlobalGenerator.h +++ b/Source/cmGlobalGenerator.h @@ -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/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/cmMakefile.cxx b/Source/cmMakefile.cxx index 6f05d45..154da50 100644 --- a/Source/cmMakefile.cxx +++ b/Source/cmMakefile.cxx @@ -2081,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); @@ -4261,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/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/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/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 7a53a1d..3135a06 100644 --- a/Source/cmSetSourceFilesPropertiesCommand.cxx +++ b/Source/cmSetSourceFilesPropertiesCommand.cxx @@ -10,9 +10,16 @@ #include "cmExecutionStatus.h" #include "cmMakefile.h" +#include "cmSetPropertyCommand.h" #include "cmSourceFile.h" #include "cmStringAlgorithms.h" +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,16 +30,86 @@ bool cmSetSourceFilesPropertiesCommand(std::vector<std::string> const& args, // break the arguments into source file names and properties // old style allows for specifier before PROPERTIES keyword - static const cm::string_view propNames[] = { - "ABSTRACT", "GENERATED", "WRAP_EXCLUDE", - "COMPILE_FLAGS", "OBJECT_DEPENDS", "PROPERTIES" + static const cm::string_view prop_names[] = { + "ABSTRACT", "GENERATED", "WRAP_EXCLUDE", "COMPILE_FLAGS", + "OBJECT_DEPENDS", "PROPERTIES", "DIRECTORY", "TARGET_DIRECTORY" }; - auto propsBegin = std::find_first_of( - args.begin(), args.end(), std::begin(propNames), std::end(propNames)); + 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; + } + + 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 for each directory scope represented by a + // cmMakefile instance. + std::string 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 true; +} + +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; // build the property pairs - for (auto j = propsBegin; j != args.end(); ++j) { + 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); @@ -40,26 +117,26 @@ bool cmSetSourceFilesPropertiesCommand(std::vector<std::string> const& args, } else if (*j == "COMPILE_FLAGS") { propertyPairs.emplace_back("COMPILE_FLAGS"); ++j; - if (j == args.end()) { - status.SetError("called with incorrect number of arguments " - "COMPILE_FLAGS with no flags"); + if (j == prop_end) { + errors = "called with incorrect number of arguments " + "COMPILE_FLAGS with no flags"; return false; } propertyPairs.push_back(*j); } else if (*j == "OBJECT_DEPENDS") { propertyPairs.emplace_back("OBJECT_DEPENDS"); ++j; - if (j == args.end()) { - status.SetError("called with incorrect number of arguments " - "OBJECT_DEPENDS with no dependencies"); + 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") { // PROPERTIES is followed by new style prop value pairs - cmStringRange newStyleProps{ j + 1, args.end() }; + cmStringRange newStyleProps{ j + 1, prop_end }; if (newStyleProps.size() % 2 != 0) { - status.SetError("called with incorrect number of arguments."); + errors = "called with incorrect number of arguments."; return false; } // set newStyleProps as is. @@ -67,16 +144,16 @@ bool cmSetSourceFilesPropertiesCommand(std::vector<std::string> const& args, // break out of the loop. break; } else { - status.SetError("called with illegal arguments, maybe missing a " - "PROPERTIES specifier?"); + errors = "called with illegal arguments, maybe missing a " + "PROPERTIES specifier?"; return false; } } // loop over all the files - for (const std::string& sfname : cmStringRange{ args.begin(), propsBegin }) { + for (const std::string& sfname : cmStringRange{ file_begin, file_end }) { // get the source file - if (cmSourceFile* sf = status.GetMakefile().GetOrCreateSource(sfname)) { + 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/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/cmTarget.cxx b/Source/cmTarget.cxx index d43fbe5..e165f4c 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 = 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/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 93c09fe..97f7093 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. @@ -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)) { @@ -3493,12 +3480,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; } } @@ -4133,7 +4120,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 +4222,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 +4274,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 +4409,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/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/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/Glob.cxx b/Source/kwsys/Glob.cxx index fad6ee1..5452f73 100644 --- a/Source/kwsys/Glob.cxx +++ b/Source/kwsys/Glob.cxx @@ -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/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(); } |