summaryrefslogtreecommitdiffstats
path: root/Source
diff options
context:
space:
mode:
authorCarsten Rudolph <18394207+crud89@users.noreply.github.com>2022-01-22 09:29:46 (GMT)
committerBrad King <brad.king@kitware.com>2022-01-22 11:35:41 (GMT)
commitb2f8f0bb87b3b49a39d1db4333bffc5405166245 (patch)
treebbead21bb96a02373d752526f275eb503bd1a803 /Source
parent193b8fca52b5665387dbc7f3199981d9e6cd4b79 (diff)
downloadCMake-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.cxx3
-rw-r--r--Source/cmBuildOptions.h25
-rw-r--r--Source/cmGeneratorTarget.cxx20
-rw-r--r--Source/cmGeneratorTarget.h3
-rw-r--r--Source/cmGlobalGenerator.cxx2
-rw-r--r--Source/cmGlobalVisualStudio10Generator.cxx69
-rw-r--r--Source/cmGlobalVisualStudio10Generator.h2
-rw-r--r--Source/cmVisualStudio10TargetGenerator.cxx40
-rw-r--r--Source/cmVisualStudio10TargetGenerator.h1
-rw-r--r--Source/cmakemain.cxx23
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);