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