diff --git a/CHANGES.txt b/CHANGES.txt
index db0c0e7e..fadc1e9d 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -13,3 +13,4 @@ Since 5.0-alpha1:
* Action arguments (_ARGS) are now keyed by both index and value
* Configuration baking and validation now skipped for execute only actions
* os.findlib() now accepts paths to search as argument
+* Visual Studio .user files are now only generated if not empty
diff --git a/src/actions/vstudio/vs2005.lua b/src/actions/vstudio/vs2005.lua
index 59e7a620..ed314047 100644
--- a/src/actions/vstudio/vs2005.lua
+++ b/src/actions/vstudio/vs2005.lua
@@ -1,7 +1,7 @@
--
-- actions/vstudio/vs2005.lua
-- Add support for the Visual Studio 2005 project formats.
--- Copyright (c) 2008-2014 Jason Perkins and the Premake project
+-- Copyright (c) 2008-2015 Jason Perkins and the Premake project
--
premake.vstudio.vs2005 = {}
@@ -31,10 +31,22 @@
if premake.project.isdotnet(prj) then
premake.generate(prj, ".csproj", vstudio.cs2005.generate)
- premake.generate(prj, ".csproj.user", vstudio.cs2005.generate_user)
+
+ -- Skip generation of empty user files
+ local user = p.capture(function() vstudio.cs2005.generateUser(prj) end)
+ if #user > 0 then
+ p.generate(prj, ".csproj.user", function() p.outln(user) end)
+ end
+
elseif premake.project.iscpp(prj) then
premake.generate(prj, ".vcproj", vstudio.vc200x.generate)
- premake.generate(prj, ".vcproj.user", vstudio.vc200x.generate_user)
+
+ -- Skip generation of empty user files
+ local user = p.capture(function() vstudio.vc200x.generateUser(prj) end)
+ if #user > 0 then
+ p.generate(prj, ".vcproj.user", function() p.outln(user) end)
+ end
+
end
end
diff --git a/src/actions/vstudio/vs2005_csproj_user.lua b/src/actions/vstudio/vs2005_csproj_user.lua
index 3f92e1d6..f0941891 100644
--- a/src/actions/vstudio/vs2005_csproj_user.lua
+++ b/src/actions/vstudio/vs2005_csproj_user.lua
@@ -1,52 +1,90 @@
--
-- vs2005_csproj_user.lua
-- Generate a Visual Studio 2005/2008 C# .user file.
--- Copyright (c) 2009-2014 Jason Perkins and the Premake project
+-- Copyright (c) 2009-2015 Jason Perkins and the Premake project
--
local p = premake
- local cs2005 = p.vstudio.cs2005
- local project = p.project
+ local m = p.vstudio.cs2005
--
--- Generate a Visual Studio 200x C# user file, with support for the new platforms API.
+-- Generate a Visual Studio 200x C# user file.
--
- function cs2005.generate_user(prj)
- p.vstudio.projectElement()
- _p(1,'')
+ m.elements.userProjectPropertyGroup = function()
+ return {
+ m.referencePath,
+ }
+ end
+ m.elements.userConfigPropertyGroup = function()
+ return {
+ m.localDebuggerCommandArguments,
+ }
+ end
+
+ function m.generateUser(prj)
+ -- Only want output if there is something to configure
+ local prjGroup = p.capture(function()
+ p.push(2)
+ p.callArray(m.elements.userProjectPropertyGroup, prj)
+ p.pop(2)
+ end)
+
+ local contents = {}
+ local size = 0
+
+ for cfg in p.project.eachconfig(prj) do
+ contents[cfg] = p.capture(function()
+ p.push(2)
+ p.callArray(m.elements.userConfigPropertyGroup, cfg)
+ p.pop(2)
+ end)
+ size = size + #contents[cfg]
+ end
+
+ if #prjGroup > 0 or size > 0 then
+ p.vstudio.projectElement()
+
+ if #prjGroup > 0 then
+ p.push('')
+ p.outln(prjGroup)
+ p.pop('')
+ end
+
+ for cfg in p.project.eachconfig(prj) do
+ if #contents[cfg] > 0 then
+ p.push('', m.condition(cfg))
+ p.outln(contents[cfg])
+ p.pop('')
+ end
+ end
+
+ p.pop('')
+ end
+ end
+
+
+
+---
+-- Output any reference paths required by the project.
+---
+
+ function m.referencePath(prj)
-- Per-configuration reference paths aren't supported (are they?) so just
-- use the first configuration in the project
- local cfg = project.getfirstconfig(prj)
-
- local refpaths = path.translate(project.getrelative(prj, cfg.libdirs))
- _p(2,'%s', table.concat(refpaths, ";"))
-
- _p(' ')
-
- for cfg in project.eachconfig(prj) do
- local contents = p.capture(function()
- cs2005.debugsettings(cfg)
- end)
-
- if #contents > 0 then
- _p(1,'', cs2005.condition(cfg))
- p.outln(contents)
- _p(1,'')
- end
+ local cfg = p.project.getfirstconfig(prj)
+ local paths = path.translate(p.project.getrelative(prj, cfg.libdirs))
+ if #paths > 0 then
+ p.w('%s', table.concat(paths, ";"))
end
-
- _p('')
end
- function cs2005.debugsettings(cfg)
- cs2005.localDebuggerCommandArguments(cfg)
- end
- function cs2005.localDebuggerCommandArguments(cfg)
+
+ function m.localDebuggerCommandArguments(cfg)
if #cfg.debugargs > 0 then
- _x(2,'%s', table.concat(cfg.debugargs, " "))
+ p.x('%s', table.concat(cfg.debugargs, " "))
end
end
\ No newline at end of file
diff --git a/src/actions/vstudio/vs200x_vcproj_user.lua b/src/actions/vstudio/vs200x_vcproj_user.lua
index e8852237..40853c8f 100644
--- a/src/actions/vstudio/vs200x_vcproj_user.lua
+++ b/src/actions/vstudio/vs200x_vcproj_user.lua
@@ -1,79 +1,133 @@
--
-- vs200x_vcproj_user.lua
-- Generate a Visual Studio 2002-2008 C/C++ project .user file
--- Copyright (c) 2011-2013 Jason Perkins and the Premake project
+-- Copyright (c) 2011-2015 Jason Perkins and the Premake project
--
local p = premake
- local vstudio = premake.vstudio
- local project = p.project
-
local m = p.vstudio.vc200x
+
--
-- Generate a Visual Studio 200x C++ user file, with support for the new platforms API.
--
- function m.generate_user(prj)
+ m.elements.user = function(cfg)
+ return {
+ m.debugSettings,
+ }
+ end
+
+ function m.generateUser(prj)
p.indent("\t")
- m.xmlElement()
+
+ -- Only want output if there is something to configure
+ local contents = {}
+ local size = 0
+
+ for cfg in p.project.eachconfig(prj) do
+ contents[cfg] = p.capture(function()
+ p.push(4)
+ p.callArray(m.elements.user, cfg)
+ p.pop(4)
+ end)
+ size = size + #contents[cfg]
+ end
+
+ if size > 0 then
+ m.xmlElement()
+ m.visualStudioUserFile()
+ p.push('')
+ for cfg in p.project.eachconfig(prj) do
+ m.userConfiguration(cfg)
+ p.push(' 0 then
+ p.outln(contents[cfg])
+ end
+ p.pop('/>')
+ p.pop('')
+ end
+ p.pop('')
+ p.pop('')
+ end
+ end
+
+
+
+---
+-- Output the opening project tag.
+---
+
+ function m.visualStudioUserFile()
p.push('')
-
- p.push('')
- for cfg in project.eachconfig(prj) do
- m.userconfiguration(cfg)
- m.debugdir(cfg)
- p.pop('')
- end
- p.pop('')
- p.pop('')
end
+
--
-- Write out the element, describing a specific Premake
-- build configuration/platform pairing.
--
- function m.userconfiguration(cfg)
+ function m.userConfiguration(cfg)
p.push('')
end
+
--
-- Write out the debug settings for this project.
--
- function m.debugdir(cfg)
- p.push(' 0 then
p.x('CommandArguments="%s"', table.concat(cfg.debugargs, " "))
end
+ end
+
+ function m.debugCommand(cfg)
+ if cfg.debugcommand then
+ local command = p.project.getrelative(cfg.project, cfg.debugcommand)
+ p.x('Command="%s"', path.translate(command))
+ end
+ end
+
+
+ function m.debugDir(cfg)
+ if cfg.debugdir then
+ local debugdir = p.project.getrelative(cfg.project, cfg.debugdir)
+ p.x('WorkingDirectory="%s"', path.translate(debugdir))
+ end
+ end
+
+
+ function m.debugEnvironment(cfg)
if #cfg.debugenvs > 0 then
p.x('Environment="%s"', table.concat(cfg.debugenvs, "\n"))
if cfg.flags.DebugEnvsDontMerge then
p.x('EnvironmentMerge="false"')
end
end
-
- p.pop('/>')
end
diff --git a/src/actions/vstudio/vs2010.lua b/src/actions/vstudio/vs2010.lua
index 54d004db..72a3c018 100644
--- a/src/actions/vstudio/vs2010.lua
+++ b/src/actions/vstudio/vs2010.lua
@@ -1,7 +1,7 @@
--
-- actions/vstudio/vs2010.lua
-- Add support for the Visual Studio 2010 project formats.
--- Copyright (c) 2009-2014 Jason Perkins and the Premake project
+-- Copyright (c) 2009-2015 Jason Perkins and the Premake project
--
premake.vstudio.vs2010 = {}
@@ -40,15 +40,27 @@
if premake.project.isdotnet(prj) then
premake.generate(prj, ".csproj", vstudio.cs2005.generate)
- premake.generate(prj, ".csproj.user", vstudio.cs2005.generate_user)
+
+ -- Skip generation of empty user files
+ local user = p.capture(function() vstudio.cs2005.generateUser(prj) end)
+ if #user > 0 then
+ p.generate(prj, ".csproj.user", function() p.outln(user) end)
+ end
+
elseif premake.project.iscpp(prj) then
premake.generate(prj, ".vcxproj", vstudio.vc2010.generate)
- premake.generate(prj, ".vcxproj.user", vstudio.vc2010.generateUser)
+
+ -- Skip generation of empty user files
+ local user = p.capture(function() vstudio.vc2010.generateUser(prj) end)
+ if #user > 0 then
+ p.generate(prj, ".vcxproj.user", function() p.outln(user) end)
+ end
-- Only generate a filters file if the source tree actually has subfolders
if tree.hasbranches(project.getsourcetree(prj)) then
premake.generate(prj, ".vcxproj.filters", vstudio.vc2010.generateFilters)
end
+
end
end
diff --git a/src/actions/vstudio/vs2010_vcxproj_user.lua b/src/actions/vstudio/vs2010_vcxproj_user.lua
index 4cc462f1..9bdd20c2 100755
--- a/src/actions/vstudio/vs2010_vcxproj_user.lua
+++ b/src/actions/vstudio/vs2010_vcxproj_user.lua
@@ -1,36 +1,55 @@
--
-- vs2010_vcxproj_user.lua
-- Generate a Visual Studio 201x C/C++ project .user file
--- Copyright (c) 2011-2013 Jason Perkins and the Premake project
+-- Copyright (c) 2011-2015 Jason Perkins and the Premake project
--
local p = premake
- local vstudio = p.vstudio
- local vc2010 = p.vstudio.vc2010
- local project = p.project
-
local m = p.vstudio.vc2010
--
--- Generate a Visual Studio 201x C++ user file, with support for the new platforms API.
+-- Generate a Visual Studio 201x C++ user file.
--
+ m.elements.user = function(cfg)
+ return {
+ m.debugSettings,
+ }
+ end
+
function m.generateUser(prj)
- m.xmlDeclaration()
- m.userProject()
- for cfg in project.eachconfig(prj) do
- p.push('', m.condition(cfg))
- m.debugSettings(cfg)
- p.pop('')
+ -- Only want output if there is something to configure
+ local contents = {}
+ local size = 0
+
+ for cfg in p.project.eachconfig(prj) do
+ contents[cfg] = p.capture(function()
+ p.push(2)
+ p.callArray(m.elements.user, cfg)
+ p.pop(2)
+ end)
+ size = size + #contents[cfg]
+ end
+
+ if size > 0 then
+ m.xmlDeclaration()
+ m.userProject()
+ for cfg in p.project.eachconfig(prj) do
+ p.push('', m.condition(cfg))
+ if #contents[cfg] > 0 then
+ p.outln(contents[cfg])
+ end
+ p.pop('')
+ end
+ p.pop('')
end
- _p('')
end
--
--- Output the XML declaration and opening tag.
+-- Output the opening tag.
--
function m.userProject()
@@ -41,24 +60,24 @@
- vc2010.elements.debugSettings = function(cfg)
+ m.elements.debugSettings = function(cfg)
return {
- vc2010.localDebuggerCommand,
- vc2010.localDebuggerWorkingDirectory,
- vc2010.debuggerFlavor,
- vc2010.localDebuggerCommandArguments,
- vc2010.localDebuggerEnvironment,
- vc2010.localDebuggerMergeEnvironment,
+ m.localDebuggerCommand,
+ m.localDebuggerWorkingDirectory,
+ m.debuggerFlavor,
+ m.localDebuggerCommandArguments,
+ m.localDebuggerEnvironment,
+ m.localDebuggerMergeEnvironment,
}
end
- function vc2010.debugSettings(cfg)
- p.callArray(vc2010.elements.debugSettings, cfg)
+ function m.debugSettings(cfg)
+ p.callArray(m.elements.debugSettings, cfg)
end
- function vc2010.debuggerFlavor(cfg)
+ function m.debuggerFlavor(cfg)
if cfg.debugdir or cfg.debugcommand then
p.w('WindowsLocalDebugger')
end
@@ -66,16 +85,16 @@
- function vc2010.localDebuggerCommand(cfg)
+ function m.localDebuggerCommand(cfg)
if cfg.debugcommand then
- local dir = project.getrelative(cfg.project, cfg.debugcommand)
+ local dir = p.project.getrelative(cfg.project, cfg.debugcommand)
p.w('%s', path.translate(dir))
end
end
- function vc2010.localDebuggerCommandArguments(cfg)
+ function m.localDebuggerCommandArguments(cfg)
if #cfg.debugargs > 0 then
p.x('%s', table.concat(cfg.debugargs, " "))
end
@@ -83,16 +102,16 @@
- function vc2010.localDebuggerWorkingDirectory(cfg)
+ function m.localDebuggerWorkingDirectory(cfg)
if cfg.debugdir then
- local dir = project.getrelative(cfg.project, cfg.debugdir)
+ local dir = p.project.getrelative(cfg.project, cfg.debugdir)
p.x('%s', path.translate(dir))
end
end
- function vc2010.localDebuggerEnvironment(cfg)
+ function m.localDebuggerEnvironment(cfg)
if #cfg.debugenvs > 0 then
local envs = table.concat(cfg.debugenvs, "\n")
if cfg.flags.DebugEnvsInherit then
@@ -108,7 +127,7 @@
- function vc2010.localDebuggerMergeEnvironment(cfg)
+ function m.localDebuggerMergeEnvironment(cfg)
if #cfg.debugenvs > 0 and cfg.flags.DebugEnvsDontMerge then
p.w(2,'false')
end
diff --git a/src/base/premake.lua b/src/base/premake.lua
index 428493a0..7f011d48 100644
--- a/src/base/premake.lua
+++ b/src/base/premake.lua
@@ -164,6 +164,7 @@
_indentLevel = 0
callback(obj)
f:close()
+ _indentLevel = 0
end
diff --git a/tests/_tests.lua b/tests/_tests.lua
index 08deae23..482a5e01 100644
--- a/tests/_tests.lua
+++ b/tests/_tests.lua
@@ -55,7 +55,7 @@ return {
"tools/test_gcc.lua",
"tools/test_msc.lua",
- -- Visual Studio 2005-2010 C# projects
+ -- Visual Studio 2005-2013 C# projects
"actions/vstudio/cs2005/test_assembly_refs.lua",
"actions/vstudio/cs2005/test_build_events.lua",
"actions/vstudio/cs2005/test_common_props.lua",
@@ -69,8 +69,9 @@ return {
"actions/vstudio/cs2005/test_project_refs.lua",
"actions/vstudio/cs2005/projectsettings.lua",
"actions/vstudio/cs2005/test_targets.lua",
+ "actions/vstudio/cs2005/test_user_file.lua",
- -- Visual Studio 2005-2010 solutions
+ -- Visual Studio 2005-2013 solutions
"actions/vstudio/sln2005/test_dependencies.lua",
"actions/vstudio/sln2005/test_header.lua",
"actions/vstudio/sln2005/test_nested_projects.lua",
@@ -92,8 +93,9 @@ return {
"actions/vstudio/vc200x/test_project.lua",
"actions/vstudio/vc200x/test_project_refs.lua",
"actions/vstudio/vc200x/test_resource_compiler.lua",
+ "actions/vstudio/vc200x/test_user_file.lua",
- -- Visual Studio 2010 C/C++ projects
+ -- Visual Studio 2010-2013 C/C++ projects
"actions/vstudio/vc2010/test_assembly_refs.lua",
"actions/vstudio/vc2010/test_build_events.lua",
"actions/vstudio/vc2010/test_compile_settings.lua",
@@ -118,6 +120,7 @@ return {
"actions/vstudio/vc2010/test_prop_sheet.lua",
"actions/vstudio/vc2010/test_resource_compile.lua",
"actions/vstudio/vc2010/test_rule_vars.lua",
+ "actions/vstudio/vc2010/test_user_file.lua",
-- Makefile tests
"actions/make/test_make_escaping.lua",
diff --git a/tests/actions/vstudio/cs2005/test_debug_props.lua b/tests/actions/vstudio/cs2005/test_debug_props.lua
index ad44ec33..bd24191c 100644
--- a/tests/actions/vstudio/cs2005/test_debug_props.lua
+++ b/tests/actions/vstudio/cs2005/test_debug_props.lua
@@ -65,12 +65,10 @@
function suite.debugStartArguments()
debugargs "foobar"
-
local cfg = test.getconfig(prj, "Debug")
- cs2005.debugsettings(cfg)
-
+ cs2005.localDebuggerCommandArguments(cfg)
test.capture [[
- foobar
+foobar
]]
end
diff --git a/tests/actions/vstudio/cs2005/test_user_file.lua b/tests/actions/vstudio/cs2005/test_user_file.lua
new file mode 100644
index 00000000..193555a9
--- /dev/null
+++ b/tests/actions/vstudio/cs2005/test_user_file.lua
@@ -0,0 +1,49 @@
+--
+-- tests/actions/vstudio/cs2005/test_user_file.lua
+-- Verify handling of empty and non-empty .user files for VC#.
+-- Copyright (c) 2015 Jason Perkins and the Premake project
+--
+
+ local suite = test.declare("vstudio_cs2005_user_file")
+ local cs2005 = premake.vstudio.cs2005
+
+
+--
+-- Setup
+--
+
+ local sln
+
+ function suite.setup()
+ _ACTION = "vs2008"
+ sln = test.createsolution()
+ language "C#"
+ end
+
+ local function prepare()
+ local prj = test.getproject(sln, 1)
+ cs2005.generateUser(prj)
+ end
+
+
+--
+-- If no debugger settings have been specified, then the .user
+-- file should not be written at all.
+--
+
+ function suite.noOutput_onNoSettings()
+ prepare()
+ test.isemptycapture()
+ end
+
+
+--
+-- If a debugger setting has been specified, output.
+--
+
+ function suite.doesOutput_onDebugSettings()
+ debugargs { "hello" }
+ prepare()
+ test.hasoutput()
+ end
+
diff --git a/tests/actions/vstudio/vc200x/test_debug_settings.lua b/tests/actions/vstudio/vc200x/test_debug_settings.lua
index e0862258..6cc0bf1f 100644
--- a/tests/actions/vstudio/vc200x/test_debug_settings.lua
+++ b/tests/actions/vstudio/vc200x/test_debug_settings.lua
@@ -22,7 +22,7 @@
local function prepare()
local cfg = test.getconfig(prj, "Debug")
- vc200x.debugdir(cfg)
+ vc200x.debugSettings(cfg)
end
@@ -32,10 +32,7 @@
function suite.emptyBlock_onNoSettings()
prepare()
- test.capture [[
-
- ]]
+ test.isemptycapture()
end
@@ -49,9 +46,7 @@
debugcommand "bin/emulator.exe"
prepare()
test.capture [[
-
+Command="..\bin\emulator.exe"
]]
end
@@ -66,9 +61,7 @@
debugdir "bin/debug"
prepare()
test.capture [[
-
+WorkingDirectory="..\bin\debug"
]]
end
@@ -81,9 +74,7 @@
debugargs { "arg1", "arg2" }
prepare()
test.capture [[
-
+CommandArguments="arg1 arg2"
]]
end
@@ -96,9 +87,7 @@
debugenvs { "key=value" }
prepare()
test.capture [[
-
+Environment="key=value"
]]
end
@@ -111,9 +100,7 @@
debugenvs { 'key="value"' }
prepare()
test.capture [[
-
+Environment="key="value""
]]
end
@@ -127,9 +114,7 @@
debugenvs { "key=value", "foo=bar" }
prepare()
test.capture [[
-
+Environment="key=value
foo=bar"
]]
end
@@ -144,9 +129,7 @@
flags { "DebugEnvsDontMerge" }
prepare()
test.capture [[
-
+Environment="key=value"
+EnvironmentMerge="false"
]]
end
diff --git a/tests/actions/vstudio/vc200x/test_user_file.lua b/tests/actions/vstudio/vc200x/test_user_file.lua
new file mode 100644
index 00000000..9616d242
--- /dev/null
+++ b/tests/actions/vstudio/vc200x/test_user_file.lua
@@ -0,0 +1,48 @@
+--
+-- tests/actions/vstudio/vc200x/test_user_file.lua
+-- Verify handling of empty and non-empty .user files for VC'200x.
+-- Copyright (c) 2015 Jason Perkins and the Premake project
+--
+
+ local suite = test.declare("vstudio_vs200x_user_file")
+ local vc200x = premake.vstudio.vc200x
+
+
+--
+-- Setup
+--
+
+ local sln
+
+ function suite.setup()
+ _ACTION = "vs2008"
+ sln = test.createsolution()
+ end
+
+ local function prepare()
+ local prj = test.getproject(sln, 1)
+ vc200x.generateUser(prj)
+ end
+
+
+--
+-- If no debugger settings have been specified, then the .user
+-- file should not be written at all.
+--
+
+ function suite.noOutput_onNoSettings()
+ prepare()
+ test.isemptycapture()
+ end
+
+
+--
+-- If a debugger setting has been specified, output.
+--
+
+ function suite.doesOutput_onDebugSettings()
+ debugcommand "bin/emulator.exe"
+ prepare()
+ test.hasoutput()
+ end
+
diff --git a/tests/actions/vstudio/vc2010/test_user_file.lua b/tests/actions/vstudio/vc2010/test_user_file.lua
new file mode 100644
index 00000000..9689cde0
--- /dev/null
+++ b/tests/actions/vstudio/vc2010/test_user_file.lua
@@ -0,0 +1,48 @@
+--
+-- tests/actions/vstudio/vc2010/test_user_file.lua
+-- Verify handling of empty and non-empty .user files for VC'201x.
+-- Copyright (c) 2015 Jason Perkins and the Premake project
+--
+
+ local suite = test.declare("vstudio_vs2010_user_file")
+ local vc2010 = premake.vstudio.vc2010
+
+
+--
+-- Setup
+--
+
+ local sln
+
+ function suite.setup()
+ _ACTION = "vs2010"
+ sln = test.createsolution()
+ end
+
+ local function prepare()
+ local prj = test.getproject(sln, 1)
+ vc2010.generateUser(prj)
+ end
+
+
+--
+-- If no debugger settings have been specified, then the .user
+-- file should not be written at all.
+--
+
+ function suite.noOutput_onNoSettings()
+ prepare()
+ test.isemptycapture()
+ end
+
+
+--
+-- If a debugger setting has been specified, output.
+--
+
+ function suite.doesOutput_onDebugSettings()
+ debugcommand "bin/emulator.exe"
+ prepare()
+ test.hasoutput()
+ end
+
diff --git a/tests/testfx.lua b/tests/testfx.lua
index ace5b256..5024bc76 100644
--- a/tests/testfx.lua
+++ b/tests/testfx.lua
@@ -121,6 +121,14 @@
end
+ function test.hasoutput()
+ local actual = premake.captured()
+ if actual == "" then
+ test.fail("expected output, received none");
+ end
+ end
+
+
function test.isemptycapture()
local actual = premake.captured()
if actual ~= "" then