Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/windirstat/premake-4.x-stable.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOliver Schneider <oliver@assarbad.net>2022-03-14 01:49:34 +0300
committerOliver Schneider <oliver@assarbad.net>2022-03-14 01:49:34 +0300
commitda97ae64683047a29cdf46e881bdf4ee19096bca (patch)
tree99503e07aa994a66291887bd8b2ac29399558c31
parent338c922ecc544e7ab8533f5853890a6806e6e6cb (diff)
Reviewed and reworked the premake4.lua to make better use of modern VS versionsHEADhg/WDS-build
- Still sticking to VS2005 as the "default" for my release builds for now. - The premake4 behavioral patches moved to the bottom of premake4.lua to improve readbility (most people are stumped by seeing lots of Lua code). So since it doesn't even matter where these go, let's place them at the bottom. --HG-- branch : WDS-build
-rw-r--r--Premake4.vs8.vcproj4
-rw-r--r--premake4.lua769
2 files changed, 384 insertions, 389 deletions
diff --git a/Premake4.vs8.vcproj b/Premake4.vs8.vcproj
index 1a911b2..0e1382e 100644
--- a/Premake4.vs8.vcproj
+++ b/Premake4.vs8.vcproj
@@ -48,7 +48,6 @@
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="false"
- ProgramDataBaseFileName="$(OutDir)\premake4.pdb"
DebugInformationFormat="0"
CompileAs="1"
/>
@@ -135,7 +134,6 @@
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="false"
- ProgramDataBaseFileName="$(OutDir)\premake4.pdb"
DebugInformationFormat="4"
CompileAs="1"
/>
@@ -157,7 +155,6 @@
LinkIncremental="2"
AdditionalLibraryDirectories=""
GenerateDebugInformation="true"
- ProgramDataBaseFileName="$(OutDir)\premake4.pdb"
SubSystem="1"
EntryPointSymbol="mainCRTStartup"
TargetMachine="1"
@@ -220,7 +217,6 @@
UsePrecompiledHeader="0"
WarningLevel="4"
Detect64BitPortabilityProblems="false"
- ProgramDataBaseFileName="$(OutDir)\premake4.pdb"
DebugInformationFormat="0"
CompileAs="1"
/>
diff --git a/premake4.lua b/premake4.lua
index 0d275bc..92719eb 100644
--- a/premake4.lua
+++ b/premake4.lua
@@ -12,292 +12,20 @@
]]
local action = _ACTION or ""
if _OPTIONS["publish"] then
- print "INFO: Creating 'Publish' build solution."
- publish = true
-end
-do
- -- This is mainly to support older premake4 builds
- if not premake.project.getbasename then
- print "Magic happens for old premake4 versions without premake.project.getbasename() ..."
- -- override the function to establish the behavior we'd get after patching Premake to have premake.project.getbasename
- premake.project.getbasename = function(prjname, pattern)
- return pattern:gsub("%%%%", prjname)
- end
- -- obviously we also need to overwrite the following to generate functioning VS solution files
- premake.vstudio.projectfile = function(prj)
- local pattern
- if prj.language == "C#" then
- pattern = "%%.csproj"
- else
- pattern = iif(_ACTION > "vs2008", "%%.vcxproj", "%%.vcproj")
- end
-
- local fname = premake.project.getbasename(prj.name, pattern)
- fname = path.join(prj.location, fname)
- return fname
- end
- -- we simply overwrite the original function on older Premake versions
- premake.project.getfilename = function(prj, pattern)
- local fname = premake.project.getbasename(prj.name, pattern)
- fname = path.join(prj.location, fname)
- return path.getrelative(os.getcwd(), fname)
- end
- end
- -- This is mainly to support older premake4 in which CompileAs did not work
- -- for VS2010 and newer
- if not premake.vstudio.vc2010.individualSourceFile or not premake.vstudio.vc200x.individualSourceFile then
- local vc2010 = premake.vstudio.vc2010
- local vc200x = premake.vstudio.vc200x
- local tree = premake.tree
- print "Magic happens for old premake4 versions faulty CompileAs handling for VS2010 and newer ..."
- -- A boilerplate implementation
- vc200x.individualSourceFile = function(prj, depth, fname, node)
- -- handle file configuration stuff. This needs to be cleaned up and simplified.
- -- configurations are cached, so this isn't as bad as it looks
- for _, cfginfo in ipairs(prj.solution.vstudio_configs) do
- if cfginfo.isreal then
- local cfg = premake.getconfig(prj, cfginfo.src_buildcfg, cfginfo.src_platform)
-
- local usePCH = (not prj.flags.NoPCH and prj.pchsource == node.cfg.name)
- local isSourceCode = path.iscppfile(fname)
- local needsCompileAs = (path.iscfile(fname) ~= premake.project.iscproject(prj))
-
- if usePCH or (isSourceCode and needsCompileAs) then
- _p(depth, '<FileConfiguration')
- _p(depth, '\tName="%s"', cfginfo.name)
- _p(depth, '\t>')
- _p(depth, '\t<Tool')
- _p(depth, '\t\tName="%s"', iif(cfg.system == "Xbox360",
- "VCCLX360CompilerTool",
- "VCCLCompilerTool"))
- if needsCompileAs then
- _p(depth, '\t\tCompileAs="%s"', iif(path.iscfile(fname), 1, 2))
- end
-
- if usePCH then
- if cfg.system == "PS3" then
- local options = table.join(premake.snc.getcflags(cfg),
- premake.snc.getcxxflags(cfg),
- cfg.buildoptions)
- options = table.concat(options, " ");
- options = options .. ' --create_pch="$(IntDir)/$(TargetName).pch"'
- _p(depth, '\t\tAdditionalOptions="%s"', premake.esc(options))
- else
- _p(depth, '\t\tUsePrecompiledHeader="1"')
- end
- end
-
- _p(depth, '\t/>')
- _p(depth, '</FileConfiguration>')
- end
-
- end
- end
- end
- vc200x.Files = function(prj)
- local tr = premake.project.buildsourcetree(prj)
-
- tree.traverse(tr, {
- -- folders are handled at the internal nodes
- onbranchenter = function(node, depth)
- _p(depth, '<Filter')
- _p(depth, '\tName="%s"', node.name)
- _p(depth, '\tFilter=""')
- _p(depth, '\t>')
- end,
-
- onbranchexit = function(node, depth)
- _p(depth, '</Filter>')
- end,
-
- -- source files are handled at the leaves
- onleaf = function(node, depth)
- local fname = node.cfg.name
-
- _p(depth, '<File')
- _p(depth, '\tRelativePath="%s"', path.translate(fname, "\\"))
- _p(depth, '\t>')
- depth = depth + 1
-
- vc200x.individualSourceFile(prj, depth, fname, node)
-
- depth = depth - 1
- _p(depth, '</File>')
- end,
- }, false, 2)
-
- end
- -- A boilerplate implementation
- vc2010.individualSourceFile = function(prj, config_mappings, file)
- local configs = prj.solution.vstudio_configs
- local translatedpath = path.translate(file.name, "\\")
- _p(2,'<ClCompile Include=\"%s\">', translatedpath)
- for _, cfginfo in ipairs(configs) do
- if config_mappings[cfginfo] and translatedpath == config_mappings[cfginfo] then
- _p(3,'<PrecompiledHeader '.. if_config_and_platform() .. '>Create</PrecompiledHeader>', premake.esc(cfginfo.name))
- config_mappings[cfginfo] = nil --only one source file per pch
- end
- end
- if path.iscfile(file.name) ~= premake.project.iscproject(prj) then
- _p(3,'<CompileAs>%s</CompileAs>', iif(path.iscfile(file.name), 'CompileAsC', 'CompileAsCpp'))
- end
- _p(2,'</ClCompile>')
- end
- -- Overriding the function which calls the above
- vc2010.compilerfilesgroup = function(prj)
- local configs = prj.solution.vstudio_configs
- local files = vc2010.getfilegroup(prj, "ClCompile")
- if #files > 0 then
- local config_mappings = {}
- for _, cfginfo in ipairs(configs) do
- local cfg = premake.getconfig(prj, cfginfo.src_buildcfg, cfginfo.src_platform)
- if cfg.pchheader and cfg.pchsource and not cfg.flags.NoPCH then
- config_mappings[cfginfo] = path.translate(cfg.pchsource, "\\")
- end
- end
-
- _p(1,'<ItemGroup>')
- for _, file in ipairs(files) do
- vc2010.individualSourceFile(prj, config_mappings, file)
- end
- _p(1,'</ItemGroup>')
- end
- end
- end
- -- Make UUID generation for filters deterministic
- if os.str2uuid ~= nil then
- local vc2010 = premake.vstudio.vc2010
- vc2010.filteridgroup = function(prj)
- local filters = { }
- local filterfound = false
-
- for file in premake.project.eachfile(prj) do
- -- split the path into its component parts
- local folders = string.explode(file.vpath, "/", true)
- local path = ""
- for i = 1, #folders - 1 do
- -- element is only written if there *are* filters
- if not filterfound then
- filterfound = true
- _p(1,'<ItemGroup>')
- end
-
- path = path .. folders[i]
-
- -- have I seen this path before?
- if not filters[path] then
- local seed = path .. (prj.uuid or "")
- local deterministic_uuid = os.str2uuid(seed)
- filters[path] = true
- _p(2, '<Filter Include="%s">', path)
- _p(3, '<UniqueIdentifier>{%s}</UniqueIdentifier>', deterministic_uuid)
- _p(2, '</Filter>')
- end
-
- -- prepare for the next subfolder
- path = path .. "\\"
- end
- end
-
- if filterfound then
- _p(1,'</ItemGroup>')
- end
- end
- end
- -- Name the project files after their VS version
- local orig_getbasename = premake.project.getbasename
- premake.project.getbasename = function(prjname, pattern)
- -- The below is used to insert the .vs(8|9|10|11|12|14|15|16|17) into the file names for projects and solutions
- if _ACTION then
- name_map = {vs2005 = "vs8", vs2008 = "vs9", vs2010 = "vs10", vs2012 = "vs11", vs2013 = "vs12", vs2015 = "vs14", vs2017 = "vs15", vs2019 = "vs16", vs2022 = "vs17"}
- if name_map[_ACTION] then
- pattern = pattern:gsub("%%%%", "%%%%." .. name_map[_ACTION])
- else
- pattern = pattern:gsub("%%%%", "%%%%." .. _ACTION)
- end
- end
- return orig_getbasename(prjname, pattern)
- end
- -- Older versions of Premake4 fail to set the proper entry point, although they could simply let it out entirely ...
- local orig_vc2010_link = premake.vstudio.vc2010.link
- premake.vstudio.vc2010.link = function(cfg)
- if cfg.flags and cfg.flags.Unicode then
- io.capture()
- orig_vc2010_link(cfg)
- local captured = io.endcapture()
- captured = captured:gsub("(<EntryPointSymbol>)(mainCRTStartup)", "%1w%2")
- io.write(captured)
- else
- orig_vc2010_link(cfg)
- end
- end
- local orig_vc200x_VCLinkerTool = premake.vstudio.vc200x.VCLinkerTool
- premake.vstudio.vc200x.VCLinkerTool = function(cfg)
- if cfg.flags and cfg.flags.Unicode then
- io.capture()
- orig_vc200x_VCLinkerTool(cfg)
- local captured = io.endcapture()
- captured = captured:gsub('(EntryPointSymbol=")(mainCRTStartup)', "%1w%2")
- io.write(captured)
- else
- orig_vc200x_VCLinkerTool(cfg)
- end
- end
- premake.vstudio.vc200x.toolmap.VCLinkerTool = premake.vstudio.vc200x.VCLinkerTool
- -- Make sure we can generate XP-compatible projects for newer Visual Studio versions
- local orig_vc2010_configurationPropertyGroup = premake.vstudio.vc2010.configurationPropertyGroup
- premake.vstudio.vc2010.configurationPropertyGroup = function(cfg, cfginfo)
- io.capture()
- orig_vc2010_configurationPropertyGroup(cfg, cfginfo)
- local captured = io.endcapture()
- local toolsets = { vs2012 = "v110", vs2013 = "v120", vs2015 = "v140", vs2017 = "v141" }
- local toolset = toolsets[_ACTION]
- if toolset then
- if _OPTIONS["xp"] then
- toolset = toolset .. "_xp"
- captured = captured:gsub("(</PlatformToolset>)", "_xp%1")
- end
- end
- io.write(captured)
- end
- -- Override the object directory paths ... don't make them "unique" inside premake4
- local orig_gettarget = premake.gettarget
- premake.gettarget = function(cfg, direction, pathstyle, namestyle, system)
- local r = orig_gettarget(cfg, direction, pathstyle, namestyle, system)
- if (cfg.objectsdir) and (cfg.objdir) then
- cfg.objectsdir = cfg.objdir
- end
- return r
- end
- -- Silently suppress generation of the .user files ...
- local orig_generate = premake.generate
- premake.generate = function(obj, filename, callback)
- if filename:find('.vcproj.user') or filename:find('.vcxproj.user') then
- return
- end
- orig_generate(obj, filename, callback)
- end
- -- We want to output the file with UTF-8 BOM
- local orig_vc2010_header = premake.vstudio.vc2010.header
- premake.vstudio.vc2010.header = function(targets)
- io.capture()
- orig_vc2010_header(targets)
- local captured = io.endcapture()
- io.write("\239\187\191")
- io.write(captured)
- end
+ print "INFO: Creating 'Publish' build solution."
+ publish = true
end
local function transformMN(input) -- transform the macro names for older Visual Studio versions
- local new_map = { vs2002 = 0, vs2003 = 0, vs2005 = 0, vs2008 = 0 }
- local replacements = { Platform = "PlatformName", Configuration = "ConfigurationName" }
- if new_map[action] ~= nil then
- for k,v in pairs(replacements) do
- if input:find(k) then
- input = input:gsub(k, v)
- end
- end
- end
- return input
+ local new_map = { vs2002 = 0, vs2003 = 0, vs2005 = 0, vs2008 = 0 }
+ local replacements = { Platform = "PlatformName", Configuration = "ConfigurationName" }
+ if new_map[action] ~= nil then
+ for k,v in pairs(replacements) do
+ if input:find(k) then
+ input = input:gsub(k, v)
+ end
+ end
+ end
+ return input
end
--
-- Define the project. Put the release configuration first so it will be the
@@ -306,82 +34,82 @@ end
--
solution "Premake4"
- configurations { "Release", "Debug", "Publish" }
- location ( _OPTIONS["to"] )
-
- project "Premake4"
- local int_dir = "intermediate/" .. action .. "_$(" .. transformMN("Platform") .. ")_$(" .. transformMN("Configuration") .. ")"
- uuid "7F000221-EACC-2F4F-A07F-6A5D34AF10D0"
- targetname "premake4"
- language "C"
- kind "ConsoleApp"
- objdir (int_dir)
- flags { "No64BitChecks", "ExtraWarnings", "StaticRuntime" }
- includedirs { "src/host/lua-5.1.4/src" }
- defines { "USE_KECCAK" }
-
- files
- {
- "*.txt", "**.lua",
- "src/**.h", "src/**.c",
- "src/host/scripts.c"
- }
-
- excludes
- {
- "src/premake.lua",
- "src/host/lua-5.1.4/src/lua.c",
- "src/host/lua-5.1.4/src/luac.c",
- "src/host/lua-5.1.4/src/print.c",
- "src/host/lua-5.1.4/**.lua",
- "src/host/lua-5.1.4/etc/*.c",
- "src/host/hgtip.h",
- "packages/**",
- "samples/**",
- "tests/**",
- }
-
- configuration "Debug"
- targetdir "bin/debug"
- defines "_DEBUG"
- flags { "Symbols" }
-
- configuration "Release or Publish"
- targetdir "bin/release"
- defines "NDEBUG"
- flags { "OptimizeSize" }
-
- configuration "vs*"
- defines { "_CRT_SECURE_NO_WARNINGS" }
-
- configuration "vs2005"
- defines {"_CRT_SECURE_NO_DEPRECATE" }
-
- configuration "windows"
- links { "ole32" }
- files { "src/host/premake4.rc" }
-
- configuration {"windows", "Publish"}
- defines { "HAVE_HGTIP", "PREMAKE_VERSION=4.4-wds"}
-
- configuration "linux or bsd"
- defines { "LUA_USE_POSIX", "LUA_USE_DLOPEN" }
- links { "m" }
- linkoptions { "-rdynamic" }
-
- configuration "linux"
- links { "dl" }
-
- configuration "macosx"
- defines { "LUA_USE_MACOSX" }
- links { "CoreServices.framework" }
-
- configuration { "macosx", "gmake" }
- buildoptions { "-mmacosx-version-min=10.4" }
- linkoptions { "-mmacosx-version-min=10.4" }
-
- configuration { "solaris" }
- linkoptions { "-Wl,--export-dynamic" }
+ configurations { "Release", "Debug", "Publish" }
+ location ( _OPTIONS["to"] )
+
+ project "Premake4"
+ local int_dir = "intermediate/" .. action .. "_$(" .. transformMN("Platform") .. ")_$(" .. transformMN("Configuration") .. ")"
+ uuid "7F000221-EACC-2F4F-A07F-6A5D34AF10D0"
+ targetname "premake4"
+ language "C"
+ kind "ConsoleApp"
+ objdir (int_dir)
+ flags { "No64BitChecks", "ExtraWarnings", "StaticRuntime" }
+ includedirs { "src/host/lua-5.1.4/src" }
+ defines { "USE_KECCAK" }
+
+ files
+ {
+ "*.txt", "**.lua",
+ "src/**.h", "src/**.c",
+ "src/host/scripts.c"
+ }
+
+ excludes
+ {
+ "src/premake.lua",
+ "src/host/lua-5.1.4/src/lua.c",
+ "src/host/lua-5.1.4/src/luac.c",
+ "src/host/lua-5.1.4/src/print.c",
+ "src/host/lua-5.1.4/**.lua",
+ "src/host/lua-5.1.4/etc/*.c",
+ "src/host/hgtip.h",
+ "packages/**",
+ "samples/**",
+ "tests/**",
+ }
+
+ configuration "Debug"
+ targetdir "bin/debug"
+ defines "_DEBUG"
+ flags { "Symbols" }
+
+ configuration "Release or Publish"
+ targetdir "bin/release"
+ defines "NDEBUG"
+ flags { "OptimizeSize" }
+
+ configuration "vs*"
+ defines { "_CRT_SECURE_NO_WARNINGS" }
+
+ configuration "vs2005"
+ defines {"_CRT_SECURE_NO_DEPRECATE" }
+
+ configuration "windows"
+ links { "ole32" }
+ files { "src/host/premake4.rc" }
+
+ configuration {"windows", "Publish"}
+ defines { "HAVE_HGTIP", "PREMAKE_VERSION=4.4-wds"}
+
+ configuration "linux or bsd"
+ defines { "LUA_USE_POSIX", "LUA_USE_DLOPEN" }
+ links { "m" }
+ linkoptions { "-rdynamic" }
+
+ configuration "linux"
+ links { "dl" }
+
+ configuration "macosx"
+ defines { "LUA_USE_MACOSX" }
+ links { "CoreServices.framework" }
+
+ configuration { "macosx", "gmake" }
+ buildoptions { "-mmacosx-version-min=10.4" }
+ linkoptions { "-mmacosx-version-min=10.4" }
+
+ configuration { "solaris" }
+ linkoptions { "-Wl,--export-dynamic" }
@@ -389,10 +117,10 @@ solution "Premake4"
-- A more thorough cleanup.
--
- if _ACTION == "clean" then
- os.rmdir("bin")
- os.rmdir("build")
- end
+ if _ACTION == "clean" then
+ os.rmdir("bin")
+ os.rmdir("build")
+ end
@@ -402,15 +130,15 @@ solution "Premake4"
-- in preparation for deployment.
--
- newoption {
- trigger = "to",
- value = "path",
- description = "Set the output location for the generated files"
- }
- newoption {
- trigger = "xp",
- description = "Enable XP-compatible build for newer Visual Studio versions."
- }
+ newoption {
+ trigger = "to",
+ value = "path",
+ description = "Set the output location for the generated files"
+ }
+ newoption {
+ trigger = "xp",
+ description = "Enable XP-compatible build for newer Visual Studio versions."
+ }
@@ -420,13 +148,13 @@ solution "Premake4"
-- a release build.
--
- dofile("scripts/embed.lua")
+ dofile("scripts/embed.lua")
- newaction {
- trigger = "embed",
- description = "Embed scripts in scripts.c; required before release builds",
- execute = doembed
- }
+ newaction {
+ trigger = "embed",
+ description = "Embed scripts in scripts.c; required before release builds",
+ execute = doembed
+ }
--
@@ -435,10 +163,281 @@ solution "Premake4"
--
- dofile("scripts/release.lua")
+ dofile("scripts/release.lua")
- newaction {
- trigger = "release",
- description = "Prepare a new release (incomplete)",
- execute = dorelease
- }
+ newaction {
+ trigger = "release",
+ description = "Prepare a new release (incomplete)",
+ execute = dorelease
+ }
+
+--[[
+ This part of the premake4.lua modifies the core premake4 behavior a little.
+
+ It does the following (in order of appearence below):
+
+ - New option --sdkver to override <WindowsTargetPlatformVersion> on modern VS
+ - New option --clang to request ClangCL toolset on modern VS
+ - New option --xp to request XP-compatible toolset on modern VS
+ - On older premake4 versions it will provide a premake.project.getbasename
+ function, furthermore two other functions get patched to make use of it
+ - premake.project.getbasename() gets overridden to insert a marker into the
+ created file name, based on the chosen action
+ Example: foobar.vcxproj becomes foobar.vs2022.vcxproj etc ...
+ The purpose of this exercise is to allow for projects/solutions of several
+ Visual Studio versions to reside in the same folder
+ - Options "dotnet" gets removed
+ - The "platform" option has some allowed values removed
+ - The "os" option has some allowed values removed
+ - The actions are trimmed to what we know can work
+]]
+
+newoption { trigger = "sdkver", value = "SDKVER", description = "Allows to override SDK version (VS2015 through VS2022)" }
+newoption { trigger = "clang", description = "Allows to use clang-cl as compiler and lld-link as linker (VS2019 and VS2022)" }
+newoption { trigger = "xp", description = "Allows to use a supported XP toolset for some VS versions" }
+
+do
+ -- This is mainly to support older premake4 builds
+ if not premake.project.getbasename then
+ print "Magic happens for old premake4 versions without premake.project.getbasename() ..."
+ -- override the function to establish the behavior we'd get after patching Premake to have premake.project.getbasename
+ premake.project.getbasename = function(prjname, pattern)
+ return pattern:gsub("%%%%", prjname)
+ end
+ -- obviously we also need to overwrite the following to generate functioning VS solution files
+ premake.vstudio.projectfile = function(prj)
+ local pattern
+ if prj.language == "C#" then
+ pattern = "%%.csproj"
+ else
+ pattern = iif(_ACTION > "vs2008", "%%.vcxproj", "%%.vcproj")
+ end
+
+ local fname = premake.project.getbasename(prj.name, pattern)
+ fname = path.join(prj.location, fname)
+ return fname
+ end
+ -- we simply overwrite the original function on older Premake versions
+ premake.project.getfilename = function(prj, pattern)
+ local fname = premake.project.getbasename(prj.name, pattern)
+ fname = path.join(prj.location, fname)
+ return path.getrelative(os.getcwd(), fname)
+ end
+ end
+ -- Make UUID generation for filters deterministic
+ if os.str2uuid ~= nil then
+ local vc2010 = premake.vstudio.vc2010
+ vc2010.filteridgroup = function(prj)
+ local filters = { }
+ local filterfound = false
+
+ for file in premake.project.eachfile(prj) do
+ -- split the path into its component parts
+ local folders = string.explode(file.vpath, "/", true)
+ local path = ""
+ for i = 1, #folders - 1 do
+ -- element is only written if there *are* filters
+ if not filterfound then
+ filterfound = true
+ _p(1,"<ItemGroup>")
+ end
+
+ path = path .. folders[i]
+
+ -- have I seen this path before?
+ if not filters[path] then
+ local seed = path .. (prj.uuid or "")
+ local deterministic_uuid = os.str2uuid(seed)
+ filters[path] = true
+ _p(2, '<Filter Include="%s">', path)
+ _p(3, "<UniqueIdentifier>{%s}</UniqueIdentifier>", deterministic_uuid)
+ _p(2, "</Filter>")
+ end
+
+ -- prepare for the next subfolder
+ path = path .. "\\"
+ end
+ end
+
+ if filterfound then
+ _p(1,"</ItemGroup>")
+ end
+ end
+ end
+ -- Name the project files after their VS version
+ local orig_getbasename = premake.project.getbasename
+ premake.project.getbasename = function(prjname, pattern)
+ -- The below is used to insert the .vs(8|9|10|11|12|14|15|16|17) into the file names for projects and solutions
+ if _ACTION then
+ name_map = {vs2005 = "vs8", vs2008 = "vs9", vs2010 = "vs10", vs2012 = "vs11", vs2013 = "vs12", vs2015 = "vs14", vs2017 = "vs15", vs2019 = "vs16", vs2022 = "vs17"}
+ if name_map[_ACTION] then
+ pattern = pattern:gsub("%%%%", "%%%%." .. name_map[_ACTION])
+ else
+ pattern = pattern:gsub("%%%%", "%%%%." .. _ACTION)
+ end
+ end
+ return orig_getbasename(prjname, pattern)
+ end
+ -- Premake4 sets the PDB file name for the compiler's PDB to the default
+ -- value used by the linker's PDB. This causes error C1052 on VS2017. Fix it.
+ -- But this also fixes up certain other areas of the generated project. The idea
+ -- here is to catch the original _p() invocations, evaluate the arguments and
+ -- then act based on those, using orig_p() as a standin during a call to the
+ -- underlying premake.vs2010_vcxproj() function ;-)
+ local orig_premake_vs2010_vcxproj = premake.vs2010_vcxproj
+ premake.vs2010_vcxproj = function(prj)
+ -- The whole stunt below is necessary in order to modify the resource_compile()
+ -- output. Given it's a local function we have to go through hoops.
+ local orig_p = _G._p
+ local besilent = false
+ -- We patch the global _p() function
+ _G._p = function(indent, msg, first, ...)
+ -- Look for non-empty messages and narrow it down by the indent values
+ if msg ~= nil then
+ if msg:match("<ProgramDataBaseFileName>[^<]+</ProgramDataBaseFileName>") then
+ return -- we want to suppress these
+ end
+ if indent == 2 then
+ if msg == '<ClCompile Include=\"%s\">' and first == "delayload-stubs\\ntdll-delayed-stubs.c" then
+ orig_p(indent, msg, first, ...) -- what was originally supposed to be output
+ orig_p(indent+1, "<ExcludedFromBuild>true</ExcludedFromBuild>")
+ return
+ end
+ if msg == "<RootNamespace>%s</RootNamespace>" then
+ local sdkmap = {vs2015 = "8.1", vs2017 = "10.0.17763.0", vs2019 = "10.0", vs2022 = "10.0"}
+ if (not _ACTION) or (not sdkmap[_ACTION]) then -- should not happen, but tread carefully anyway
+ orig_p(indent, msg, first, ...) -- what was originally supposed to be output
+ return
+ end
+ local sdkver = _OPTIONS["sdkver"] or sdkmap[_ACTION]
+ orig_p(indent, msg, first, ...) -- what was originally supposed to be output
+ orig_p(indent, "<WindowsTargetPlatformVersion>%s</WindowsTargetPlatformVersion>", sdkver)
+ return
+ end
+ if msg == "<PlatformToolset>%s</PlatformToolset>" then
+ if (_OPTIONS["clang"] ~= nil) and (_ACTION == "vs2017") then
+ if _OPTIONS["xp"] ~= nil then
+ print "WARNING: The --clang option takes precedence over --xp, therefore picking v141_clang_c2 toolset."
+ end
+ print "WARNING: If you are used to Clang support from VS2019 and newer, be sure to review your choice. It's not the same on older VS versions."
+ orig_p(indent, msg, "v141_clang_c2")
+ return
+ elseif (_OPTIONS["clang"] ~= nil) and (_ACTION >= "vs2019") then
+ if _OPTIONS["xp"] ~= nil then
+ print "WARNING: The --clang option takes precedence over --xp, therefore picking ClangCL toolset."
+ end
+ orig_p(indent, msg, "ClangCL")
+ return
+ elseif _OPTIONS["xp"] ~= nil then
+ local toolsets = { vs2012 = "v110", vs2013 = "v120", vs2015 = "v140", vs2017 = "v141", vs2019 = "v142", vs2022 = "v143" }
+ local toolset = toolsets[_ACTION]
+ if toolset then
+ if _OPTIONS["xp"] and toolset >= "v141" then
+ toolset = "v141" -- everything falls back to the VS2017 XP toolset for more recent VS
+ end
+ orig_p(indent,"<PlatformToolset>%s_xp</PlatformToolset>", toolset)
+ return
+ end
+ end
+ end
+ elseif indent == 3 then
+ -- This is what vanilla VS would output it as, so let's try to align with that
+ if msg == "<PrecompiledHeader></PrecompiledHeader>" then
+ orig_p(indent, "<PrecompiledHeader>")
+ orig_p(indent, "</PrecompiledHeader>")
+ return
+ end
+ end
+ end
+ if not besilent then -- should we be silent (i.e. suppress default output)?
+ orig_p(indent, msg, first, ...)
+ end
+ end
+ orig_premake_vs2010_vcxproj(prj)
+ _G._p = orig_p -- restore in any case
+ end
+ -- ... same as above but for VS200x this time
+ local function wrap_remove_pdb_attribute(origfunc)
+ local fct = function(cfg)
+ local old_captured = io.captured -- save io.captured state
+ io.capture() -- this sets io.captured = ""
+ origfunc(cfg)
+ local captured = io.endcapture()
+ assert(captured ~= nil)
+ captured = captured:gsub('%s+ProgramDataBaseFileName=\"[^"]+\"', "")
+ if old_captured ~= nil then
+ io.captured = old_captured .. captured -- restore outer captured state, if any
+ else
+ io.write(captured)
+ end
+ end
+ return fct
+ end
+ premake.vstudio.vc200x.VCLinkerTool = wrap_remove_pdb_attribute(premake.vstudio.vc200x.VCLinkerTool)
+ premake.vstudio.vc200x.toolmap.VCLinkerTool = premake.vstudio.vc200x.VCLinkerTool -- this is important as well
+ premake.vstudio.vc200x.VCCLCompilerTool = wrap_remove_pdb_attribute(premake.vstudio.vc200x.VCCLCompilerTool)
+ premake.vstudio.vc200x.toolmap.VCCLCompilerTool = premake.vstudio.vc200x.VCCLCompilerTool -- this is important as well
+ -- Override the object directory paths ... don't make them "unique" inside premake4
+ local orig_gettarget = premake.gettarget
+ premake.gettarget = function(cfg, direction, pathstyle, namestyle, system)
+ local r = orig_gettarget(cfg, direction, pathstyle, namestyle, system)
+ if (cfg.objectsdir) and (cfg.objdir) then
+ cfg.objectsdir = cfg.objdir
+ end
+ return r
+ end
+ -- Silently suppress generation of the .user files ...
+ local orig_generate = premake.generate
+ premake.generate = function(obj, filename, callback)
+ if filename:find(".vcproj.user") or filename:find(".vcxproj.user") then
+ return
+ end
+ orig_generate(obj, filename, callback)
+ end
+ -- Fix up premake.getlinks() to not do stupid stuff with object files we pass
+ local orig_premake_getlinks = premake.getlinks
+ premake.getlinks = function(cfg, kind, part)
+ local origret = orig_premake_getlinks(cfg, kind, part)
+ local ret = {}
+ for k,v in ipairs(origret) do
+ local dep = v:gsub(".obj.lib", ".obj")
+ dep = dep:gsub(".lib.lib", ".lib")
+ table.insert(ret, dep)
+ end
+ return ret
+ end
+
+ -- Remove an option altogether or some otherwise accepted values for that option
+ local function remove_allowed_optionvalues(option, values_toremove)
+ if premake.option.list[option] ~= nil then
+ if values_toremove == nil then
+ premake.option.list[option] = nil
+ return
+ end
+ if premake.option.list.platform["allowed"] ~= nil then
+ local allowed = premake.option.list[option].allowed
+ for i = #allowed, 1, -1 do
+ if values_toremove[allowed[i][1]] then
+ table.remove(allowed, i)
+ end
+ end
+ end
+ end
+ end
+
+ local function remove_action(action)
+ if premake.action.list[action] ~= nil then
+ premake.action.list[action] = nil
+ end
+ end
+
+ -- Remove some unwanted/outdated options
+ remove_allowed_optionvalues("dotnet")
+ remove_allowed_optionvalues("platform", { universal = 0, universal32 = 0, universal64 = 0, ps3 = 0, xbox360 = 0, })
+ remove_allowed_optionvalues("os") -- ... , { bsd = 0, haiku = 0, linux = 0, macosx = 0, solaris = 0, }
+ remove_allowed_optionvalues("cc")
+ -- ... and actions (mainly because they are untested)
+ for k,v in pairs({codeblocks = 0, codelite = 0, xcode3 = 0, xcode4 = 0, vs2002 = 0, vs2003 = 0, }) do -- vs2005 = 0, vs2008 = 0, vs2010 = 0, vs2012 = 0, vs2013 = 0
+ remove_action(k)
+ end
+end