Commits

Jason McKesson  committed aff98c2 Merge

Merge with default

  • Participants
  • Parent commits 092e176, ab25607
  • Branches alfonse-bug-fix

Comments (0)

Files changed (28)

 
 .DS_Store
 
-*.orig
-
 build
 bin
 obj
 Scratchpad.txt
 Unix Worksheet.worksheet
 project.bbprojectdata
-Premake4.tmproj
+Premake4.tmproj

File src/actions/make/_make.lua

 
 	premake.make = { }
 	local make = premake.make
+	local solution = premake.solution
 	local project = premake5.project
 
 --
 			if premake.isdotnetproject(prj) then
 				premake.generate(prj, makefile, make.generate_csharp)
 			else
-				premake.generate(prj, makefile, make.generate_cpp)
+				premake.generate(prj, makefile, make.cpp.generate)
 			end
 		end,
 		
 
 
 --
--- Output the default configuration for a project.
--- @return
---    True if a default configuration is written, false if the project
---    does not contain any supported configurations.
+-- Write out the default configuration rule for a solution or project.
+-- @param target
+--    The solution or project object for which a makefile is being generated.
 --
 
-	function make.defaultconfig(prj)
-		-- I don't actually loop, just getting the first config
-		for cfg in project.eachconfig(prj) do
+	function make.defaultconfig(target)
+		-- find the configuration iterator function
+		local eachconfig = iif(target.project, project.eachconfig, solution.eachconfig)
+		local iter = eachconfig(target)
+		
+		-- grab the first configuration and write the block
+		local cfg = iter()
+		if cfg then
 			_p('ifndef config')
 			_p('  config=%s', make.esc(cfg.shortname))
 			_p('endif')
 			_p('export config')
 			_p('')
-			return true
 		end
 	end
 
 				count = count + 1 
 			end
 			
-			if (searchprjs) then
-				for _,prj in ipairs(sln.projects) do
+			if searchprjs then
+				for _, prj in ipairs(sln.projects) do
 					if prj.location == this.location then
 						count = count + 1
 					end

File src/actions/make/make_cpp.lua

 	premake.make.cpp = { }
 	local make = premake.make
 	local cpp = premake.make.cpp
+	local project = premake5.project
+	local config = premake5.config
 
 
 --
+-- Generate a GNU make C++ project makefile, with support for the new platforms API.
+--
 
--- Generate a GNU make C++ project makefile, with support for the new platforms API.
+	function make.cpp.generate(prj)
+		--[[
+		-- create a shortcut to the compiler interface
+		local cc = premake.gettool(prj)
+
+		-- build a list of supported target platforms that also includes a generic build
+		local platforms = premake.filterplatforms(prj.solution, cc.platforms, "Native")
+		--]]
+		
+		cpp.header(prj)
+
+		for cfg in project.eachconfig(prj) do
+			cpp.config(cfg)
+		end
+		
+		--[[
+
+		-- list intermediate files
+		_p('OBJECTS := \\')
+		for _, file in ipairs(prj.files) do
+			if path.iscppfile(file) then
+				_p('\t$(OBJDIR)/%s.o \\', _MAKE.esc(path.getbasename(file)))
+			end
+		end
+		_p('')
+
+		_p('RESOURCES := \\')
+		for _, file in ipairs(prj.files) do
+			if path.isresourcefile(file) then
+				_p('\t$(OBJDIR)/%s.res \\', _MAKE.esc(path.getbasename(file)))
+			end
+		end
+		_p('')
+	--]]
+		
+		-- identify the shell type
+		_p('SHELLTYPE := msdos')
+		_p('ifeq (,$(ComSpec)$(COMSPEC))')
+		_p('  SHELLTYPE := posix')
+		_p('endif')
+		_p('ifeq (/bin,$(findstring /bin,$(SHELL)))')
+		_p('  SHELLTYPE := posix')
+		_p('endif')
+		_p('')
+
+		-- main build rule(s)
+		_p('.PHONY: clean prebuild prelink')
+		_p('')
+
+	--[[
+		if os.is("MacOSX") and prj.kind == "WindowedApp" then
+			_p('all: $(TARGETDIR) $(OBJDIR) prebuild prelink $(TARGET) $(dir $(TARGETDIR))PkgInfo $(dir $(TARGETDIR))Info.plist')
+		else
+			_p('all: $(TARGETDIR) $(OBJDIR) prebuild prelink $(TARGET)')
+		end
+		_p('\t@:')
+		_p('')
+
+		-- target build rule
+		_p('$(TARGET): $(GCH) $(OBJECTS) $(LDDEPS) $(RESOURCES)')
+		_p('\t@echo Linking %s', prj.name)
+		_p('\t$(SILENT) $(LINKCMD)')
+		_p('\t$(POSTBUILDCMDS)')
+		_p('')
+
+		-- Create destination directories. Can't use $@ for this because it loses the
+		-- escaping, causing issues with spaces and parenthesis
+		_p('$(TARGETDIR):')
+		premake.make_mkdirrule("$(TARGETDIR)")
+
+		_p('$(OBJDIR):')
+		premake.make_mkdirrule("$(OBJDIR)")
+
+		-- Mac OS X specific targets
+		if os.is("MacOSX") and prj.kind == "WindowedApp" then
+			_p('$(dir $(TARGETDIR))PkgInfo:')
+			_p('$(dir $(TARGETDIR))Info.plist:')
+			_p('')
+		end
+	--]]
+	
+		-- clean target
+		_p('clean:')
+		_p('\t@echo Cleaning %s', prj.name)
+		_p('ifeq (posix,$(SHELLTYPE))')
+		_p('\t$(SILENT) rm -f  $(TARGET)')
+		_p('\t$(SILENT) rm -rf $(OBJDIR)')
+		_p('else')
+		_p('\t$(SILENT) if exist $(subst /,\\\\,$(TARGET)) del $(subst /,\\\\,$(TARGET))')
+		_p('\t$(SILENT) if exist $(subst /,\\\\,$(OBJDIR)) rmdir /s /q $(subst /,\\\\,$(OBJDIR))')
+		_p('endif')
+		_p('')
+
+		-- custom build step targets
+		_p('prebuild:')
+		_p('\t$(PREBUILDCMDS)')
+		_p('')
+
+		_p('prelink:')
+		_p('\t$(PRELINKCMDS)')
+		_p('')
+
+	--[[
+		-- precompiler header rule
+		cpp.pchrules(prj)
+
+		-- per-file rules
+		for _, file in ipairs(prj.files) do
+			if path.iscppfile(file) then
+				_p('$(OBJDIR)/%s.o: %s', _MAKE.esc(path.getbasename(file)), _MAKE.esc(file))
+				_p('\t@echo $(notdir $<)')
+				cpp.buildcommand(path.iscfile(file))
+			elseif (path.getextension(file) == ".rc") then
+				_p('$(OBJDIR)/%s.res: %s', _MAKE.esc(path.getbasename(file)), _MAKE.esc(file))
+				_p('\t@echo $(notdir $<)')
+				_p('\t$(SILENT) $(RESCOMP) $< -O coff -o "$@" $(RESFLAGS)')
+			end
+		end
+		_p('')
+
+		-- include the dependencies, built by GCC (with the -MMD flag)
+		_p('-include $(OBJECTS:%%.o=%%.d)')
+		--]]
+		
+		print("** Warning: GMake C++ project have not been ported yet")
+	end
+
 
 --
+-- Write out the C++ makefile header.
+--
 
+	function cpp.header(prj)
+		-- a little help for the uninitiated
+		_p('# %s C/C++ project makefile autogenerated by Premake', premake.action.current().shortname)
+		_p('')
 
-	function make.generate_cpp(prj)
-		print("** Warning: GMake C++ project have not been ported yet")
+		make.defaultconfig(prj)
+
+		_p('ifndef verbose')
+		_p('  SILENT = @')
+		_p('endif')
+		_p('')
+				
+		--[[
+		_p('ifndef CC')
+		_p('  CC = %s', cc.cc)
+		_p('endif')
+		_p('')
+
+		_p('ifndef CXX')
+		_p('  CXX = %s', cc.cxx)
+		_p('endif')
+		_p('')
+
+		_p('ifndef AR')
+		_p('  AR = %s', cc.ar)
+		_p('endif')
+		_p('')
+		
+		_p('ifndef RESCOMP')
+		_p('  ifdef WINDRES')
+		_p('    RESCOMP = $(WINDRES)')
+		_p('  else')
+		_p('    RESCOMP = windres')
+		_p('  endif')
+		_p('endif')
+		_p('')	
+		--]]
+	end
+
+
+--
+-- Write out the settings for a particular configuration.
+--
+
+	function cpp.config(cfg)
+		-- identify the toolset used by this configurations
+		local toolset = premake.tools[cfg.toolset or "gcc"]
+		if not toolset then
+			error("Invalid toolset '" + cfg.toolset + "'")
+		end
+	
+		_p('ifeq ($(config),%s)', make.esc(cfg.shortname))
+	
+	--[[
+		-- if this platform requires a special compiler or linker, list it here
+		cpp.platformtools(cfg, cc)
+	--]]
+
+		local targetinfo = config.gettargetinfo(cfg)
+		
+		_p('  OBJDIR     = %s', make.esc(cfg.objdir))
+		_p('  TARGETDIR  = %s', make.esc(targetinfo.directory))
+		_p('  TARGET     = $(TARGETDIR)/%s', make.esc(targetinfo.name))
+		_p('  DEFINES   += %s', table.concat(toolset.getdefines(cfg.defines), " "))
+		_p('  INCLUDES  += %s', table.concat(make.esc(toolset.getincludedirs(cfg.includedirs), " ")))
+		_p('  CPPFLAGS  += %s $(DEFINES) $(INCLUDES)', table.concat(toolset.getcppflags(cfg), " "))
+		_p('  CFLAGS    += $(CPPFLAGS) $(ARCH) %s', table.concat(table.join(toolset.getcflags(cfg), cfg.buildoptions), " "))
+		_p('  CXXFLAGS  += $(CFLAGS) %s', table.concat(toolset.getcxxflags(cfg), " "))
+		_p('  LDFLAGS   += %s', table.concat(table.join(toolset.getldflags(cfg), cfg.linkoptions), " "))
+	
+		local resflags = table.join(toolset.getdefines(cfg.resdefines), toolset.getincludedirs(cfg.resincludedirs), cfg.resoptions)
+		_p('  RESFLAGS  += $(DEFINES) $(INCLUDES) %s', table.concat(resflags, " "))
+
+	--[[
+		-- set up precompiled headers
+		cpp.pchconfig(cfg)
+
+		_p('  LIBS      += %s', table.concat(cc.getlinkflags(cfg), " "))
+		_p('  LDDEPS    += %s', table.concat(_MAKE.esc(premake.getlinks(cfg, "siblings", "fullpath")), " "))
+
+		if cfg.kind == "StaticLib" then
+			if cfg.platform:startswith("Universal") then
+				_p('  LINKCMD    = libtool -o $(TARGET) $(OBJECTS)')
+			else
+				_p('  LINKCMD    = $(AR) -rcs $(TARGET) $(OBJECTS)')
+			end
+		else
+			-- this was $(TARGET) $(LDFLAGS) $(OBJECTS)
+			--  but had trouble linking to certain static libs so $(OBJECTS) moved up
+			-- then $(LDFLAGS) moved to end
+			--   https://sourceforge.net/tracker/?func=detail&aid=3430158&group_id=71616&atid=531880
+			_p('  LINKCMD    = $(%s) -o $(TARGET) $(OBJECTS) $(RESOURCES) $(ARCH) $(LIBS) $(LDFLAGS)', iif(cfg.language == "C", "CC", "CXX"))
+		end
+	--]]
+	
+		_p('  define PREBUILDCMDS')
+		if #cfg.prebuildcommands > 0 then
+			_p('\t@echo Running pre-build commands')
+			_p('\t%s', table.implode(cfg.prebuildcommands, "", "", "\n\t"))
+		end
+		_p('  endef')
+
+		_p('  define PRELINKCMDS')
+		if #cfg.prelinkcommands > 0 then
+			_p('\t@echo Running pre-link commands')
+			_p('\t%s', table.implode(cfg.prelinkcommands, "", "", "\n\t"))
+		end
+		_p('  endef')
+
+		_p('  define POSTBUILDCMDS')
+		if #cfg.postbuildcommands > 0 then
+			_p('\t@echo Running post-build commands')
+			_p('\t%s', table.implode(cfg.postbuildcommands, "", "", "\n\t"))
+		end
+		_p('  endef')
+
+	--[[
+		-- write out config-level makesettings blocks
+		make.settings(cfg, cc)
+	--]]
+
+		_p('endif')
+		_p('')	
 	end
 
 
 		_p('ifeq ($(config),%s)', _MAKE.esc(cfg.shortname))
 
 		-- if this platform requires a special compiler or linker, list it here
-		cpp.platformtools(cfg, cc)
+		cpp.platformtools_old(cfg, cc)
 
 		_p('  OBJDIR     = %s', _MAKE.esc(cfg.objectsdir))
 		_p('  TARGETDIR  = %s', _MAKE.esc(cfg.buildtarget.directory))
 -- Platform support
 --
 
-	function cpp.platformtools(cfg, cc)
+	function cpp.platformtools_old(cfg, cc)
 		local platform = cc.platforms[cfg.platform]
 		if platform.cc then
 			_p('  CC         = %s', platform.cc)

File src/actions/make/make_solution.lua

 
 	local make = premake.make
 	local solution = premake.solution
+	local project = premake5.project
 
 
 --
 --
 
 	function make.generate_solution(sln)
-		
---[[		
-		-- create a shortcut to the compiler interface
-		local cc = premake[_OPTIONS.cc]
-
-		-- build a list of supported target platforms that also includes a generic build
-		local platforms = premake.filterplatforms(sln, cc.platforms, "Native")
---]]
-
 		-- a little guidance for the uninitiated
 		_p('# %s solution makefile autogenerated by Premake', premake.action.current().shortname)
 		_p('# Type "make help" for usage help')
 		_p('')
 
-		-- find and set a default configuration
-		for prj in solution.eachproject_ng(sln) do
-			if make.defaultconfig(prj) then
-				break
-			end
-		end
-		
-		
---[[
-		
-		-- set a default configuration
-		_p('ifndef config')
-		_p('  config=%s', _MAKE.esc(premake.getconfigname(sln.configurations[1], platforms[1], true)))
-		_p('endif')
-		_p('export config')
-		_p('')
+		make.defaultconfig(sln)
+		make.projects(sln)
 
-		-- list the projects included in the solution
-		_p('PROJECTS := %s', table.concat(_MAKE.esc(table.extract(sln.projects, "name")), " "))
-		_p('')
 		_p('.PHONY: all clean help $(PROJECTS)')
 		_p('')
 		_p('all: $(PROJECTS)')
 		_p('')
 
-		-- write the project build rules
-		for _, prj in ipairs(sln.projects) do
-			_p('%s: %s', _MAKE.esc(prj.name), table.concat(_MAKE.esc(table.extract(premake.getdependencies(prj), "name")), " "))
-			_p('\t@echo "==== Building %s ($(config)) ===="', prj.name)
-			_p('\t@${MAKE} --no-print-directory -C %s -f %s', _MAKE.esc(path.getrelative(sln.location, prj.location)), _MAKE.esc(make.getmakefilename(prj, true)))
-			_p('')
-		end
+		make.projectrules(sln)
+		make.cleanrules(sln)
+		make.helprule(sln)
+	end
 
-		-- clean rules
+
+--
+-- Write out the rules for the `make clean` action.
+--
+
+	function make.cleanrules(sln)
 		_p('clean:')
-		for _ ,prj in ipairs(sln.projects) do
-			_p('\t@${MAKE} --no-print-directory -C %s -f %s clean', _MAKE.esc(path.getrelative(sln.location, prj.location)), _MAKE.esc(make.getmakefilename(prj, true)))
+		for prj in solution.eachproject_ng(sln) do
+			local slnpath = solution.getlocation(sln)
+			local prjpath = path.getrelative(slnpath, project.getlocation(prj))
+			_p(1,'@${MAKE} --no-print-directory -C %s -f %s clean', make.esc(prjpath), make.esc(make.getmakefilename(prj, true)))
 		end
 		_p('')
---]]
-
-		make.helprule(sln)
-
---[[
-		-- help rule
-		_p('help:')
-		_p(1,'@echo "Usage: make [config=name] [target]"')
-		_p(1,'@echo ""')
-		_p(1,'@echo "CONFIGURATIONS:"')
-
-		local cfgpairs = { }
-		for _, platform in ipairs(platforms) do
-			for _, cfgname in ipairs(sln.configurations) do
-				_p(1,'@echo "   %s"', premake.getconfigname(cfgname, platform, true))
-			end
-		end
-		_p(1,'@echo ""')
-		
-		_p(1,'@echo "TARGETS:"')
-		_p(1,'@echo "   all (default)"')
-		_p(1,'@echo "   clean"')
-
-		for _, prj in ipairs(sln.projects) do
-			_p(1,'@echo "   %s"', prj.name)
-		end
-
-		_p(1,'@echo ""')
-		_p(1,'@echo "For more information, see http://industriousone.com/premake/quick-start"')
-
---]]
-
-		print("** Warning: GMake solutions have not been ported yet")
 	end
 
 
 		end
 
 		_p(1,'@echo ""')
+
+		_p(1,'@echo "TARGETS:"')
+		_p(1,'@echo "   all (default)"')
+		_p(1,'@echo "   clean"')
+
+		for prj in solution.eachproject_ng(sln) do
+			_p(1,'@echo "   %s"', prj.name)
+		end
+
+		_p(1,'@echo ""')
+		_p(1,'@echo "For more information, see http://industriousone.com/premake/quick-start"')
 	end
 
 
+--
+-- Write out the list of projects that comprise the solution.
+--
+
+	function make.projects(sln)
+		_p('PROJECTS := %s', table.concat(make.esc(table.extract(sln.projects, "name")), " "))
+		_p('')
+	end
+
+
+--
+-- Write out the rules to build each of the solution's projects.
+--
+
+	function make.projectrules(sln)
+		for prj in solution.eachproject_ng(sln) do
+			local deps = project.getdependencies(prj)
+			deps = table.extract(deps, "name")			
+			_p('%s: %s', make.esc(prj.name), make.esc(table.concat(deps, " ")))
+			
+			_p(1,'@echo "==== Building %s ($(config)) ===="', prj.name)
+
+			local slnpath = solution.getlocation(sln)
+			local prjpath = path.getrelative(slnpath, project.getlocation(prj))
+			_p(1,'@${MAKE} --no-print-directory -C %s -f %s', make.esc(prjpath), make.esc(make.getmakefilename(prj, true)))
+			
+			_p('')
+		end
+	end
+
+
+
 -----------------------------------------------------------------------------
 -- Everything below this point is a candidate for deprecation
 -----------------------------------------------------------------------------

File src/actions/vstudio/_vstudio.lua

 -- form: <project platform name>|<architecture>.
 --
 
-	function vstudio.configname(cfg)
+	function vstudio.configname(cfg, arch)
 		local platform = vstudio.projectplatform(cfg)
-		local architecture = vstudio.architecture(cfg)
+		local architecture = arch or vstudio.architecture(cfg)
 		return platform .. "|" .. architecture
 	end
 
 		oncleansolution = premake.vstudio.cleansolution,
 		oncleanproject  = premake.vstudio.cleanproject,
 		oncleantarget   = premake.vstudio.cleantarget
-	}
+	}

File src/actions/vstudio/vs2005_solution.lua

 		_p(1,'GlobalSection(ProjectConfigurationPlatforms) = postSolution')
 		for prj in solution.eachproject_ng(sln) do
 			for slncfg in solution.eachconfig(sln) do
-				local prjcfg = project.mapconfig(prj, slncfg.buildcfg, slncfg.platform)
+				local prjcfg = project.getconfig(prj, slncfg.buildcfg, slncfg.platform)
 				if prjcfg then
 					local slnplatform = vstudio.platform(slncfg)
 					local prjplatform = vstudio.projectplatform(prjcfg)

File src/actions/vstudio/vs200x_vcproj.lua

 
 		vc200x.xmldeclaration()
 		vc200x.visualStudioProject(prj)
-		vc200x.platforms(prj)
-
+		local architectures = vc200x.platforms(prj)
+		
 		if _ACTION > "vs2003" then
 			_p(1,'<ToolFiles>')
 			_p(1,'</ToolFiles>')
 
 		_p(1,'<Configurations>')
 		for cfg in project.eachconfig(prj) do
-			vc200x.configuration(cfg)
-			vc200x.tools(cfg)
-			_p(2,'</Configuration>')
+			-- Visual Studio requires each project configuration to have an
+			-- entry for every project architecture. Those that are not 
+			-- actually part of the solution, use a skeleton configuration.
+			local cfgarch = vstudio.architecture(cfg)
+			for _, prjarch in ipairs(architectures) do
+				if cfgarch == prjarch then
+					vc200x.configuration(cfg)
+					vc200x.tools(cfg)
+					_p(2,'</Configuration>')
+				else
+					vc200x.emptyconfiguration(cfg, prjarch)
+				end
+			end
 		end
 		_p(1,'</Configurations>')
 
 		local cfg = project.getconfig(prj, prj.configurations[1], prj.platforms[1])
 		_p(1,'Keyword="%s"', iif(cfg.flags.Managed, "ManagedCProj", "Win32Proj"))
 		
+		_p(1,'TargetFrameworkVersion=\"0\"')
 		_p(1,'>')
 	end
 
 	function vc200x.platforms(prj)
 		_p(1,'<Platforms>')
 
-		architectures = { }
+		architectures = {}
 		for cfg in project.eachconfig(prj) do
 			local arch = vstudio.architecture(cfg)
-			if not architectures[arch] then
+			if not table.contains(architectures, arch) then
+				table.insert(architectures, arch)
 				_p(2,'<Platform')
 				_p(3,'Name="%s"', arch)
 				_p(2,'/>')
-				architectures[arch] = true
 			end
 		end
 
 		_p(1,'</Platforms>')
+		return architectures
 	end
 
 
 
 
 --
+-- Write out an empty configuration element for a build configuration/
+-- platform that is not actually part of the solution.
+--
+
+	function vc200x.emptyconfiguration(cfg, arch)
+		_p(2,'<Configuration')
+		_x(3,'Name="%s|%s"', vstudio.projectplatform(cfg), arch)
+		_p(3,'IntermediateDirectory="$(PlatformName)\$(ConfigurationName)"')
+		_p(3,'ConfigurationType="1"')
+		_p(3,'>')
+	
+		local tools = vc200x.gettools(cfg)
+		for _, tool in ipairs(tools) do
+			vc200x.tool(tool)
+		end
+		
+		_p(2,'</Configuration>')
+	end
+
+
+--
 -- Write out the tool elements for a specific configuration.
 --
 
 			_p(4,'MinimalRebuild="%s"', bool(true))
 		end
 		
-		if cfg.flags.NoExceptions then
-			_p(4,'ExceptionHandling="%s"', iif(_ACTION < "vs2005", "FALSE", 0))
-		elseif cfg.flags.SEH and _ACTION > "vs2003" then
-			_p(4,'ExceptionHandling="2"')
-		end
-		
 		if vc200x.optimization(cfg) == 0 and not cfg.flags.Managed then
 			_p(4,'BasicRuntimeChecks="3"')
 		end
 			_p(4,'StringPooling="%s"', bool(true))
 		end
 		
+		if cfg.flags.NoExceptions then
+			_p(4,'ExceptionHandling="%s"', iif(_ACTION < "vs2005", "FALSE", 0))
+		elseif cfg.flags.SEH and _ACTION > "vs2003" then
+			_p(4,'ExceptionHandling="2"')
+		end
+		
 		local runtime
 		if premake.config.isdebugbuild(cfg) then
 			runtime = iif(cfg.flags.StaticRuntime, 1, 3)
 			_p(4,'UsePrecompiledHeader="%s"', iif(_ACTION > "vs2003" or cfg.flags.NoPCH, 0, 2))
 		end
 		
+		_x(4,'ProgramDataBaseFileName="$(OutDir)\\%s.pdb"', config.gettargetinfo(cfg).basename)
+		
 		vc200x.warnings(cfg)
 		
-		_x(4,'ProgramDataBaseFileName="$(OutDir)\\%s.pdb"', config.gettargetinfo(cfg).basename)
-		
 		_p(4,'DebugInformationFormat="%s"', vc200x.symbols(cfg))
 		
 		if cfg.project.language == "C" then
 
 
 	function vc200x.VCCLExternalCompilerTool(cfg, toolset)
-		local buildoptions = table.join(toolset.getcflags(cfg), toolset.getcxxflags(cfg), cfg.buildoptions)
-		
+		local buildoptions = table.join(toolset.getcflags(cfg), toolset.getcxxflags(cfg), cfg.buildoptions)		
 		if not cfg.flags.NoPCH and cfg.pchheader then
-			_p(4,'UsePrecompiledHeader="%s"', iif(_ACTION < "vs2005", 3, 2))
-			_x(4,'PrecompiledHeaderThrough="%s"', path.getname(cfg.pchheader))
 			table.insert(buildoptions, '--use_pch="$(IntDir)/$(TargetName).pch"')
-		else
-			_p(4,'UsePrecompiledHeader="%s"', iif(_ACTION > "vs2003" or cfg.flags.NoPCH, 0, 2))
 		end
-
 		if #buildoptions > 0 then
 			_x(4,'AdditionalOptions="%s"', table.concat(buildoptions, " "))
 		end
 		vc200x.additionalIncludeDirectories(cfg, cfg.includedirs)
 		vc200x.preprocessorDefinitions(cfg, cfg.defines)
 
+		if not cfg.flags.NoPCH and cfg.pchheader then
+			_p(4,'UsePrecompiledHeader="%s"', iif(_ACTION < "vs2005", 3, 2))
+			_x(4,'PrecompiledHeaderThrough="%s"', path.getname(cfg.pchheader))
+		else
+			_p(4,'UsePrecompiledHeader="%s"', iif(_ACTION > "vs2003" or cfg.flags.NoPCH, 0, 2))
+		end
+
 		_x(4,'ProgramDataBaseFileName="$(OutDir)\\%s.pdb"', config.gettargetinfo(cfg).basename)
 
 		_p(4,'DebugInformationFormat="0"')
 			end
 		end
 		
-		_p(3,'<Tool')
-		_p(4,'Name="VCManifestTool"')
-		if #manifests > 0 then
-			_x(4,'AdditionalManifestFiles="%s"', table.concat(manifests, ";"))
-		end
-		_p(3,'/>')
+			_p(3,'<Tool')
+			_p(4,'Name="VCManifestTool"')
+			if #manifests > 0 then
+				_x(4,'AdditionalManifestFiles="%s"', table.concat(manifests, ";"))
+			end
+			_p(3,'/>')
 	end
 
 
 			_x(4,'AdditionalOptions="%s"', table.concat(cfg.resoptions, " "))
 		end
 
-		vc200x.additionalIncludeDirectories(cfg, table.join(cfg.includedirs, cfg.resincludedirs))
 		vc200x.preprocessorDefinitions(cfg, table.join(cfg.defines, cfg.resdefines))
+			vc200x.additionalIncludeDirectories(cfg, table.join(cfg.includedirs, cfg.resincludedirs))
 		
 		_p(3,'/>')
 	end
 				"VCBscMakeTool",
 				"VCFxCopTool",
 				"VCAppVerifierTool",
-				"VCWebDeploymentTool",
 				"VCPostBuildEventTool"
 			}
 		end

File src/actions/vstudio/vs2010_vcxproj.lua

 --
 
 	function vc2010.projectConfigurations(prj)
+		-- build a list of all architectures used in this project
+		local platforms = {}
+		for cfg in project.eachconfig(prj) do
+			local arch = vstudio.architecture(cfg)
+			if not table.contains(platforms, arch) then
+				table.insert(platforms, arch)
+			end
+		end
+	
 		_p(1,'<ItemGroup Label="ProjectConfigurations">')
 		for cfg in project.eachconfig(prj) do
-			_x(2,'<ProjectConfiguration Include="%s">', vstudio.configname(cfg))
-			_x(3,'<Configuration>%s</Configuration>', vstudio.projectplatform(cfg))
-			_p(3,'<Platform>%s</Platform>', vstudio.architecture(cfg))
-			_p(2,'</ProjectConfiguration>')
+			for _, arch in ipairs(platforms) do
+				_x(2,'<ProjectConfiguration Include="%s">', vstudio.configname(cfg, arch))
+				_x(3,'<Configuration>%s</Configuration>', vstudio.projectplatform(cfg))
+				_p(3,'<Platform>%s</Platform>', arch)
+				_p(2,'</ProjectConfiguration>')
+			end
 		end
 		_p(1,'</ItemGroup>')
 	end

File src/project/config.lua

 			end
 		end	
 
-		if not cfg.links then print(debug.traceback()) end
-		
 		for _, link in ipairs(cfg.links) do
 			local item
 
 						item = path.rebase(config.getlinkinfo(prjcfg).fullpath, 
 						                   project.getlocation(prjcfg.project), 
 						                   project.getlocation(cfg.project))
-						if item == "directory" then
+						if part == "directory" then
 							item = path.getdirectory(item)
 						end
 					end

File src/project/oven.lua

 --
 
 	function oven.merge(cfg, block, filterField)
+		if block.removes then
+			oven.remove(cfg, block.removes, filterField)
+		end
+		
 		if filterField then
 			if block[filterField] then
 				oven.mergefield(cfg, filterField, block[filterField])
 			end
 		end
 		
-		if block.removes then
-			oven.remove(cfg, block.removes, filterField)
-		end
-		
 		-- remember the container object (solution, project, etc.)
 		cfg[type(block)] = block
 		
 
 	function oven.mergetables(original, additions)
 		for _, item in ipairs(additions) do
-			-- prevent duplicates
-			if not original[item] then
-				original[item] = item
-				table.insert(original, item)
+			-- if the item is already in the list, remove it. This allows a
+			-- later configuration block (i.e. a project) to override the
+			-- ordering of values from an earlier block (i.e. a solution).
+			-- Could be a performance hit; have to wait and see.
+			if original[item] then
+				local i = table.indexof(original, item)
+				table.remove(original, i)
 			end
+			original[item] = item
+			table.insert(original, item)
 		end
 		return original
 	end

File src/project/project.lua

 		-- prevent any default system setting from influencing configurations
 		result.system = nil
 		
-		-- create a map between solution and project configurations
-		local cfglist, cfgmap = project.bakeconfigmap(result)
-		result.cfglist = cfglist
-		result.cfgmap = cfgmap
+		-- apply any mappings to the project's configuration set
+		result.cfglist = project.bakeconfigmap(result)
 
 		-- bake all configurations contained by the project
 		local configs = {}
-		for _, pairing in ipairs(cfglist) do
+		for _, pairing in ipairs(result.cfglist) do
 			local buildcfg = pairing[1]
 			local platform = pairing[2]
 			local cfg = project.bakeconfig(result, buildcfg, platform)
 --
 
 	function project.bakeconfigmap(prj)
-		-- apply an individual config map entry to a build cfg + platform pair
-		function applymap(pairing, patterns, replacements)
-			-- does this pattern match any part of the pair?
-			for i = 1, #pairing do
-				local matched = true
-				for j = 1, #patterns do
-					if pairing[i] ~= patterns[j] then
-						matched = false
-					end
-				end
-				
-				-- yes, replace one or more parts (with a copy)
-				if matched then
-					local result
-					if #patterns == 1 and #replacements == 1 then
-						result = { pairing[1], pairing[2] }
-						result[i] = replacements[1]
-					else
-						result = { replacements[1], replacements[2] }
-					end
-					return result
-				end
-			end
-			
-			-- no, return the original pair
-			return pairing
+		-- Apply any mapping tables to the project's initial configuration set,
+		-- which includes configurations inherited from the solution. These rules
+		-- may cause configurations to be added ore removed from the project.
+		local configs = table.fold(prj.configurations or {}, prj.platforms or {})
+		for i, cfg in ipairs(configs) do
+			configs[i] = project.mapconfig(prj, cfg[1], cfg[2])
 		end
 		
-		-- pair up the project's original list of build cfgs and platforms
-		local slncfgs = table.fold(prj.configurations or {}, prj.platforms or {})
-		
-		-- apply the set of mappings
-		local prjcfgs = {}
-		for patterns, replacements in pairs(prj.configmap or {}) do
-			if type(patterns) ~= "table" then
-				patterns = { patterns }
-			end
-			
-			local count = #slncfgs
-			for i = 1, count do
-				prjcfgs[i] = applymap(prjcfgs[i] or slncfgs[i], patterns, replacements)
-			end
-		end
-
-		-- if there was no configuration map, then project configs will be empty,
-		-- and I can just use the solution level lists for this project
-		if #prjcfgs == 0 then
-			return slncfgs
-		end
-		
-		-- split the result back into separate build configuration and platform
-		-- lists, removing any duplicates along the way. Storing the insertion
-		-- index of each value gives a key into the final list later
+		-- walk through the result and remove duplicates
 		local buildcfgs = {}
 		local platforms = {}
 		
-		for _, pairing in ipairs(prjcfgs) do
+		for _, pairing in ipairs(configs) do
 			local buildcfg = pairing[1]
 			local platform = pairing[2]
-						
-			if not buildcfgs[buildcfg] then
-				buildcfgs[buildcfg] = #buildcfgs
+			
+			if not table.contains(buildcfgs, buildcfg) then
 				table.insert(buildcfgs, buildcfg)
 			end
 			
-			if platform and not platforms[platform] then
-				platforms[platform] = #platforms
+			if platform and not table.contains(platforms, platform) then
 				table.insert(platforms, platform)
 			end
 		end
 
 		-- merge these canonical lists back into pairs for the final result
-		local result = table.fold(buildcfgs, platforms)
-		
-		-- finally, build a map from the original, solution-facing configs
-		-- to these results
-		local map = {}
-		for i, slncfg in ipairs(slncfgs) do
-			local prjcfg = prjcfgs[i]
-			
-			-- figure out where this project cfg appears in the result list
-			local index = buildcfgs[prjcfg[1]]
-			if #platforms > 0 then
-				local platformIndex = platforms[prjcfg[2] or platforms[1]]
-				index = (index * #platforms) + platformIndex
-			end
-			index = index + 1
-			
-			-- add an entry to the map point to this result
-			local key = slncfg[1] .. (slncfg[2] or "")
-			map[key] = result[index]
-		end
-		
-		return result, map
+		configs = table.fold(buildcfgs, platforms)	
+		return configs
 	end
 
 
 			prj = project.bake(prj, prj.solution)
 		end
 	
+		-- if no build configuration is specified, return the "root" project
+		-- configurations, which includes all configuration values that
+		-- weren't set with a specific configuration filter
 		if not buildcfg then
 			return prj
 		end
 		
+		-- apply any configuration mappings
+		local pairing = project.mapconfig(prj, buildcfg, platform)
+		buildcfg = pairing[1]
+		platform = pairing[2]
+
+		-- if the project has a platforms list, and the solution does
+		-- not, default to the first project platform
+		platform = platform or prj.platforms[1]
+		
+		-- look up and return the associated config		
 		local key = (buildcfg or "*") .. (platform or "")
 		return prj.configs[key]
 	end
 
 
 --
--- Given a solution-level build configuration and platform, returns the 
--- corresponding project configuration, or nil if no such configuration exists.
+-- Given a build config/platform pairing, applies any project configuration maps
+-- and returns a new (or the same) pairing.
 --
 
 	function project.mapconfig(prj, buildcfg, platform)
-		if prj.cfgmap then
-			local cfg = prj.cfgmap[buildcfg .. (platform or "")]
-			buildcfg = cfg[1]
-			platform = cfg[2]
+		local pairing = { buildcfg, platform }
+		
+		for patterns, replacements in pairs(prj.configmap or {}) do
+			if type(patterns) ~= "table" then
+				patterns = { patterns }
+			end
+			
+			-- does this pattern match any part of the pair?
+			for i = 1, #pairing do
+				local matched = true
+				for j = 1, #patterns do
+					if pairing[i] ~= patterns[j] then
+						matched = false
+					end
+				end
+
+				-- yes, replace one or more parts (with a copy)
+				if matched then
+					if #patterns == 1 and #replacements == 1 then
+						result = { pairing[1], pairing[2] }
+						pairing[i] = replacements[1]
+					else
+						pairing = { replacements[1], replacements[2] }
+					end
+
+					return pairing
+				end
+			end			
 		end
-		return project.getconfig(prj, buildcfg, platform)
+	
+		return pairing
 	end
+

File src/tools/gcc.lua

 
 
 --
+-- Decorate defines for the GCC command line.
+--
+
+	function gcc.getdefines(defines)
+		local result = {}
+		for _, define in ipairs(defines) do
+			table.insert(result, '-D' .. define)
+		end
+		return result
+	end
+
+
+--
+-- Decorate include file search paths for the GCC command line.
+--
+
+	function gcc.getincludedirs(dirs)
+		local result = {}
+		for _, dir in ipairs(dirs) do
+			table.insert(result, "-I" .. dir)
+		end
+		return result
+	end
+
+
+--
 -- Return a list of LDFLAGS for a specific configuration.
 --
 
 	function gcc.getldflags(cfg)
 		local flags = {}
 		
+		-- Scan the list of linked libraries. If any are referenced with
+		-- paths, add those to the list of library search paths
+		for _, dir in ipairs(config.getlinks(cfg, "all", "directory")) do
+			table.insert(flags, '-L' .. dir)
+		end
+		
 		if not cfg.flags.Symbols then
 			-- OS X has a bug, see http://lists.apple.com/archives/Darwin-dev/2006/Sep/msg00084.html
 			if cfg.system == premake.MACOSX then

File tests/actions/make/solution/test_default_config.lua

+--
+-- tests/actions/make/test_default_config.lua
+-- Validate generation of default configuration block for makefiles.
+-- Copyright (c) 2012 Jason Perkins and the Premake project
+--
+
+	T.make_default_config = {}
+	local suite = T.make_default_config
+	local make = premake.make
+
+
+--
+-- Setup/teardown
+--
+
+	local sln, prj
+
+	function suite.setup()
+		sln = test.createsolution()
+	end
+
+	local function prepare()
+		prj = premake.solution.getproject_ng(sln, 1)
+		make.defaultconfig(prj)
+	end
+
+
+--
+-- Verify the handling of the default setup: Debug and Release, no platforms.
+--
+
+	function suite.defaultsToFirstBuildCfg_onNoPlatforms()
+		prepare()
+		test.capture [[
+ifndef config
+  config=debug
+endif
+		]]
+	end
+
+
+--
+-- Verify handling of build config/platform combination.
+--
+
+	function suite.defaultsToFirstPairing_onPlatforms()
+		platforms { "Win32", "Win64" }
+		prepare()
+		test.capture [[
+ifndef config
+  config=debug_win32
+endif
+		]]
+	end
+
+
+--
+-- If the project excludes a solution build cfg, it should be skipped
+-- over as the default config as well.
+--
+
+	function suite.usesFirstValidPairing_onExcludedConfig()
+		platforms { "Win32", "Win64" }
+		removeconfigurations { "Debug" }
+		prepare()
+		test.capture [[
+ifndef config
+  config=release_win32
+endif
+		]]
+	end

File tests/actions/make/solution/test_help_rule.lua

+--
+-- tests/actions/make/test_help_rule.lua
+-- Validate generation of help rule and configurations list.
+-- Copyright (c) 2012 Jason Perkins and the Premake project
+--
+
+	T.make_help_rule = {}
+	local suite = T.make_help_rule
+	local make = premake.make
+	local solution = premake.solution
+
+
+--
+-- Setup/teardown
+--
+
+	local sln, prj
+
+	function suite.setup()
+		sln = test.createsolution()
+	end
+
+	local function prepare()
+		sln = solution.bake(sln)
+		make.helprule(sln)
+	end
+
+
+--
+-- Start with the default Debug and Release setup.
+--
+
+	function suite.looksOkay_onDefaultSetup()
+		prepare()
+		test.capture [[
+help:
+	@echo "Usage: make [config=name] [target]"
+	@echo ""
+	@echo "CONFIGURATIONS:"
+	@echo "  debug"
+	@echo "  release"
+		]]
+	end

File tests/actions/make/test_default_config.lua

---
--- tests/actions/make/test_default_config.lua
--- Validate generation of default configuration block for makefiles.
--- Copyright (c) 2012 Jason Perkins and the Premake project
---
-
-	T.make_default_config = {}
-	local suite = T.make_default_config
-	local make = premake.make
-
-
---
--- Setup/teardown
---
-
-	local sln, prj
-
-	function suite.setup()
-		sln = test.createsolution()
-	end
-
-	local function prepare()
-		prj = premake.solution.getproject_ng(sln, 1)
-		make.defaultconfig(prj)
-	end
-
-
---
--- Verify the handling of the default setup: Debug and Release, no platforms.
---
-
-	function suite.defaultsToFirstBuildCfg_onNoPlatforms()
-		prepare()
-		test.capture [[
-ifndef config
-  config=debug
-endif
-		]]
-	end
-
-
---
--- Verify handling of build config/platform combination.
---
-
-	function suite.defaultsToFirstPairing_onPlatforms()
-		platforms { "Win32", "Win64" }
-		prepare()
-		test.capture [[
-ifndef config
-  config=debug_win32
-endif
-		]]
-	end
-
-
---
--- If the project excludes a solution build cfg, it should be skipped
--- over as the default config as well.
---
-
-	function suite.defaultsToFirstPairing_onPlatforms()
-		platforms { "Win32", "Win64" }
-		removeconfigurations { "Debug" }
-		prepare()
-		test.capture [[
-ifndef config
-  config=release_win32
-endif
-		]]
-	end
-
-
---
--- If the project excludes a solution platform, it should be skipped
--- over as the default config as well.
---
-
-	function suite.defaultsToFirstPairing_onPlatforms()
-		platforms { "Win32", "Win64" }
-		removeplatforms { "Win32" }
-		prepare()
-		test.capture [[
-ifndef config
-  config=debug_win64
-endif
-		]]
-	end
-
-	

File tests/actions/make/test_help_rule.lua

---
--- tests/actions/make/test_help_rule.lua
--- Validate generation of help rule and configurations list.
--- Copyright (c) 2012 Jason Perkins and the Premake project
---
-
-	T.make_help_rule = {}
-	local suite = T.make_help_rule
-	local make = premake.make
-	local solution = premake.solution
-
-
---
--- Setup/teardown
---
-
-	local sln, prj
-
-	function suite.setup()
-		sln = test.createsolution()
-	end
-
-	local function prepare()
-		sln = solution.bake(sln)
-		make.helprule(sln)
-	end
-
-
---
--- Start with the default Debug and Release setup.
---
-
-	function suite.looksOkay_onDefaultSetup()
-		prepare()
-		test.capture [[
-help:
-	@echo "Usage: make [config=name] [target]"
-	@echo ""
-	@echo "CONFIGURATIONS:"
-	@echo "  debug"
-	@echo "  release"
-		]]
-	end

File tests/actions/make/test_make_escaping.lua

 --
 -- tests/actions/make/test_make_escaping.lua
 -- Validate the escaping of literal values in Makefiles.
--- Copyright (c) 2010 Jason Perkins and the Premake project
+-- Copyright (c) 2010-2012 Jason Perkins and the Premake project
 --
 
 	T.make_escaping = { }
 	local suite = T.make_escaping
+	local make = premake.make
 
 
 	function suite.Escapes_Spaces()
-		test.isequal("Program\\ Files", _MAKE.esc("Program Files"))
+		test.isequal("Program\\ Files", make.esc("Program Files"))
 	end
 
 	function suite.Escapes_Backslashes()
-		test.isequal("Program\\\\Files", _MAKE.esc("Program\\Files"))
+		test.isequal("Program\\\\Files", make.esc("Program\\Files"))
 	end
 	
 	function suite.Escapes_Parens()
-		test.isequal("Debug\\(x86\\)", _MAKE.esc("Debug(x86)"))
+		test.isequal("Debug\\(x86\\)", make.esc("Debug(x86)"))
 	end
 	
 	function suite.DoesNotEscape_ShellReplacements()
-		test.isequal("-L$(NVSDKCUDA_ROOT)/C/lib", _MAKE.esc("-L$(NVSDKCUDA_ROOT)/C/lib"))
+		test.isequal("-L$(NVSDKCUDA_ROOT)/C/lib", make.esc("-L$(NVSDKCUDA_ROOT)/C/lib"))
 	end
 	
 	function suite.CanEscape_ShellReplacementCapturesShortest()
-		test.isequal("a\\(x\\)b$(ROOT)c\\(y\\)d", _MAKE.esc("a(x)b$(ROOT)c(y)d"))
+		test.isequal("a\\(x\\)b$(ROOT)c\\(y\\)d", make.esc("a(x)b$(ROOT)c(y)d"))
 	end
 

File tests/actions/vstudio/vc200x/test_compiler_block.lua

 				RuntimeLibrary="2"
 				EnableFunctionLevelLinking="true"
 				UsePrecompiledHeader="0"
+				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				WarningLevel="3"
-				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				DebugInformationFormat="0"
 			/>
 		]]
 				RuntimeLibrary="3"
 				EnableFunctionLevelLinking="true"
 				UsePrecompiledHeader="0"
+				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				WarningLevel="3"
-				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				DebugInformationFormat="4"
 			/>
 		]]
 				RuntimeLibrary="2"
 				EnableFunctionLevelLinking="true"
 				UsePrecompiledHeader="0"
+				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				WarningLevel="3"
-				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				DebugInformationFormat="3"
 			/>
 		]]
 				RuntimeLibrary="3"
 				EnableFunctionLevelLinking="true"
 				UsePrecompiledHeader="0"
+				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				WarningLevel="3"
-				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				DebugInformationFormat="1"
 			/>
 		]]
 				EnableFunctionLevelLinking="true"
 				UsePrecompiledHeader="2"
 				PrecompiledHeaderThrough="common.h"
+				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				WarningLevel="3"
-				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				DebugInformationFormat="0"
 			/>
 		]]
 				EnableFunctionLevelLinking="true"
 				FloatingPointModel="2"
 				UsePrecompiledHeader="0"
+				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				WarningLevel="3"
-				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				DebugInformationFormat="0"
 			/>
 		]]
 				EnableFunctionLevelLinking="true"
 				FloatingPointModel="1"
 				UsePrecompiledHeader="0"
+				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				WarningLevel="3"
-				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				DebugInformationFormat="0"
 			/>
 		]]
 				RuntimeLibrary="2"
 				EnableFunctionLevelLinking="true"
 				UsePrecompiledHeader="0"
+				ProgramDataBaseFileName="$(OutDir)\foob.pdb"
 				WarningLevel="3"
-				ProgramDataBaseFileName="$(OutDir)\foob.pdb"
 				DebugInformationFormat="0"
 			/>
 		]]
 				RuntimeLibrary="3"
 				EnableFunctionLevelLinking="true"
 				UsePrecompiledHeader="0"
+				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				WarningLevel="3"
-				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				DebugInformationFormat="4"
 			/>
 		]]
 				RuntimeLibrary="2"
 				EnableFunctionLevelLinking="true"
 				UsePrecompiledHeader="0"
+				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				WarningLevel="3"
-				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				DebugInformationFormat="0"
 				CompileAs="1"
 			/>
 				RuntimeLibrary="3"
 				EnableFunctionLevelLinking="true"
 				UsePrecompiledHeader="0"
+				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				WarningLevel="3"
-				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				DebugInformationFormat="4"
 			/>
 		]]
 				RuntimeLibrary="2"
 				EnableFunctionLevelLinking="true"
 				UsePrecompiledHeader="0"
+				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				WarningLevel="4"
-				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				DebugInformationFormat="0"
 			/>
 		]]
 				RuntimeLibrary="2"
 				EnableFunctionLevelLinking="true"
 				UsePrecompiledHeader="0"
+				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				WarningLevel="3"
 				WarnAsError="true"
-				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				DebugInformationFormat="0"
 			/>
 		]]
 				RuntimeLibrary="2"
 				EnableFunctionLevelLinking="true"
 				UsePrecompiledHeader="0"
+				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				WarningLevel="0"
-				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				DebugInformationFormat="0"
 			/>
 		]]
 				RuntimeLibrary="2"
 				EnableFunctionLevelLinking="true"
 				UsePrecompiledHeader="0"
+				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				WarningLevel="3"
 				Detect64BitPortabilityProblems="true"
-				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				DebugInformationFormat="0"
 			/>
 		]]
 				RuntimeLibrary="2"
 				EnableFunctionLevelLinking="true"
 				UsePrecompiledHeader="0"
+				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				WarningLevel="0"
-				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				DebugInformationFormat="0"
 			/>
 		]]
 				RuntimeLibrary="2"
 				EnableFunctionLevelLinking="true"
 				UsePrecompiledHeader="0"
+				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				WarningLevel="3"
-				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				DebugInformationFormat="0"
 			/>
 		]]

File tests/actions/vstudio/vc200x/test_external_compiler.lua

 		test.capture [[
 			<Tool
 				Name="VCCLCompilerTool"
+				AdditionalOptions="-Xc+=exceptions -Xc+=rtti"
 				UsePrecompiledHeader="0"
-				AdditionalOptions="-Xc+=exceptions -Xc+=rtti"
 				ProgramDataBaseFileName="$(OutDir)\MyProject.pdb"
 				DebugInformationFormat="0"
 				CompileAs="0"
 		test.capture [[
 			<Tool
 				Name="VCCLCompilerTool"
-				UsePrecompiledHeader="0"
 				AdditionalOptions="-Xc+=exceptions -Xc+=rtti"
 				AdditionalIncludeDirectories="..\include;include"
+				UsePrecompiledHeader="0"
 		]]
 	end

File tests/actions/vstudio/vc200x/test_manifest_block.lua

File contents unchanged.

File tests/actions/vstudio/vc200x/test_project.lua

 	ProjectGUID="{AE61726D-187C-E440-BD07-2556188A6565}"
 	RootNamespace="MyProject"
 	Keyword="Win32Proj"
+	TargetFrameworkVersion="0"
 	>
 		]]
 	end
 	Name="MyProject"
 	ProjectGUID="{AE61726D-187C-E440-BD07-2556188A6565}"
 	Keyword="Win32Proj"
-	>
 		]]
 	end
 
 	ProjectGUID="{AE61726D-187C-E440-BD07-2556188A6565}"
 	RootNamespace="MyProject"
 	Keyword="ManagedCProj"
-	>
 		]]
 	end
 

File tests/actions/vstudio/vc2010/test_project_configs.lua

 			<Configuration>Debug x32</Configuration>
 			<Platform>Win32</Platform>
 		</ProjectConfiguration>
+		<ProjectConfiguration Include="Debug x32|x64">
+			<Configuration>Debug x32</Configuration>
+			<Platform>x64</Platform>
+		</ProjectConfiguration>
+		<ProjectConfiguration Include="Debug x64|Win32">
+			<Configuration>Debug x64</Configuration>
+			<Platform>Win32</Platform>
+		</ProjectConfiguration>
 		<ProjectConfiguration Include="Debug x64|x64">
 			<Configuration>Debug x64</Configuration>
 			<Platform>x64</Platform>

File tests/oven/test_lists.lua

 		prj = project("MyProject")
 		defines { "PROJECT", "DUPLICATE" }
 		cfg = oven.bake(prj, sln, {"Debug"})
-		test.isequal("SOLUTION|DUPLICATE|PROJECT", table.concat(cfg.defines, "|"))
+		test.isequal("SOLUTION|PROJECT|DUPLICATE", table.concat(cfg.defines, "|"))
 	end

File tests/oven/test_removes.lua

 
 	function suite.remove_onExactValueMatch()
 		flags { "Symbols", "Optimize", "NoRTTI" }
+		configuration {}
 		removeflags "Optimize"
 		prepare()
 		test.isequal({ "Symbols", "NoRTTI" }, cfg.flags)
 
 	function suite.remove_onMultipleValues()
 		flags { "Symbols", "NoExceptions", "Optimize", "NoRTTI" }
+		configuration {}
 		removeflags { "NoExceptions", "NoRTTI" }
 		prepare()
 		test.isequal({ "Symbols", "Optimize" }, cfg.flags)
 
 	function suite.remove_onWildcard()
 		defines { "WIN32", "WIN64", "LINUX", "MACOSX" }
+		configuration {}
 		removedefines { "WIN*" }
 		prepare()
 		test.isequal({ "LINUX", "MACOSX" }, cfg.defines)
 
 	function suite.remove_onExactValueMatch()
 		flags { "Symbols", "Optimize", "NoRTTI" }
+		configuration {}
 		removeflags "Optimize"
 		prepare()
 		test.isnil(cfg.flags.Optimize)
 
 	function suite.remove_onFileField()
 		files { "hello.c", "goodbye.c" }
+		configuration {}
 		removefiles { "goodbye.c" }
 		prepare()
 		test.isequal(path.join(os.getcwd(), "hello.c"), table.concat(cfg.files))

File tests/premake4.lua

 	dofile("project/test_filtering.lua")
 	dofile("project/test_getconfig.lua")
 	dofile("project/test_hasconfig.lua")
-	dofile("project/test_mapconfig.lua")
 	dofile("project/test_vpaths.lua")
 
 	-- Configuration object tests
 	dofile("actions/vstudio/vc2010/test_resource_compile.lua")
 
 	-- Makefile tests
-	dofile("actions/make/test_default_config.lua")
-	dofile("actions/make/test_help_rule.lua")
+	dofile("actions/make/solution/test_default_config.lua")
+	dofile("actions/make/solution/test_help_rule.lua")
 	dofile("actions/make/test_make_escaping.lua")
 	dofile("actions/make/test_make_pch.lua")
 	dofile("actions/make/test_make_linking.lua")

File tests/project/test_eachconfig.lua

 		sln = solution("MySolution")
 	end
 
-	local function prepare()
+	local function prepare(buildcfgs)
 		project("MyProject")
+		if buildcfgs then
+			configurations ( buildcfgs )
+		end
 		prj = premake.solution.getproject_ng(sln, 1)
 		for cfg in premake5.project.eachconfig(prj, field) do
 			_p(2,'%s:%s', cfg.buildcfg or "", cfg.platform or "")
 		Release:
 		]]
 	end
+
 	
+--
+-- If there is overlap in the solution and project configuration lists,
+-- the ordering at the project level should be maintained to avoid
+-- unnecessarily dirtying the project file.
+--
+
+	function suite.maintainsProjectOrdering_onSolutionOverlap()
+		configurations { "Debug", "Release" }
+		prepare { "Debug", "Development", "Profile", "Release" }
+		test.capture [[
+		Debug:
+		Development:
+		Profile:
+		Release:
+		]]
+	end
+

File tests/project/test_getconfig.lua

 		sln, prj = test.createsolution()
 	end
 
-	local function prepare()
-		cfg = premake.project.getconfig(prj, "Debug")
+	local function prepare(buildcfg)
+		buildcfg = buildcfg or "Debug"
+		cfg = premake.project.getconfig(prj, buildcfg)
+	end
+
+
+--
+-- When no configuration is specified in the project, the solution
+-- settings should map directly to a configuration object.
+--
+
+	function suite.solutionConfig_onNoProjectConfigs()
+		prepare()
+		test.isequal("Debug", cfg.buildcfg)
+	end
+
+
+--
+-- If a project configuration mapping exists, it should be taken into
+-- account when fetching the configuration object.
+--
+
+	function suite.appliesCfgMapping_onMappingExists()
+		configmap { ["Debug"] = "Development" }
+		prepare()
+		test.isequal("Development", cfg.buildcfg)
+	end
+
+
+--
+-- If a configuration mapping exists, can also use the mapped value
+-- to fetch the configuration.
+--
+
+	function suite.fetchesMappedCfg_onMappedName()
+		configmap { ["Debug"] = "Development" }
+		prepare("Development")
+		test.isequal("Development", cfg.buildcfg)
+	end
+
+
+--
+-- If the specified configuration has been removed from the project,
+-- then nil should be returned.
+--
+
+	function suite.returnsNil_onRemovedConfig()
+		removeconfigurations { "Debug" }
+		prepare()
+		test.isnil(cfg)
+	end
+
+
+--
+-- If the project has a platforms list, and the solution does not, 
+-- use the first project platform.
+--
+
+	function suite.usesFirstPlatform_onNoSolutionPlatforms()
+		platforms { "x32", "x64" }
+		prepare()
+		test.isequal("x32", cfg.platform)
 	end
 
 
 		prepare()
 		test.isequal("correct", cfg.defines[1])
 	end
+
+
+--
+-- If the configuration doesn't exist in the project, but it can be mapped
+-- from the solution, returned the mapped configuration.
+--
+
+	function suite.returnsMappedConfig_onOtherwiseMissing()
+		removeconfigurations "Debug"
+		configmap { Debug = "Release" }
+		prepare()
+		test.isequal("Release", cfg.buildcfg)
+	end
+
+		

File tests/project/test_mapconfig.lua

---
--- tests/project/test_mapconfig.lua
--- Tests mapping between solution and project configurations.
--- Copyright (c) 2012 Jason Perkins and the Premake project
---
-
-	T.project_mapconfig = { }
-	local suite = T.project_mapconfig
-	local project = premake5.project
-
---
--- Setup and teardown
---
-
-	local sln, prj, cfg
-
-	function suite.setup()
-		sln = test.createsolution()
-	end
-
-	local function prepare()
-		prj = premake.solution.getproject_ng(sln, 1)
-		cfg = project.mapconfig(prj, "Debug")
-	end
-
-
---
--- No mapping should pass right through.
---
-
-	function suite.exactMatch_onNoMapping()
-		prepare()
-		test.isequal("Debug", cfg.buildcfg)
-	end
-
-
---
--- If the value is mapped, the corresponding config should be returned.
---
-
-	function suite.returnsMappedCfg_onMapping()
-		configmap { ["Debug"] = "Development" }
-		prepare()
-		test.isequal("Development", cfg.buildcfg)
-	end
-