Browse Source

cmGlobalVisualStudio10Generator: Auto restore NuGet packages.

Carsten Rudolph 3 years ago
parent
commit
b2f8f0bb87
32 changed files with 319 additions and 8 deletions
  1. 1 0
      Help/manual/cmake-variables.7.rst
  2. 11 0
      Help/manual/cmake.1.rst
  3. 10 0
      Help/release/dev/vs-package-restore.rst
  4. 22 0
      Help/variable/CMAKE_VS_NUGET_PACKAGE_RESTORE.rst
  5. 2 1
      Source/CTest/cmCTestBuildAndTestHandler.cxx
  6. 24 1
      Source/cmBuildOptions.h
  7. 20 0
      Source/cmGeneratorTarget.cxx
  8. 3 0
      Source/cmGeneratorTarget.h
  9. 1 1
      Source/cmGlobalGenerator.cxx
  10. 69 0
      Source/cmGlobalVisualStudio10Generator.cxx
  11. 2 0
      Source/cmGlobalVisualStudio10Generator.h
  12. 35 5
      Source/cmVisualStudio10TargetGenerator.cxx
  13. 1 0
      Source/cmVisualStudio10TargetGenerator.h
  14. 23 0
      Source/cmakemain.cxx
  15. 1 0
      Tests/RunCMake/CMakeLists.txt
  16. 1 0
      Tests/RunCMake/CommandLine/build-invalid-package-resolve-arg-result.txt
  17. 1 0
      Tests/RunCMake/CommandLine/build-invalid-package-resolve-arg-stderr.txt
  18. 3 0
      Tests/RunCMake/VsNugetPackageRestore/CMakeLists.txt
  19. 17 0
      Tests/RunCMake/VsNugetPackageRestore/Package/CMakeLists.txt
  20. 9 0
      Tests/RunCMake/VsNugetPackageRestore/Package/Library.cs
  21. 14 0
      Tests/RunCMake/VsNugetPackageRestore/Program.cs
  22. 5 0
      Tests/RunCMake/VsNugetPackageRestore/Repository/NuGetTestProject/1.0.0/.nupkg.metadata
  23. BIN
      Tests/RunCMake/VsNugetPackageRestore/Repository/NuGetTestProject/1.0.0/nugettestproject.1.0.0.nupkg
  24. 1 0
      Tests/RunCMake/VsNugetPackageRestore/Repository/NuGetTestProject/1.0.0/nugettestproject.1.0.0.nupkg.sha512
  25. 11 0
      Tests/RunCMake/VsNugetPackageRestore/Repository/NuGetTestProject/1.0.0/nugettestproject.nuspec
  26. 12 0
      Tests/RunCMake/VsNugetPackageRestore/RunCMakeTest.cmake
  27. 9 0
      Tests/RunCMake/VsNugetPackageRestore/VsNugetPackageRestore.cmake
  28. 7 0
      Tests/RunCMake/VsNugetPackageRestore/nuget.config.in
  29. 1 0
      Tests/RunCMake/VsNugetPackageRestore/vs-nuget-package-restore-off-result.txt
  30. 1 0
      Tests/RunCMake/VsNugetPackageRestore/vs-nuget-package-restore-off-stderr.txt
  31. 1 0
      Tests/RunCMake/VsNugetPackageRestore/vs-nuget-package-restore-wrong-result.txt
  32. 1 0
      Tests/RunCMake/VsNugetPackageRestore/vs-nuget-package-restore-wrong-stderr.txt

+ 1 - 0
Help/manual/cmake-variables.7.rst

@@ -119,6 +119,7 @@ Variables that Provide Information
    /variable/CMAKE_VS_DEVENV_COMMAND
    /variable/CMAKE_VS_MSBUILD_COMMAND
    /variable/CMAKE_VS_NsightTegra_VERSION
+   /variable/CMAKE_VS_NUGET_PACKAGE_RESTORE
    /variable/CMAKE_VS_PLATFORM_NAME
    /variable/CMAKE_VS_PLATFORM_NAME_DEFAULT
    /variable/CMAKE_VS_PLATFORM_TOOLSET

+ 11 - 0
Help/manual/cmake.1.rst

@@ -463,6 +463,17 @@ following options:
   Build target ``clean`` first, then build.
   (To clean only, use ``--target clean``.)
 
+``--resolve-package-references=<on|off|only>``
+  .. versionadded:: 3.23
+
+  Resolve remote package references (e.g. NuGet packages) before build.
+  When set to ``on`` (default), packages will be restored before building a
+  target. When set to ``only``, the packages will be restored, but no build
+  will be performed. When set to ``off``, no packages will be restored.
+
+  If the target does not define any package references, this option does
+  nothing.
+
 ``--use-stderr``
   Ignored.  Behavior is default in CMake >= 3.0.
 

+ 10 - 0
Help/release/dev/vs-package-restore.rst

@@ -0,0 +1,10 @@
+vs-package-restore
+------------------
+
+* Targets with :prop_tgt:`VS_PACKAGE_REFERENCES` will now automatically attempt
+  to restore the package references from NuGet. The cache variable
+  :variable:`CMAKE_VS_NUGET_PACKAGE_RESTORE` was added to toggle automatic
+  package restore off.
+
+* :manual:`cmake(1)` gained the ``--resolve-package-references=<on|off|only>``
+  command-line option to control automatic package restoration.

+ 22 - 0
Help/variable/CMAKE_VS_NUGET_PACKAGE_RESTORE.rst

@@ -0,0 +1,22 @@
+CMAKE_VS_NUGET_PACKAGE_RESTORE
+------------------------------
+
+.. versionadded:: 3.23
+
+When using a Visual Studio generator, this cache variable controls
+if msbuild should automatically attempt to restore NuGet packages
+prior to a build. NuGet packages can be defined using the
+:prop_tgt:`VS_PACKAGE_REFERENCES` property on a target. If no
+package references are defined, this setting will do nothing.
+
+The command line option ``--resolve-package-references`` can be used
+alternatively to control the resolve behavior globally. This option
+will take precedence over the cache variable.
+
+Targets that use the :prop_tgt:`DOTNET_SDK` are required to run a
+restore before building. Disabling this option may cause the build
+to fail in such projects.
+
+This setting is stored as a cache entry. Default value is ``ON``.
+
+See also the :prop_tgt:`VS_PACKAGE_REFERENCES` property.

+ 2 - 1
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,

+ 24 - 1
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;
 };

+ 20 - 0
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)) {

+ 3 - 0
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

+ 1 - 1
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,

+ 69 - 0
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();

+ 2 - 0
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);

+ 35 - 5
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);
+      }
+    }
+  }
+}

+ 1 - 0
Source/cmVisualStudio10TargetGenerator.h

@@ -198,6 +198,7 @@ private:
   std::string GetCSharpSourceLink(cmSourceFile const* source);
 
   void WriteStdOutEncodingUtf8(Elem& e1);
+  void UpdateCache();
 
 private:
   friend class cmVS10GeneratorOptions;

+ 23 - 0
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);

+ 1 - 0
Tests/RunCMake/CMakeLists.txt

@@ -618,6 +618,7 @@ endif()
 
 if(CMAKE_GENERATOR MATCHES "^Visual Studio (1[6-9]|[2-9][0-9])")
   add_RunCMake_test(VsDotnetSdk)
+  add_RunCMake_test(VsNugetPackageRestore)
 endif()
 
 if(XCODE_VERSION)

+ 1 - 0
Tests/RunCMake/CommandLine/build-invalid-package-resolve-arg-result.txt

@@ -0,0 +1 @@
+1

+ 1 - 0
Tests/RunCMake/CommandLine/build-invalid-package-resolve-arg-stderr.txt

@@ -0,0 +1 @@
+^Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\]

+ 3 - 0
Tests/RunCMake/VsNugetPackageRestore/CMakeLists.txt

@@ -0,0 +1,3 @@
+cmake_minimum_required(VERSION 3.22)
+project(${RunCMake_TEST} NONE)
+include(${RunCMake_TEST}.cmake)

+ 17 - 0
Tests/RunCMake/VsNugetPackageRestore/Package/CMakeLists.txt

@@ -0,0 +1,17 @@
+cmake_minimum_required(VERSION 3.12)
+
+project(NuGetTestProject VERSION 1.0.0 LANGUAGES CSharp)
+
+add_library(NuGetPackage SHARED "Library.cs")
+set_target_properties(NuGetPackage PROPERTIES
+  VS_DOTNET_TARGET_FRAMEWORK_VERSION "v4.7.2"
+  VS_DOTNET_REFERENCES "System")
+install(TARGETS NuGetPackage)
+
+set(CPACK_GENERATOR "NuGet")
+set(CPACK_PACKAGE_NAME "NuGetTestProject")
+set(CPACK_PACKAGE_VERSION "${PROJECT_VERSION}")
+set(CPACK_PACKAGE_DESCRIPTION "Package to test automatic NuGet package restore.")
+set(CPACK_PACKAGE_VENDOR "CMake.org")
+
+include(CPack)

+ 9 - 0
Tests/RunCMake/VsNugetPackageRestore/Package/Library.cs

@@ -0,0 +1,9 @@
+using System;
+
+namespace CMake
+{
+    public class NuGetTest
+    {
+        public static int GetNumber() => 42;
+    }
+}

+ 14 - 0
Tests/RunCMake/VsNugetPackageRestore/Program.cs

@@ -0,0 +1,14 @@
+using System;
+using CMake;
+
+namespace Test
+{
+    public class Program
+    {
+        public static void Main(string[] args)
+        {
+            Console.WriteLine(NuGetTest.GetNumber());
+            Console.ReadKey();
+        }
+    }
+}

+ 5 - 0
Tests/RunCMake/VsNugetPackageRestore/Repository/NuGetTestProject/1.0.0/.nupkg.metadata

@@ -0,0 +1,5 @@
+{
+  "version": 2,
+  "contentHash": "2sG1Ws4da8r6qj7rUAZ1GaOjkELonH0X+vR9yfDwgg+QxG0cpRIfGqEXKAkGT+UCwU24ogJcm8IA9dXv5zmLXg==",
+  "source": null
+}

BIN
Tests/RunCMake/VsNugetPackageRestore/Repository/NuGetTestProject/1.0.0/nugettestproject.1.0.0.nupkg


+ 1 - 0
Tests/RunCMake/VsNugetPackageRestore/Repository/NuGetTestProject/1.0.0/nugettestproject.1.0.0.nupkg.sha512

@@ -0,0 +1 @@
+2sG1Ws4da8r6qj7rUAZ1GaOjkELonH0X+vR9yfDwgg+QxG0cpRIfGqEXKAkGT+UCwU24ogJcm8IA9dXv5zmLXg==

+ 11 - 0
Tests/RunCMake/VsNugetPackageRestore/Repository/NuGetTestProject/1.0.0/nugettestproject.nuspec

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
+  <metadata>
+    <id>NuGetTestProject</id>
+    <version>1.0.0</version>
+    <authors>CMake.org</authors>
+    <requireLicenseAcceptance>false</requireLicenseAcceptance>
+    <description>Package to test automatic NuGet package restore.</description>
+    <summary>NuGetTestProject built using CMake</summary>
+  </metadata>
+</package>

+ 12 - 0
Tests/RunCMake/VsNugetPackageRestore/RunCMakeTest.cmake

@@ -0,0 +1,12 @@
+cmake_policy(SET CMP0053 NEW)
+include(RunCMake)
+
+set(RunCMake_TEST_BINARY_DIR ${RunCMake_BINARY_DIR}/VsNugetPackageRestore)
+run_cmake(VsNugetPackageRestore)
+
+set(RunCMake_TEST_NO_CLEAN 1)
+run_cmake_command(vs-nuget-package-restore-off ${CMAKE_COMMAND} --build ${RunCMake_TEST_BINARY_DIR} --resolve-package-references=off)
+run_cmake_command(vs-nuget-package-restore-only ${CMAKE_COMMAND} --build ${RunCMake_TEST_BINARY_DIR} --resolve-package-references=only)
+run_cmake_command(vs-nuget-package-restore-on ${CMAKE_COMMAND} --build ${RunCMake_TEST_BINARY_DIR} --resolve-package-references=on)
+run_cmake_command(vs-nuget-package-restore-wrong ${CMAKE_COMMAND} --build ${RunCMake_TEST_BINARY_DIR} --resolve-package-references=wrong)
+set(RunCMake_TEST_NO_CLEAN 0)

+ 9 - 0
Tests/RunCMake/VsNugetPackageRestore/VsNugetPackageRestore.cmake

@@ -0,0 +1,9 @@
+enable_language(CSharp)
+
+add_executable(TestProgram "Program.cs")
+configure_file("nuget.config.in" "nuget.config")
+set_target_properties(TestProgram PROPERTIES
+  VS_DOTNET_TARGET_FRAMEWORK_VERSION "v4.7.2"
+  VS_DOTNET_REFERENCES "System"
+  VS_PACKAGE_REFERENCES "NuGetTestProject_1.0.0"
+)

+ 7 - 0
Tests/RunCMake/VsNugetPackageRestore/nuget.config.in

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+  <packageSources>
+    <clear />
+    <add key="local" value="@CMAKE_CURRENT_SOURCE_DIR@/Repository/" />
+  </packageSources>
+</configuration>

+ 1 - 0
Tests/RunCMake/VsNugetPackageRestore/vs-nuget-package-restore-off-result.txt

@@ -0,0 +1 @@
+1

+ 1 - 0
Tests/RunCMake/VsNugetPackageRestore/vs-nuget-package-restore-off-stderr.txt

@@ -0,0 +1 @@
+^$

+ 1 - 0
Tests/RunCMake/VsNugetPackageRestore/vs-nuget-package-restore-wrong-result.txt

@@ -0,0 +1 @@
+1

+ 1 - 0
Tests/RunCMake/VsNugetPackageRestore/vs-nuget-package-restore-wrong-stderr.txt

@@ -0,0 +1 @@
+^Usage: cmake --build <dir> +\[options\] \[-- \[native-options\]\]