--[[
This premake4.lua _requires_ windirstat/premake-stable to work properly.
If you don't want to use the code-signed build that can be found in the
download section of that project, you can build from the WDS-branch at:
https://bitbucket.org/windirstat/premake-stable
--]]
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, '')
_p(depth, '\t')
_p(depth, '')
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, '')
end,
onbranchexit = function(node, depth)
_p(depth, '')
end,
-- source files are handled at the leaves
onleaf = function(node, depth)
local fname = node.cfg.name
_p(depth, '')
depth = depth + 1
vc200x.individualSourceFile(prj, depth, fname, node)
depth = depth - 1
_p(depth, '')
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,'', translatedpath)
for _, cfginfo in ipairs(configs) do
if config_mappings[cfginfo] and translatedpath == config_mappings[cfginfo] then
_p(3,'Create', 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,'%s', iif(path.iscfile(file.name), 'CompileAsC', 'CompileAsCpp'))
end
_p(2,'')
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,'')
for _, file in ipairs(files) do
vc2010.individualSourceFile(prj, config_mappings, file)
end
_p(1,'')
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,'')
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, '', path)
_p(3, '{%s}', deterministic_uuid)
_p(2, '')
end
-- prepare for the next subfolder
path = path .. "\\"
end
end
if filterfound then
_p(1,'')
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) into the file names for projects and solutions
if _ACTION then
name_map = {vs2002 = "vs7", vs2003 = "vs7_1", vs2005 = "vs8", vs2008 = "vs9", vs2010 = "vs10", vs2012 = "vs11", vs2013 = "vs12", vs2015 = "vs14", vs2017 = "vs15"}
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("()(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("()", "_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
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
end
--
-- Define the project. Put the release configuration first so it will be the
-- default when folks build using the makefile. That way they don't have to
-- worry about the /scripts argument and all that.
--
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"}
postbuildcommands { 'ollisign.cmd -a "$(TargetPath)" "https://bitbucket.org/windirstat/premake-stable" "premake4"' }
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" }
--
-- A more thorough cleanup.
--
if _ACTION == "clean" then
os.rmdir("bin")
os.rmdir("build")
end
--
-- Use the --to=path option to control where the project files get generated. I use
-- this to create project files for each supported toolset, each in their own folder,
-- 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."
}
--
-- Use the embed action to convert all of the Lua scripts into C strings, which
-- can then be built into the executable. Always embed the scripts before creating
-- a release build.
--
dofile("scripts/embed.lua")
newaction {
trigger = "embed",
description = "Embed scripts in scripts.c; required before release builds",
execute = doembed
}
--
-- Use the release action to prepare source and binary packages for a new release.
-- This action isn't complete yet; a release still requires some manual work.
--
dofile("scripts/release.lua")
newaction {
trigger = "release",
description = "Prepare a new release (incomplete)",
execute = dorelease
}