for vs2017 and up nuget is now handled by msbuild instead of premake

via the new PackageReference nodes.

The upsides here are
1) the MS package downloading and validation is much faster than the premake version
2) since the config is in the project file instead of packages.config which means
   multiple nuget projects can sit in the same folder.

Fixed nuget code to only use PackageReference on .net projects,
and moved validation code into the module where it belongs.
This commit is contained in:
R. Blaine Whittle 2017-09-21 15:40:25 -07:00 committed by Tom van Dijck
parent 3cdaed431e
commit 116b1c2c80
9 changed files with 626 additions and 495 deletions

View File

@ -74,6 +74,7 @@ return {
"vc2010/test_manifest.lua",
"vc2010/test_nmake_props.lua",
"vc2010/test_nuget_packages_config.lua",
"vc2010/test_nuget_package_references.lua",
"vc2010/test_output_props.lua",
"vc2010/test_platform_toolset.lua",
"vc2010/test_project_configs.lua",

View File

@ -0,0 +1,71 @@
--
-- tests/actions/vstudio/vs2010/test_nuget_package_references.lua
-- Validate generation of NuGet packages references for Visual Studio 2017 and newer.
-- Copyright (c) 2012-2015 Jason Perkins and the Premake project
--
local p = premake
local suite = test.declare("vstudio_vs2010_nuget_package_references")
local cs2005 = p.vstudio.cs2005
local nuget2010 = p.vstudio.nuget2010
local dotnetbase = p.vstudio.dotnetbase
--
-- Setup and teardown
--
local wks, prj
function suite.setup()
p.action.set("vs2017")
wks = test.createWorkspace()
configurations {'Debug','Release'}
language "C#"
end
local function prepare(platform)
prj = test.getproject(wks, 1)
dotnetbase.packageReferences(prj)
end
--
-- Should not output anything if no packages have been set.
--
function suite.noOutputIfNoPackages()
prepare()
test.isemptycapture()
end
--
-- Writes the packages.config file properly.
--
function suite.structureIsCorrect()
nuget { "Newtonsoft.Json:10.0.2", "NUnit:3.6.1", "SSH.NET:2016.0.0" }
prepare()
test.capture [[
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="10.0.2"/>
<PackageReference Include="NUnit" Version="3.6.1"/>
<PackageReference Include="SSH.NET" Version="2016.0.0"/>
</ItemGroup>
]]
end
function suite.configStructureIsCorrect()
nuget { "NUnit:3.6.1", "SSH.NET:2016.0.0" }
filter { "configurations:Debug" }
nuget { "Newtonsoft.Json:10.0.2" }
prepare()
test.capture [[
<ItemGroup>
<PackageReference Include="NUnit" Version="3.6.1"/>
<PackageReference Include="SSH.NET" Version="2016.0.0"/>
<PackageReference Include="Newtonsoft.Json" Version="10.0.2" Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "/>
</ItemGroup>
]]
end

File diff suppressed because it is too large Load Diff

View File

@ -85,16 +85,18 @@
end
end
-- Skip generation of empty packages.config files
local packages = p.capture(function() vstudio.nuget2010.generatePackagesConfig(prj) end)
if #packages > 0 then
p.generate(prj, "packages.config", function() p.outln(packages) end)
end
if not vstudio.nuget2010.supportsPackageReferences(prj) then
-- Skip generation of empty packages.config files
local packages = p.capture(function() vstudio.nuget2010.generatePackagesConfig(prj) end)
if #packages > 0 then
p.generate(prj, "packages.config", function() p.outln(packages) end)
end
-- Skip generation of empty NuGet.Config files
local config = p.capture(function() vstudio.nuget2010.generateNuGetConfig(prj) end)
if #config > 0 then
p.generate(prj, "NuGet.Config", function() p.outln(config) end)
-- Skip generation of empty NuGet.Config files
local config = p.capture(function() vstudio.nuget2010.generateNuGetConfig(prj) end)
if #config > 0 then
p.generate(prj, "NuGet.Config", function() p.outln(config) end)
end
end
end

View File

@ -38,6 +38,10 @@
end
end
function nuget2010.supportsPackageReferences(prj)
return _ACTION >= "vs2017" and p.project.isdotnet(prj)
end
--
-- Given a package string, returns a table containing "verbatimVersion",
@ -368,3 +372,66 @@
p.pop('</packageSources>')
p.pop('</configuration>')
end
--
-- nuget workspace validation
--
function nuget2010.uniqueProjectLocationsWithNuGet(wks)
local locations = {}
for prj in p.workspace.eachproject(wks) do
if not nuget2010.supportsPackageReferences(prj) then
local function fail()
p.error("projects '%s' and '%s' cannot have the same location when using NuGet with different packages (packages.config conflict)", locations[prj.location].name, prj.name)
end
if locations[prj.location] and #locations[prj.location].nuget > 0 and #prj.nuget > 0 then
if #locations[prj.location].nuget ~= #prj.nuget then
fail()
end
for i, package in ipairs(locations[prj.location].nuget) do
if prj.nuget[i] ~= package then
fail()
end
end
end
locations[prj.location] = prj
end
end
end
p.override(p.validation.elements, "workspace", function (oldfn, wks)
local t = oldfn(wks)
table.insert(t, nuget2010.uniqueProjectLocationsWithNuGet)
return t
end)
--
-- nuget project validation
--
function nuget2010.NuGetHasHTTP(prj)
if not http and #prj.nuget > 0 and not nuget2010.supportsPackageReferences(prj) then
p.error("Premake was compiled with --no-curl, but Curl is required for NuGet support (project '%s' is referencing NuGet packages)", prj.name)
end
end
function nuget2010.NuGetPackageStrings(prj)
for _, package in ipairs(prj.nuget) do
local components = package:explode(":")
if #components ~= 2 or #components[1] == 0 or #components[2] == 0 then
p.error("NuGet package '%s' in project '%s' is invalid - please give packages in the format 'id:version', e.g. 'NUnit:3.6.1'", package, prj.name)
end
end
end
p.override(p.validation.elements, "project", function (oldfn, prj)
local t = oldfn(prj)
table.insert(t, nuget2010.NuGetHasHTTP)
table.insert(t, nuget2010.NuGetPackageStrings)
return t
end)

View File

@ -1711,9 +1711,11 @@
end
function m.importNuGetTargets(prj)
for i = 1, #prj.nuget do
local targetsFile = nuGetTargetsFile(prj, prj.nuget[i])
p.x('<Import Project="%s" Condition="Exists(\'%s\')" />', targetsFile, targetsFile)
if not vstudio.nuget2010.supportsPackageReferences(prj) then
for i = 1, #prj.nuget do
local targetsFile = nuGetTargetsFile(prj, prj.nuget[i])
p.x('<Import Project="%s" Condition="Exists(\'%s\')" />', targetsFile, targetsFile)
end
end
end

View File

@ -847,7 +847,7 @@
api.register {
name = "nuget",
scope = "project",
scope = "config",
kind = "list:string",
tokens = true,
}

View File

@ -667,7 +667,7 @@
-- packages.config file to the project. Is there a better place to
-- do this?
if #prj.nuget > 0 then
if #prj.nuget > 0 and (_ACTION < "vs2017" or p.project.iscpp(prj)) then
addFile("packages.config")
end
end

View File

@ -38,7 +38,6 @@
return {
m.workspaceHasConfigs,
m.uniqueProjectIds,
m.uniqueProjectLocationsWithNuGet,
}
end
@ -60,8 +59,6 @@
m.actionSupportsKind,
m.projectRulesExist,
m.projectValuesInScope,
m.NuGetHasHTTP,
m.NuGetPackageStrings,
}
end
@ -224,24 +221,6 @@
end
function m.NuGetHasHTTP(prj)
if not http and #prj.nuget > 0 then
p.error("Premake was compiled with --no-curl, but Curl is required for NuGet support (project '%s' is referencing NuGet packages)", prj.name)
end
end
function m.NuGetPackageStrings(prj)
for _, package in ipairs(prj.nuget) do
local components = package:explode(":")
if #components ~= 2 or #components[1] == 0 or #components[2] == 0 then
p.error("NuGet package '%s' in project '%s' is invalid - please give packages in the format 'id:version', e.g. 'NUnit:3.6.1'", package, prj.name)
end
end
end
function m.uniqueProjectIds(wks)
local uuids = {}
for prj in p.workspace.eachproject(wks) do
@ -253,29 +232,6 @@
end
function m.uniqueProjectLocationsWithNuGet(wks)
local locations = {}
for prj in p.workspace.eachproject(wks) do
local function fail()
p.error("projects '%s' and '%s' cannot have the same location when using NuGet with different packages (packages.config conflict)", locations[prj.location].name, prj.name)
end
if locations[prj.location] and #locations[prj.location].nuget > 0 and #prj.nuget > 0 then
if #locations[prj.location].nuget ~= #prj.nuget then
fail()
end
for i, package in ipairs(locations[prj.location].nuget) do
if prj.nuget[i] ~= package then
fail()
end
end
end
locations[prj.location] = prj
end
end
function m.workspaceHasConfigs(wks)
if not wks.configurations or #wks.configurations == 0 then
p.error("workspace '%s' does not contain any configurations", wks.name)