diff options
author | Carsten Rudolph <18394207+crud89@users.noreply.github.com> | 2022-01-22 09:29:46 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2022-01-22 11:35:41 (GMT) |
commit | b2f8f0bb87b3b49a39d1db4333bffc5405166245 (patch) | |
tree | bbead21bb96a02373d752526f275eb503bd1a803 /Source | |
parent | 193b8fca52b5665387dbc7f3199981d9e6cd4b79 (diff) | |
download | CMake-b2f8f0bb87b3b49a39d1db4333bffc5405166245.zip CMake-b2f8f0bb87b3b49a39d1db4333bffc5405166245.tar.gz CMake-b2f8f0bb87b3b49a39d1db4333bffc5405166245.tar.bz2 |
cmGlobalVisualStudio10Generator: Auto restore NuGet packages.
Diffstat (limited to 'Source')
-rw-r--r-- | Source/CTest/cmCTestBuildAndTestHandler.cxx | 3 | ||||
-rw-r--r-- | Source/cmBuildOptions.h | 25 | ||||
-rw-r--r-- | Source/cmGeneratorTarget.cxx | 20 | ||||
-rw-r--r-- | Source/cmGeneratorTarget.h | 3 | ||||
-rw-r--r-- | Source/cmGlobalGenerator.cxx | 2 | ||||
-rw-r--r-- | Source/cmGlobalVisualStudio10Generator.cxx | 69 | ||||
-rw-r--r-- | Source/cmGlobalVisualStudio10Generator.h | 2 | ||||
-rw-r--r-- | Source/cmVisualStudio10TargetGenerator.cxx | 40 | ||||
-rw-r--r-- | Source/cmVisualStudio10TargetGenerator.h | 1 | ||||
-rw-r--r-- | Source/cmakemain.cxx | 23 |
10 files changed, 180 insertions, 8 deletions
diff --git a/Source/CTest/cmCTestBuildAndTestHandler.cxx b/Source/CTest/cmCTestBuildAndTestHandler.cxx index 9b5e319..e09b4dd 100644 --- a/Source/CTest/cmCTestBuildAndTestHandler.cxx +++ b/Source/CTest/cmCTestBuildAndTestHandler.cxx @@ -265,7 +265,8 @@ int cmCTestBuildAndTestHandler::RunCMakeAndTest(std::string* outstring) config = "Debug"; } - cmBuildOptions buildOptions(!this->BuildNoClean, false); + cmBuildOptions buildOptions(!this->BuildNoClean, false, + PackageResolveMode::Disable); int retVal = cm.GetGlobalGenerator()->Build( cmake::NO_BUILD_PARALLEL_LEVEL, this->SourceDir, this->BinaryDir, this->BuildProject, { tar }, output, this->BuildMakeProgram, config, diff --git a/Source/cmBuildOptions.h b/Source/cmBuildOptions.h index ed26703..58baeef 100644 --- a/Source/cmBuildOptions.h +++ b/Source/cmBuildOptions.h @@ -4,13 +4,35 @@ #include "cmConfigure.h" // IWYU pragma: keep +/** \brief Defines how to resolve packages **/ +enum class PackageResolveMode +{ + /** \brief Defines behavior based on cache variable (e.g. + CMAKE_VS_NUGET_PACKAGE_RESTORE). This is the default. **/ + FromCacheVariable, + + /** \brief Ignore behavior defined by cache variable and forces packages to + be resolved prior to build. **/ + Force, + + /** \brief Ignore behavior defined by cache variable and forces packages to + be resolved, but skip the actual build. **/ + OnlyResolve, + + /** \brief Ignore behavior defined by cache variable and dont resolve any + packages **/ + Disable +}; + struct cmBuildOptions { public: cmBuildOptions() noexcept = default; - explicit cmBuildOptions(bool clean, bool fast) noexcept + explicit cmBuildOptions(bool clean, bool fast, + PackageResolveMode resolveMode) noexcept : Clean(clean) , Fast(fast) + , ResolveMode(resolveMode) { } explicit cmBuildOptions(const cmBuildOptions&) noexcept = default; @@ -18,4 +40,5 @@ public: bool Clean = false; bool Fast = false; + PackageResolveMode ResolveMode = PackageResolveMode::FromCacheVariable; }; diff --git a/Source/cmGeneratorTarget.cxx b/Source/cmGeneratorTarget.cxx index 421e136..45e3b64 100644 --- a/Source/cmGeneratorTarget.cxx +++ b/Source/cmGeneratorTarget.cxx @@ -8102,6 +8102,26 @@ cmLinkItem cmGeneratorTarget::ResolveLinkItem(BT<std::string> const& name, return cmLinkItem(resolved.Target, false, bt); } +bool cmGeneratorTarget::HasPackageReferences() const +{ + return this->IsInBuildSystem() && + !this->GetProperty("VS_PACKAGE_REFERENCES")->empty(); +} + +std::vector<std::string> cmGeneratorTarget::GetPackageReferences() const +{ + std::vector<std::string> packageReferences; + + if (this->IsInBuildSystem()) { + if (cmValue vsPackageReferences = + this->GetProperty("VS_PACKAGE_REFERENCES")) { + cmExpandList(*vsPackageReferences, packageReferences); + } + } + + return packageReferences; +} + std::string cmGeneratorTarget::GetPDBDirectory(const std::string& config) const { if (OutputInfo const* info = this->GetOutputInfo(config)) { diff --git a/Source/cmGeneratorTarget.h b/Source/cmGeneratorTarget.h index 71212c4..a58dc93 100644 --- a/Source/cmGeneratorTarget.h +++ b/Source/cmGeneratorTarget.h @@ -424,6 +424,9 @@ public: cmLinkItem ResolveLinkItem(BT<std::string> const& name, cmLocalGenerator const* lg) const; + bool HasPackageReferences() const; + std::vector<std::string> GetPackageReferences() const; + // Compute the set of languages compiled by the target. This is // computed every time it is called because the languages can change // when source file properties are changed and we do not have enough diff --git a/Source/cmGlobalGenerator.cxx b/Source/cmGlobalGenerator.cxx index 8559aba..156ecce 100644 --- a/Source/cmGlobalGenerator.cxx +++ b/Source/cmGlobalGenerator.cxx @@ -1994,7 +1994,7 @@ int cmGlobalGenerator::TryCompile(int jobs, const std::string& srcdir, } std::string config = mf->GetSafeDefinition("CMAKE_TRY_COMPILE_CONFIGURATION"); - cmBuildOptions defaultBuildOptions(false, fast); + cmBuildOptions defaultBuildOptions(false, fast, PackageResolveMode::Disable); return this->Build(jobs, srcdir, bindir, projectName, newTarget, output, "", config, defaultBuildOptions, false, diff --git a/Source/cmGlobalVisualStudio10Generator.cxx b/Source/cmGlobalVisualStudio10Generator.cxx index 5634def..6b060a6 100644 --- a/Source/cmGlobalVisualStudio10Generator.cxx +++ b/Source/cmGlobalVisualStudio10Generator.cxx @@ -1180,6 +1180,63 @@ cmGlobalVisualStudio10Generator::GenerateBuildCommand( } } makeCommand.Add(targetProject); + + // Check if we do need a restore at all (i.e. if there are package + // references and restore has not been disabled by a command line option. + PackageResolveMode restoreMode = buildOptions.ResolveMode; + bool requiresRestore = true; + + if (restoreMode == PackageResolveMode::Disable) { + requiresRestore = false; + } else if (cmValue cached = + this->CMakeInstance->GetState()->GetCacheEntryValue( + tname + "_REQUIRES_VS_PACKAGE_RESTORE")) { + requiresRestore = cached.IsOn(); + } else { + // There are no package references defined. + requiresRestore = false; + } + + // If a restore is required, evaluate the restore mode. + if (requiresRestore) { + if (restoreMode == PackageResolveMode::OnlyResolve) { + // Only invoke the restore target on the project. + makeCommand.Add("/t:Restore"); + } else { + // Invoke restore target, unless it has been explicitly disabled. + bool restorePackages = true; + + if (this->Version < VS15) { + // Package restore is only supported starting from Visual Studio + // 2017. Package restore must be executed manually using NuGet + // shell for older versions. + this->CMakeInstance->IssueMessage( + MessageType::WARNING, + "Restoring package references is only supported for Visual " + "Studio 2017 and later. You have to manually restore the " + "packages using NuGet before building the project."); + restorePackages = false; + } else if (restoreMode == PackageResolveMode::FromCacheVariable) { + // Decide if a restore is performed, based on a cache variable. + if (cmValue cached = + this->CMakeInstance->GetState()->GetCacheEntryValue( + "CMAKE_VS_NUGET_PACKAGE_RESTORE")) + restorePackages = cached.IsOn(); + } + + if (restorePackages) { + if (this->IsMsBuildRestoreSupported()) { + makeCommand.Add("/restore"); + } else { + GeneratedMakeCommand restoreCommand; + restoreCommand.Add(makeProgramSelected); + restoreCommand.Add(targetProject); + restoreCommand.Add("/t:Restore"); + makeCommands.emplace_back(restoreCommand); + } + } + } + } } std::string configArg = "/p:Configuration="; @@ -1561,6 +1618,18 @@ cmIDEFlagTable const* cmGlobalVisualStudio10Generator::GetNasmFlagTable() const return LoadFlagTable(std::string(), this->DefaultNasmFlagTableName, "NASM"); } +bool cmGlobalVisualStudio10Generator::IsMsBuildRestoreSupported() const +{ + if (this->Version >= VS16) { + return true; + } + + static std::string const vsVer15_7_5 = "15.7.27703.2042"; + cm::optional<std::string> vsVer = this->GetVSInstanceVersion(); + return (vsVer && + cmSystemTools::VersionCompareGreaterEq(*vsVer, vsVer15_7_5)); +} + std::string cmGlobalVisualStudio10Generator::GetClFlagTableName() const { std::string const& toolset = this->GetPlatformToolsetString(); diff --git a/Source/cmGlobalVisualStudio10Generator.h b/Source/cmGlobalVisualStudio10Generator.h index aea999d..4977a84 100644 --- a/Source/cmGlobalVisualStudio10Generator.h +++ b/Source/cmGlobalVisualStudio10Generator.h @@ -173,6 +173,8 @@ public: cmIDEFlagTable const* GetMasmFlagTable() const; cmIDEFlagTable const* GetNasmFlagTable() const; + bool IsMsBuildRestoreSupported() const; + protected: cmGlobalVisualStudio10Generator(cmake* cm, const std::string& name, std::string const& platformInGeneratorName); diff --git a/Source/cmVisualStudio10TargetGenerator.cxx b/Source/cmVisualStudio10TargetGenerator.cxx index 685d34d..fb8351d 100644 --- a/Source/cmVisualStudio10TargetGenerator.cxx +++ b/Source/cmVisualStudio10TargetGenerator.cxx @@ -431,6 +431,9 @@ void cmVisualStudio10TargetGenerator::Generate() // The groups are stored in a separate file for VS 10 this->WriteGroups(); + + // Update cache with project-specific entries. + this->UpdateCache(); } void cmVisualStudio10TargetGenerator::WriteClassicMsBuildProjectFile( @@ -1000,11 +1003,9 @@ bool cmVisualStudio10TargetGenerator::HasCustomCommands() const void cmVisualStudio10TargetGenerator::WritePackageReferences(Elem& e0) { - std::vector<std::string> packageReferences; - if (cmValue vsPackageReferences = - this->GeneratorTarget->GetProperty("VS_PACKAGE_REFERENCES")) { - cmExpandList(*vsPackageReferences, packageReferences); - } + std::vector<std::string> packageReferences = + this->GeneratorTarget->GetPackageReferences(); + if (!packageReferences.empty()) { Elem e1(e0, "ItemGroup"); for (std::string const& ri : packageReferences) { @@ -5366,3 +5367,32 @@ void cmVisualStudio10TargetGenerator::WriteStdOutEncodingUtf8(Elem& e1) e1.Element("StdOutEncoding", "UTF-8"); } } + +void cmVisualStudio10TargetGenerator::UpdateCache() +{ + std::vector<std::string> packageReferences; + + if (this->GeneratorTarget->HasPackageReferences()) { + // Store a cache entry that later determines, if a package restore is + // required. + this->GeneratorTarget->Makefile->AddCacheDefinition( + this->GeneratorTarget->GetName() + "_REQUIRES_VS_PACKAGE_RESTORE", "ON", + "Value Computed by CMake", cmStateEnums::STATIC); + } else { + // If there are any dependencies that require package restore, inherit the + // cache variable. + cmGlobalGenerator::TargetDependSet const& unordered = + this->GlobalGenerator->GetTargetDirectDepends(this->GeneratorTarget); + using OrderedTargetDependSet = + cmGlobalVisualStudioGenerator::OrderedTargetDependSet; + OrderedTargetDependSet depends(unordered, CMAKE_CHECK_BUILD_SYSTEM_TARGET); + + for (cmGeneratorTarget const* dt : depends) { + if (dt->HasPackageReferences()) { + this->GeneratorTarget->Makefile->AddCacheDefinition( + this->GeneratorTarget->GetName() + "_REQUIRES_VS_PACKAGE_RESTORE", + "ON", "Value Computed by CMake", cmStateEnums::STATIC); + } + } + } +} diff --git a/Source/cmVisualStudio10TargetGenerator.h b/Source/cmVisualStudio10TargetGenerator.h index 8d2b77d..ba44a6f 100644 --- a/Source/cmVisualStudio10TargetGenerator.h +++ b/Source/cmVisualStudio10TargetGenerator.h @@ -198,6 +198,7 @@ private: std::string GetCSharpSourceLink(cmSourceFile const* source); void WriteStdOutEncodingUtf8(Elem& e1); + void UpdateCache(); private: friend class cmVS10GeneratorOptions; diff --git a/Source/cmakemain.cxx b/Source/cmakemain.cxx index 0f128ce..22fdcf8 100644 --- a/Source/cmakemain.cxx +++ b/Source/cmakemain.cxx @@ -447,6 +447,7 @@ int do_build(int ac, char const* const* av) bool cleanFirst = false; bool foundClean = false; bool foundNonClean = false; + PackageResolveMode resolveMode = PackageResolveMode::FromCacheVariable; bool verbose = cmSystemTools::HasEnv("VERBOSE"); std::string presetName; bool listPresets = false; @@ -480,6 +481,22 @@ int do_build(int ac, char const* const* av) } return false; }; + auto resolvePackagesLambda = [&](std::string const& value) -> bool { + std::string v = value; + std::transform(v.begin(), v.end(), v.begin(), ::tolower); + + if (v == "on") { + resolveMode = PackageResolveMode::Force; + } else if (v == "only") { + resolveMode = PackageResolveMode::OnlyResolve; + } else if (v == "off") { + resolveMode = PackageResolveMode::Disable; + } else { + return false; + } + + return true; + }; auto verboseLambda = [&](std::string const&) -> bool { verbose = true; return true; @@ -516,6 +533,8 @@ int do_build(int ac, char const* const* av) cleanFirst = true; return true; } }, + CommandArgument{ "--resolve-package-references", + CommandArgument::Values::One, resolvePackagesLambda }, CommandArgument{ "-v", CommandArgument::Values::Zero, verboseLambda }, CommandArgument{ "--verbose", CommandArgument::Values::Zero, verboseLambda }, @@ -641,6 +660,8 @@ int do_build(int ac, char const* const* av) " --config <cfg> = For multi-configuration tools, choose <cfg>.\n" " --clean-first = Build target 'clean' first, then build.\n" " (To clean only, use --target 'clean'.)\n" + " --resolve-package-references={on|only|off}\n" + " = Restore/resolve package references during build.\n" " --verbose, -v = Enable verbose output - if supported - including\n" " the build commands to be executed. \n" " -- = Pass remaining options to the native tool.\n" @@ -658,6 +679,8 @@ int do_build(int ac, char const* const* av) cmakemainProgressCallback(msg, prog, &cm); }); + cmBuildOptions buildOptions(cleanFirst, false, resolveMode); + return cm.Build(jobs, std::move(dir), std::move(targets), std::move(config), std::move(nativeOptions), buildOptions, verbose, presetName, listPresets); |