diff --git a/src/_manifest.lua b/src/_manifest.lua
index f10130cb..986b6f95 100644
--- a/src/_manifest.lua
+++ b/src/_manifest.lua
@@ -76,6 +76,7 @@
"actions/vstudio/vs2005_csproj.lua",
"actions/vstudio/vs2005_csproj_user.lua",
"actions/vstudio/vs2010.lua",
+ "actions/vstudio/vs2010_nuget.lua",
"actions/vstudio/vs2010_vcxproj.lua",
"actions/vstudio/vs2010_vcxproj_user.lua",
"actions/vstudio/vs2010_vcxproj_filters.lua",
diff --git a/src/_premake_init.lua b/src/_premake_init.lua
index 92f109d1..9e90d532 100644
--- a/src/_premake_init.lua
+++ b/src/_premake_init.lua
@@ -748,6 +748,13 @@
}
}
+ api.register {
+ name = "nuget",
+ scope = "project",
+ kind = "list:string",
+ tokens = true,
+ }
+
api.register {
name = "objdir",
scope = "config",
diff --git a/src/actions/vstudio/_vstudio.lua b/src/actions/vstudio/_vstudio.lua
index cd60b28a..9c246829 100644
--- a/src/actions/vstudio/_vstudio.lua
+++ b/src/actions/vstudio/_vstudio.lua
@@ -12,6 +12,23 @@
local config = p.config
+--
+-- All valid .NET Framework versions, from oldest to newest.
+--
+
+ vstudio.frameworkVersions =
+ {
+ "1.0",
+ "1.1",
+ "2.0",
+ "3.0",
+ "3.5",
+ "4.0",
+ "4.5",
+ "4.6",
+ }
+
+
--
-- Mapping tables from Premake systems and architectures to Visual Studio
-- identifiers. Broken out as tables so new values can be pushed in by
diff --git a/src/actions/vstudio/vs2005.lua b/src/actions/vstudio/vs2005.lua
index 54d66614..b75227fb 100644
--- a/src/actions/vstudio/vs2005.lua
+++ b/src/actions/vstudio/vs2005.lua
@@ -21,6 +21,20 @@
p.escaper(vs2005.esc)
premake.generate(wks, ".sln", vstudio.sln2005.generate)
+
+ if _ACTION >= "vs2010" then
+ -- Skip generation of empty NuGet packages.config files
+ if p.workspace.hasProject(wks, function(prj) return #prj.nuget > 0 end) then
+ premake.generate(
+ {
+ location = path.join(wks.location, "packages.config"),
+ workspace = wks
+ },
+ nil,
+ vstudio.nuget2010.generatePackagesConfig
+ )
+ end
+ end
end
diff --git a/src/actions/vstudio/vs2005_csproj.lua b/src/actions/vstudio/vs2005_csproj.lua
index 09aaedb1..f9710540 100644
--- a/src/actions/vstudio/vs2005_csproj.lua
+++ b/src/actions/vstudio/vs2005_csproj.lua
@@ -29,7 +29,7 @@
"projectProperties",
"configurations",
"applicationIcon",
- "assemblyReferences",
+ "references",
}
function cs2005.generate(prj)
@@ -284,13 +284,29 @@
end
+--
+-- Write out the references item group.
+--
+
+ cs2005.elements.references = function(prj)
+ return {
+ cs2005.assemblyReferences,
+ cs2005.nuGetReferences,
+ }
+ end
+
+ function cs2005.references(prj)
+ _p(1,'')
+ p.callArray(cs2005.elements.references, prj)
+ _p(1,'')
+ end
+
+
--
-- Write the list of assembly (system, or non-sibling) references.
--
function cs2005.assemblyReferences(prj)
- _p(1,'')
-
-- C# doesn't support per-configuration links (does it?) so just use
-- the settings from the first available config instead
local cfg = project.getfirstconfig(prj)
@@ -314,8 +330,44 @@
_x(2,'', name)
end
end)
+ end
- _p(1,'')
+
+--
+-- Write the list of NuGet references.
+--
+
+ function cs2005.nuGetReferences(prj)
+ if _ACTION >= "vs2010" then
+ for i = 1, #prj.nuget do
+ local package = prj.nuget[i]
+ _x(2, '', vstudio.nuget2010.packageId(package))
+
+ -- We need to write HintPaths for all supported framework
+ -- versions. The last HintPath will override any previous
+ -- HintPaths (if the condition is met that is).
+
+ for _, frameworkVersion in ipairs(cs2005.identifyFrameworkVersions(prj)) do
+ local assembly = vstudio.path(
+ prj,
+ p.filename(
+ prj.solution,
+ string.format(
+ "packages\\%s\\lib\\%s\\%s.dll",
+ vstudio.nuget2010.packageName(package),
+ cs2005.formatNuGetFrameworkVersion(frameworkVersion),
+ vstudio.nuget2010.packageId(package)
+ )
+ )
+ )
+
+ _x(3, '%s', assembly, assembly)
+ end
+
+ _p(3, 'True')
+ _p(2, '')
+ end
+ end
end
@@ -401,6 +453,41 @@
return string.format('Condition="\'$(Configuration)|$(Platform)\'==\'%s\'"', premake.esc(vstudio.projectConfig(cfg)))
end
+
+--
+-- Build and return a list of all .NET Framework versions up to and including
+-- the project's framework version.
+--
+
+ function cs2005.identifyFrameworkVersions(prj)
+ local frameworks = {}
+
+ local cfg = p.project.getfirstconfig(prj)
+ local action = premake.action.current()
+ local targetFramework = cfg.dotnetframework or action.vstudio.targetFramework
+
+ for _, frameworkVersion in ipairs(vstudio.frameworkVersions) do
+ if frameworkVersion == targetFramework then
+ break
+ end
+
+ table.insert(frameworks, frameworkVersion)
+ end
+
+ table.insert(frameworks, targetFramework)
+
+ return frameworks
+ end
+
+
+--
+-- When given a .NET Framework version, returns it formatted for NuGet.
+--
+
+ function cs2005.formatNuGetFrameworkVersion(framework)
+ return "net" .. framework:gsub("%.", "")
+ end
+
---------------------------------------------------------------------------
--
-- Handlers for individual project elements
diff --git a/src/actions/vstudio/vs2010_nuget.lua b/src/actions/vstudio/vs2010_nuget.lua
new file mode 100644
index 00000000..67a4b538
--- /dev/null
+++ b/src/actions/vstudio/vs2010_nuget.lua
@@ -0,0 +1,83 @@
+--
+-- vs2010_nuget.lua
+-- Generate a NuGet packages.config file.
+-- Copyright (c) 2016 Jason Perkins and the Premake project
+--
+
+ premake.vstudio.nuget2010 = {}
+
+ local p = premake
+ local vstudio = p.vstudio
+ local nuget2010 = p.vstudio.nuget2010
+
+
+--
+-- These functions take the package string as an argument and give you
+-- information about it.
+--
+
+ function nuget2010.packageName(package)
+ return package:gsub(":", ".")
+ end
+
+ function nuget2010.packageId(package)
+ return package:sub(0, package:find(":") - 1)
+ end
+
+ function nuget2010.packageVersion(package)
+ return package:sub(package:find(":") + 1, -1)
+ end
+
+ local function packageProject(wks, package)
+ for prj in p.workspace.eachproject(wks) do
+ for i = 1, #prj.nuget do
+ local projectPackage = prj.nuget[i]
+
+ if projectPackage == package then
+ return prj
+ end
+ end
+ end
+ end
+
+ function nuget2010.packageFramework(wks, package)
+ local prj = packageProject(wks, package)
+
+ if p.project.iscpp(prj) then
+ return "native"
+ elseif p.project.isdotnet(prj) then
+ local cfg = p.project.getfirstconfig(prj)
+ local action = premake.action.current()
+ local framework = cfg.dotnetframework or action.vstudio.targetFramework
+ return cs2005.formatNuGetFrameworkVersion(framework)
+ end
+ end
+
+
+--
+-- Generates the packages.config file.
+--
+
+ function nuget2010.generatePackagesConfig(obj)
+ local wks = obj.workspace
+
+ local packages = {}
+ for prj in p.workspace.eachproject(wks) do
+ for i = 1, #prj.nuget do
+ local package = prj.nuget[i]
+
+ if not packages[package] then
+ packages[package] = true
+ end
+ end
+ end
+
+ p.w('')
+ p.push('')
+
+ for package in pairs(packages) do
+ p.x('', nuget2010.packageId(package), nuget2010.packageVersion(package), nuget2010.packageFramework(wks, package))
+ end
+
+ p.pop('')
+ end
diff --git a/src/actions/vstudio/vs2010_vcxproj.lua b/src/actions/vstudio/vs2010_vcxproj.lua
index 52466300..c4d42a50 100644
--- a/src/actions/vstudio/vs2010_vcxproj.lua
+++ b/src/actions/vstudio/vs2010_vcxproj.lua
@@ -46,6 +46,7 @@
m.projectReferences,
m.importLanguageTargets,
m.importExtensionTargets,
+ m.ensureNuGetPackageBuildImports,
}
end
@@ -1385,6 +1386,7 @@
return {
m.importGroupTargets,
m.importRuleTargets,
+ m.importNuGetTargets,
m.importBuildCustomizationsTargets
}
end
@@ -1412,6 +1414,17 @@
end
end
+ local function nuGetTargetsFile(prj, package)
+ return p.vstudio.path(prj, p.filename(prj.solution, string.format("packages\\%s\\build\\native\\%s.targets", vstudio.nuget2010.packageName(package), vstudio.nuget2010.packageId(package))))
+ end
+
+ function m.importNuGetTargets(prj)
+ for i = 1, #prj.nuget do
+ local targetsFile = nuGetTargetsFile(prj, prj.nuget[i])
+ p.x('', targetsFile, targetsFile)
+ end
+ end
+
function m.importBuildCustomizationsTargets(prj)
for i, build in ipairs(prj.buildcustomizations) do
p.w('', path.translate(build))
@@ -1420,6 +1433,21 @@
+ function m.ensureNuGetPackageBuildImports(prj)
+ p.push('')
+ p.push('')
+ p.x('This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.')
+ p.pop('')
+
+ for i = 1, #prj.nuget do
+ local targetsFile = nuGetTargetsFile(prj, prj.nuget[i])
+ p.x('', targetsFile, targetsFile)
+ end
+ p.pop('')
+ end
+
+
+
function m.importDefaultProps(prj)
p.w('')
end
diff --git a/tests/_tests.lua b/tests/_tests.lua
index a6781b84..4d778e26 100644
--- a/tests/_tests.lua
+++ b/tests/_tests.lua
@@ -82,6 +82,7 @@ return {
"actions/vstudio/sln2005/test_projects.lua",
"actions/vstudio/sln2005/test_platforms.lua",
"actions/vstudio/sln2005/test_sections.lua",
+ "actions/vstudio/sln2005/test_nuget_packages_config.lua",
-- Visual Studio 2002-2008 C/C++ projects
"actions/vstudio/vc200x/test_assembly_refs.lua",
@@ -134,6 +135,7 @@ return {
"actions/vstudio/vc2010/test_target_machine.lua",
"actions/vstudio/vc2010/test_user_file.lua",
"actions/vstudio/vc2010/test_vectorextensions.lua",
+ "actions/vstudio/vc2010/test_ensure_nuget_imports.lua",
-- Makefile tests
"actions/make/test_make_escaping.lua",
diff --git a/tests/actions/vstudio/cs2005/test_assembly_refs.lua b/tests/actions/vstudio/cs2005/test_assembly_refs.lua
index 87bf2d0f..e8ebdbce 100644
--- a/tests/actions/vstudio/cs2005/test_assembly_refs.lua
+++ b/tests/actions/vstudio/cs2005/test_assembly_refs.lua
@@ -16,14 +16,14 @@
local wks, prj
function suite.setup()
- premake.action.set("vs2008")
+ premake.action.set("vs2010")
wks = test.createWorkspace()
language "C#"
end
local function prepare(platform)
prj = test.getproject(wks, 1)
- cs2005.assemblyReferences(prj)
+ cs2005.references(prj)
end
@@ -142,3 +142,50 @@
]]
end
+
+--
+-- NuGet packages should get references.
+--
+
+ function suite.nuGetPackages()
+ dotnetframework "4.5"
+ nuget { "Newtonsoft.Json:7.0.1" }
+ prepare()
+ test.capture [[
+
+
+ packages\Newtonsoft.Json.7.0.1\lib\net10\Newtonsoft.Json.dll
+ packages\Newtonsoft.Json.7.0.1\lib\net11\Newtonsoft.Json.dll
+ packages\Newtonsoft.Json.7.0.1\lib\net20\Newtonsoft.Json.dll
+ packages\Newtonsoft.Json.7.0.1\lib\net30\Newtonsoft.Json.dll
+ packages\Newtonsoft.Json.7.0.1\lib\net35\Newtonsoft.Json.dll
+ packages\Newtonsoft.Json.7.0.1\lib\net40\Newtonsoft.Json.dll
+ packages\Newtonsoft.Json.7.0.1\lib\net45\Newtonsoft.Json.dll
+ True
+
+
+ ]]
+ end
+
+
+--
+-- NuGet packages shouldn't get HintPaths for .NET Framework
+-- versions that the project doesn't support.
+--
+
+ function suite.nuGetPackages_olderNET()
+ dotnetframework "3.0"
+ nuget { "Newtonsoft.Json:7.0.1" }
+ prepare()
+ test.capture [[
+
+
+ packages\Newtonsoft.Json.7.0.1\lib\net10\Newtonsoft.Json.dll
+ packages\Newtonsoft.Json.7.0.1\lib\net11\Newtonsoft.Json.dll
+ packages\Newtonsoft.Json.7.0.1\lib\net20\Newtonsoft.Json.dll
+ packages\Newtonsoft.Json.7.0.1\lib\net30\Newtonsoft.Json.dll
+ True
+
+
+ ]]
+ end
diff --git a/tests/actions/vstudio/sln2005/test_nuget_packages_config.lua b/tests/actions/vstudio/sln2005/test_nuget_packages_config.lua
new file mode 100644
index 00000000..f383efa9
--- /dev/null
+++ b/tests/actions/vstudio/sln2005/test_nuget_packages_config.lua
@@ -0,0 +1,43 @@
+--
+-- tests/actions/vstudio/sln2005/test_nuget_packages_config.lua
+-- Validate generation of NuGet packages.config file for Visual Studio 2010 and newer.
+-- Copyright (c) 2016 Jason Perkins and the Premake project
+--
+
+ local suite = test.declare("vstudio_sln2005_nuget_packages_config")
+ local nuget2010 = premake.vstudio.nuget2010
+
+
+--
+-- Setup
+--
+
+ local wks
+
+ function suite.setup()
+ premake.action.set("vs2010")
+ wks = test.createWorkspace()
+ end
+
+ local function prepare()
+ local prj = premake.solution.getproject(wks, 1)
+ nuget2010.generatePackagesConfig({ workspace = wks })
+ end
+
+
+--
+-- Writes the packages.config file properly.
+--
+
+ function suite.structureIsCorrect()
+ nuget { "boost:1.59.0-b1", "sdl2.v140:2.0.3", "sdl2.v140.redist:2.0.3" }
+ prepare()
+ test.capture [[
+
+
+
+
+
+
+ ]]
+ end
diff --git a/tests/actions/vstudio/vc2010/test_ensure_nuget_imports.lua b/tests/actions/vstudio/vc2010/test_ensure_nuget_imports.lua
new file mode 100644
index 00000000..2c747fec
--- /dev/null
+++ b/tests/actions/vstudio/vc2010/test_ensure_nuget_imports.lua
@@ -0,0 +1,46 @@
+--
+-- tests/actions/vstudio/vc2010/test_ensure_nuget_imports.lua
+-- Check the EnsureNuGetPackageBuildImports block of a VS 2010 project.
+-- Copyright (c) 2016 Jason Perkins and the Premake project
+--
+
+ local suite = test.declare("vs2010_ensure_nuget_imports")
+ local vc2010 = premake.vstudio.vc2010
+ local project = premake.project
+
+
+--
+-- Setup
+--
+
+ local wks
+
+ function suite.setup()
+ premake.action.set("vs2010")
+ wks = test.createWorkspace()
+ end
+
+ local function prepare()
+ local prj = premake.solution.getproject(wks, 1)
+ vc2010.ensureNuGetPackageBuildImports(prj)
+ end
+
+
+--
+-- Writes the pre-build check that makes sure that all packages are installed.
+--
+
+ function suite.structureIsCorrect()
+ nuget { "boost:1.59.0-b1", "sdl2.v140:2.0.3", "sdl2.v140.redist:2.0.3" }
+ prepare()
+ test.capture [[
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
+ ]]
+ end
diff --git a/tests/actions/vstudio/vc2010/test_extension_targets.lua b/tests/actions/vstudio/vc2010/test_extension_targets.lua
index 40d1720a..5575a2b5 100644
--- a/tests/actions/vstudio/vc2010/test_extension_targets.lua
+++ b/tests/actions/vstudio/vc2010/test_extension_targets.lua
@@ -58,6 +58,23 @@
end
+--
+-- Writes entries for NuGet packages.
+--
+
+ function suite.addsImport_onEachNuGetPackage()
+ nuget { "boost:1.59.0-b1", "sdl2.v140:2.0.3", "sdl2.v140.redist:2.0.3" }
+ prepare()
+ test.capture [[
+
+
+
+
+
+ ]]
+ end
+
+
--
-- Rule files use a project relative path.
--