A friendly fork of Premake4 used to generate project files for WinDirStat. These patches applied for use in WinDirStat are not necessarily part of the upstream premake-stable. The WDS-build branch is the one used for the accumulated changes from all other branches. Code-signed binaries available.
Revisión | afc0b5c48c950813225fad5b8e3b39012caedb72 (tree) |
---|---|
Tiempo | 2022-03-14 07:49:34 |
Autor | Oliver Schneider <oliver@assa...> |
Commiter | Oliver Schneider |
Reviewed and reworked the premake4.lua to make better use of modern VS versions
- 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
@@ -48,7 +48,6 @@ | ||
48 | 48 | UsePrecompiledHeader="0" |
49 | 49 | WarningLevel="4" |
50 | 50 | Detect64BitPortabilityProblems="false" |
51 | - ProgramDataBaseFileName="$(OutDir)\premake4.pdb" | |
52 | 51 | DebugInformationFormat="0" |
53 | 52 | CompileAs="1" |
54 | 53 | /> |
@@ -135,7 +134,6 @@ | ||
135 | 134 | UsePrecompiledHeader="0" |
136 | 135 | WarningLevel="4" |
137 | 136 | Detect64BitPortabilityProblems="false" |
138 | - ProgramDataBaseFileName="$(OutDir)\premake4.pdb" | |
139 | 137 | DebugInformationFormat="4" |
140 | 138 | CompileAs="1" |
141 | 139 | /> |
@@ -157,7 +155,6 @@ | ||
157 | 155 | LinkIncremental="2" |
158 | 156 | AdditionalLibraryDirectories="" |
159 | 157 | GenerateDebugInformation="true" |
160 | - ProgramDataBaseFileName="$(OutDir)\premake4.pdb" | |
161 | 158 | SubSystem="1" |
162 | 159 | EntryPointSymbol="mainCRTStartup" |
163 | 160 | TargetMachine="1" |
@@ -220,7 +217,6 @@ | ||
220 | 217 | UsePrecompiledHeader="0" |
221 | 218 | WarningLevel="4" |
222 | 219 | Detect64BitPortabilityProblems="false" |
223 | - ProgramDataBaseFileName="$(OutDir)\premake4.pdb" | |
224 | 220 | DebugInformationFormat="0" |
225 | 221 | CompileAs="1" |
226 | 222 | /> |
@@ -12,292 +12,20 @@ | ||
12 | 12 | ]] |
13 | 13 | local action = _ACTION or "" |
14 | 14 | if _OPTIONS["publish"] then |
15 | - print "INFO: Creating 'Publish' build solution." | |
16 | - publish = true | |
17 | -end | |
18 | -do | |
19 | - -- This is mainly to support older premake4 builds | |
20 | - if not premake.project.getbasename then | |
21 | - print "Magic happens for old premake4 versions without premake.project.getbasename() ..." | |
22 | - -- override the function to establish the behavior we'd get after patching Premake to have premake.project.getbasename | |
23 | - premake.project.getbasename = function(prjname, pattern) | |
24 | - return pattern:gsub("%%%%", prjname) | |
25 | - end | |
26 | - -- obviously we also need to overwrite the following to generate functioning VS solution files | |
27 | - premake.vstudio.projectfile = function(prj) | |
28 | - local pattern | |
29 | - if prj.language == "C#" then | |
30 | - pattern = "%%.csproj" | |
31 | - else | |
32 | - pattern = iif(_ACTION > "vs2008", "%%.vcxproj", "%%.vcproj") | |
33 | - end | |
34 | - | |
35 | - local fname = premake.project.getbasename(prj.name, pattern) | |
36 | - fname = path.join(prj.location, fname) | |
37 | - return fname | |
38 | - end | |
39 | - -- we simply overwrite the original function on older Premake versions | |
40 | - premake.project.getfilename = function(prj, pattern) | |
41 | - local fname = premake.project.getbasename(prj.name, pattern) | |
42 | - fname = path.join(prj.location, fname) | |
43 | - return path.getrelative(os.getcwd(), fname) | |
44 | - end | |
45 | - end | |
46 | - -- This is mainly to support older premake4 in which CompileAs did not work | |
47 | - -- for VS2010 and newer | |
48 | - if not premake.vstudio.vc2010.individualSourceFile or not premake.vstudio.vc200x.individualSourceFile then | |
49 | - local vc2010 = premake.vstudio.vc2010 | |
50 | - local vc200x = premake.vstudio.vc200x | |
51 | - local tree = premake.tree | |
52 | - print "Magic happens for old premake4 versions faulty CompileAs handling for VS2010 and newer ..." | |
53 | - -- A boilerplate implementation | |
54 | - vc200x.individualSourceFile = function(prj, depth, fname, node) | |
55 | - -- handle file configuration stuff. This needs to be cleaned up and simplified. | |
56 | - -- configurations are cached, so this isn't as bad as it looks | |
57 | - for _, cfginfo in ipairs(prj.solution.vstudio_configs) do | |
58 | - if cfginfo.isreal then | |
59 | - local cfg = premake.getconfig(prj, cfginfo.src_buildcfg, cfginfo.src_platform) | |
60 | - | |
61 | - local usePCH = (not prj.flags.NoPCH and prj.pchsource == node.cfg.name) | |
62 | - local isSourceCode = path.iscppfile(fname) | |
63 | - local needsCompileAs = (path.iscfile(fname) ~= premake.project.iscproject(prj)) | |
64 | - | |
65 | - if usePCH or (isSourceCode and needsCompileAs) then | |
66 | - _p(depth, '<FileConfiguration') | |
67 | - _p(depth, '\tName="%s"', cfginfo.name) | |
68 | - _p(depth, '\t>') | |
69 | - _p(depth, '\t<Tool') | |
70 | - _p(depth, '\t\tName="%s"', iif(cfg.system == "Xbox360", | |
71 | - "VCCLX360CompilerTool", | |
72 | - "VCCLCompilerTool")) | |
73 | - if needsCompileAs then | |
74 | - _p(depth, '\t\tCompileAs="%s"', iif(path.iscfile(fname), 1, 2)) | |
75 | - end | |
76 | - | |
77 | - if usePCH then | |
78 | - if cfg.system == "PS3" then | |
79 | - local options = table.join(premake.snc.getcflags(cfg), | |
80 | - premake.snc.getcxxflags(cfg), | |
81 | - cfg.buildoptions) | |
82 | - options = table.concat(options, " "); | |
83 | - options = options .. ' --create_pch="$(IntDir)/$(TargetName).pch"' | |
84 | - _p(depth, '\t\tAdditionalOptions="%s"', premake.esc(options)) | |
85 | - else | |
86 | - _p(depth, '\t\tUsePrecompiledHeader="1"') | |
87 | - end | |
88 | - end | |
89 | - | |
90 | - _p(depth, '\t/>') | |
91 | - _p(depth, '</FileConfiguration>') | |
92 | - end | |
93 | - | |
94 | - end | |
95 | - end | |
96 | - end | |
97 | - vc200x.Files = function(prj) | |
98 | - local tr = premake.project.buildsourcetree(prj) | |
99 | - | |
100 | - tree.traverse(tr, { | |
101 | - -- folders are handled at the internal nodes | |
102 | - onbranchenter = function(node, depth) | |
103 | - _p(depth, '<Filter') | |
104 | - _p(depth, '\tName="%s"', node.name) | |
105 | - _p(depth, '\tFilter=""') | |
106 | - _p(depth, '\t>') | |
107 | - end, | |
108 | - | |
109 | - onbranchexit = function(node, depth) | |
110 | - _p(depth, '</Filter>') | |
111 | - end, | |
112 | - | |
113 | - -- source files are handled at the leaves | |
114 | - onleaf = function(node, depth) | |
115 | - local fname = node.cfg.name | |
116 | - | |
117 | - _p(depth, '<File') | |
118 | - _p(depth, '\tRelativePath="%s"', path.translate(fname, "\\")) | |
119 | - _p(depth, '\t>') | |
120 | - depth = depth + 1 | |
121 | - | |
122 | - vc200x.individualSourceFile(prj, depth, fname, node) | |
123 | - | |
124 | - depth = depth - 1 | |
125 | - _p(depth, '</File>') | |
126 | - end, | |
127 | - }, false, 2) | |
128 | - | |
129 | - end | |
130 | - -- A boilerplate implementation | |
131 | - vc2010.individualSourceFile = function(prj, config_mappings, file) | |
132 | - local configs = prj.solution.vstudio_configs | |
133 | - local translatedpath = path.translate(file.name, "\\") | |
134 | - _p(2,'<ClCompile Include=\"%s\">', translatedpath) | |
135 | - for _, cfginfo in ipairs(configs) do | |
136 | - if config_mappings[cfginfo] and translatedpath == config_mappings[cfginfo] then | |
137 | - _p(3,'<PrecompiledHeader '.. if_config_and_platform() .. '>Create</PrecompiledHeader>', premake.esc(cfginfo.name)) | |
138 | - config_mappings[cfginfo] = nil --only one source file per pch | |
139 | - end | |
140 | - end | |
141 | - if path.iscfile(file.name) ~= premake.project.iscproject(prj) then | |
142 | - _p(3,'<CompileAs>%s</CompileAs>', iif(path.iscfile(file.name), 'CompileAsC', 'CompileAsCpp')) | |
143 | - end | |
144 | - _p(2,'</ClCompile>') | |
145 | - end | |
146 | - -- Overriding the function which calls the above | |
147 | - vc2010.compilerfilesgroup = function(prj) | |
148 | - local configs = prj.solution.vstudio_configs | |
149 | - local files = vc2010.getfilegroup(prj, "ClCompile") | |
150 | - if #files > 0 then | |
151 | - local config_mappings = {} | |
152 | - for _, cfginfo in ipairs(configs) do | |
153 | - local cfg = premake.getconfig(prj, cfginfo.src_buildcfg, cfginfo.src_platform) | |
154 | - if cfg.pchheader and cfg.pchsource and not cfg.flags.NoPCH then | |
155 | - config_mappings[cfginfo] = path.translate(cfg.pchsource, "\\") | |
156 | - end | |
157 | - end | |
158 | - | |
159 | - _p(1,'<ItemGroup>') | |
160 | - for _, file in ipairs(files) do | |
161 | - vc2010.individualSourceFile(prj, config_mappings, file) | |
162 | - end | |
163 | - _p(1,'</ItemGroup>') | |
164 | - end | |
165 | - end | |
166 | - end | |
167 | - -- Make UUID generation for filters deterministic | |
168 | - if os.str2uuid ~= nil then | |
169 | - local vc2010 = premake.vstudio.vc2010 | |
170 | - vc2010.filteridgroup = function(prj) | |
171 | - local filters = { } | |
172 | - local filterfound = false | |
173 | - | |
174 | - for file in premake.project.eachfile(prj) do | |
175 | - -- split the path into its component parts | |
176 | - local folders = string.explode(file.vpath, "/", true) | |
177 | - local path = "" | |
178 | - for i = 1, #folders - 1 do | |
179 | - -- element is only written if there *are* filters | |
180 | - if not filterfound then | |
181 | - filterfound = true | |
182 | - _p(1,'<ItemGroup>') | |
183 | - end | |
184 | - | |
185 | - path = path .. folders[i] | |
186 | - | |
187 | - -- have I seen this path before? | |
188 | - if not filters[path] then | |
189 | - local seed = path .. (prj.uuid or "") | |
190 | - local deterministic_uuid = os.str2uuid(seed) | |
191 | - filters[path] = true | |
192 | - _p(2, '<Filter Include="%s">', path) | |
193 | - _p(3, '<UniqueIdentifier>{%s}</UniqueIdentifier>', deterministic_uuid) | |
194 | - _p(2, '</Filter>') | |
195 | - end | |
196 | - | |
197 | - -- prepare for the next subfolder | |
198 | - path = path .. "\\" | |
199 | - end | |
200 | - end | |
201 | - | |
202 | - if filterfound then | |
203 | - _p(1,'</ItemGroup>') | |
204 | - end | |
205 | - end | |
206 | - end | |
207 | - -- Name the project files after their VS version | |
208 | - local orig_getbasename = premake.project.getbasename | |
209 | - premake.project.getbasename = function(prjname, pattern) | |
210 | - -- 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 | |
211 | - if _ACTION then | |
212 | - name_map = {vs2005 = "vs8", vs2008 = "vs9", vs2010 = "vs10", vs2012 = "vs11", vs2013 = "vs12", vs2015 = "vs14", vs2017 = "vs15", vs2019 = "vs16", vs2022 = "vs17"} | |
213 | - if name_map[_ACTION] then | |
214 | - pattern = pattern:gsub("%%%%", "%%%%." .. name_map[_ACTION]) | |
215 | - else | |
216 | - pattern = pattern:gsub("%%%%", "%%%%." .. _ACTION) | |
217 | - end | |
218 | - end | |
219 | - return orig_getbasename(prjname, pattern) | |
220 | - end | |
221 | - -- Older versions of Premake4 fail to set the proper entry point, although they could simply let it out entirely ... | |
222 | - local orig_vc2010_link = premake.vstudio.vc2010.link | |
223 | - premake.vstudio.vc2010.link = function(cfg) | |
224 | - if cfg.flags and cfg.flags.Unicode then | |
225 | - io.capture() | |
226 | - orig_vc2010_link(cfg) | |
227 | - local captured = io.endcapture() | |
228 | - captured = captured:gsub("(<EntryPointSymbol>)(mainCRTStartup)", "%1w%2") | |
229 | - io.write(captured) | |
230 | - else | |
231 | - orig_vc2010_link(cfg) | |
232 | - end | |
233 | - end | |
234 | - local orig_vc200x_VCLinkerTool = premake.vstudio.vc200x.VCLinkerTool | |
235 | - premake.vstudio.vc200x.VCLinkerTool = function(cfg) | |
236 | - if cfg.flags and cfg.flags.Unicode then | |
237 | - io.capture() | |
238 | - orig_vc200x_VCLinkerTool(cfg) | |
239 | - local captured = io.endcapture() | |
240 | - captured = captured:gsub('(EntryPointSymbol=")(mainCRTStartup)', "%1w%2") | |
241 | - io.write(captured) | |
242 | - else | |
243 | - orig_vc200x_VCLinkerTool(cfg) | |
244 | - end | |
245 | - end | |
246 | - premake.vstudio.vc200x.toolmap.VCLinkerTool = premake.vstudio.vc200x.VCLinkerTool | |
247 | - -- Make sure we can generate XP-compatible projects for newer Visual Studio versions | |
248 | - local orig_vc2010_configurationPropertyGroup = premake.vstudio.vc2010.configurationPropertyGroup | |
249 | - premake.vstudio.vc2010.configurationPropertyGroup = function(cfg, cfginfo) | |
250 | - io.capture() | |
251 | - orig_vc2010_configurationPropertyGroup(cfg, cfginfo) | |
252 | - local captured = io.endcapture() | |
253 | - local toolsets = { vs2012 = "v110", vs2013 = "v120", vs2015 = "v140", vs2017 = "v141" } | |
254 | - local toolset = toolsets[_ACTION] | |
255 | - if toolset then | |
256 | - if _OPTIONS["xp"] then | |
257 | - toolset = toolset .. "_xp" | |
258 | - captured = captured:gsub("(</PlatformToolset>)", "_xp%1") | |
259 | - end | |
260 | - end | |
261 | - io.write(captured) | |
262 | - end | |
263 | - -- Override the object directory paths ... don't make them "unique" inside premake4 | |
264 | - local orig_gettarget = premake.gettarget | |
265 | - premake.gettarget = function(cfg, direction, pathstyle, namestyle, system) | |
266 | - local r = orig_gettarget(cfg, direction, pathstyle, namestyle, system) | |
267 | - if (cfg.objectsdir) and (cfg.objdir) then | |
268 | - cfg.objectsdir = cfg.objdir | |
269 | - end | |
270 | - return r | |
271 | - end | |
272 | - -- Silently suppress generation of the .user files ... | |
273 | - local orig_generate = premake.generate | |
274 | - premake.generate = function(obj, filename, callback) | |
275 | - if filename:find('.vcproj.user') or filename:find('.vcxproj.user') then | |
276 | - return | |
277 | - end | |
278 | - orig_generate(obj, filename, callback) | |
279 | - end | |
280 | - -- We want to output the file with UTF-8 BOM | |
281 | - local orig_vc2010_header = premake.vstudio.vc2010.header | |
282 | - premake.vstudio.vc2010.header = function(targets) | |
283 | - io.capture() | |
284 | - orig_vc2010_header(targets) | |
285 | - local captured = io.endcapture() | |
286 | - io.write("\239\187\191") | |
287 | - io.write(captured) | |
288 | - end | |
15 | + print "INFO: Creating 'Publish' build solution." | |
16 | + publish = true | |
289 | 17 | end |
290 | 18 | local function transformMN(input) -- transform the macro names for older Visual Studio versions |
291 | - local new_map = { vs2002 = 0, vs2003 = 0, vs2005 = 0, vs2008 = 0 } | |
292 | - local replacements = { Platform = "PlatformName", Configuration = "ConfigurationName" } | |
293 | - if new_map[action] ~= nil then | |
294 | - for k,v in pairs(replacements) do | |
295 | - if input:find(k) then | |
296 | - input = input:gsub(k, v) | |
297 | - end | |
298 | - end | |
299 | - end | |
300 | - return input | |
19 | + local new_map = { vs2002 = 0, vs2003 = 0, vs2005 = 0, vs2008 = 0 } | |
20 | + local replacements = { Platform = "PlatformName", Configuration = "ConfigurationName" } | |
21 | + if new_map[action] ~= nil then | |
22 | + for k,v in pairs(replacements) do | |
23 | + if input:find(k) then | |
24 | + input = input:gsub(k, v) | |
25 | + end | |
26 | + end | |
27 | + end | |
28 | + return input | |
301 | 29 | end |
302 | 30 | -- |
303 | 31 | -- Define the project. Put the release configuration first so it will be the |
@@ -306,82 +34,82 @@ | ||
306 | 34 | -- |
307 | 35 | |
308 | 36 | solution "Premake4" |
309 | - configurations { "Release", "Debug", "Publish" } | |
310 | - location ( _OPTIONS["to"] ) | |
311 | - | |
312 | - project "Premake4" | |
313 | - local int_dir = "intermediate/" .. action .. "_$(" .. transformMN("Platform") .. ")_$(" .. transformMN("Configuration") .. ")" | |
314 | - uuid "7F000221-EACC-2F4F-A07F-6A5D34AF10D0" | |
315 | - targetname "premake4" | |
316 | - language "C" | |
317 | - kind "ConsoleApp" | |
318 | - objdir (int_dir) | |
319 | - flags { "No64BitChecks", "ExtraWarnings", "StaticRuntime" } | |
320 | - includedirs { "src/host/lua-5.1.4/src" } | |
321 | - defines { "USE_KECCAK" } | |
322 | - | |
323 | - files | |
324 | - { | |
325 | - "*.txt", "**.lua", | |
326 | - "src/**.h", "src/**.c", | |
327 | - "src/host/scripts.c" | |
328 | - } | |
329 | - | |
330 | - excludes | |
331 | - { | |
332 | - "src/premake.lua", | |
333 | - "src/host/lua-5.1.4/src/lua.c", | |
334 | - "src/host/lua-5.1.4/src/luac.c", | |
335 | - "src/host/lua-5.1.4/src/print.c", | |
336 | - "src/host/lua-5.1.4/**.lua", | |
337 | - "src/host/lua-5.1.4/etc/*.c", | |
338 | - "src/host/hgtip.h", | |
339 | - "packages/**", | |
340 | - "samples/**", | |
341 | - "tests/**", | |
342 | - } | |
37 | + configurations { "Release", "Debug", "Publish" } | |
38 | + location ( _OPTIONS["to"] ) | |
343 | 39 | |
344 | - configuration "Debug" | |
345 | - targetdir "bin/debug" | |
346 | - defines "_DEBUG" | |
347 | - flags { "Symbols" } | |
348 | - | |
349 | - configuration "Release or Publish" | |
350 | - targetdir "bin/release" | |
351 | - defines "NDEBUG" | |
352 | - flags { "OptimizeSize" } | |
353 | - | |
354 | - configuration "vs*" | |
355 | - defines { "_CRT_SECURE_NO_WARNINGS" } | |
356 | - | |
357 | - configuration "vs2005" | |
358 | - defines {"_CRT_SECURE_NO_DEPRECATE" } | |
359 | - | |
360 | - configuration "windows" | |
361 | - links { "ole32" } | |
362 | - files { "src/host/premake4.rc" } | |
40 | + project "Premake4" | |
41 | + local int_dir = "intermediate/" .. action .. "_$(" .. transformMN("Platform") .. ")_$(" .. transformMN("Configuration") .. ")" | |
42 | + uuid "7F000221-EACC-2F4F-A07F-6A5D34AF10D0" | |
43 | + targetname "premake4" | |
44 | + language "C" | |
45 | + kind "ConsoleApp" | |
46 | + objdir (int_dir) | |
47 | + flags { "No64BitChecks", "ExtraWarnings", "StaticRuntime" } | |
48 | + includedirs { "src/host/lua-5.1.4/src" } | |
49 | + defines { "USE_KECCAK" } | |
363 | 50 | |
364 | - configuration {"windows", "Publish"} | |
365 | - defines { "HAVE_HGTIP", "PREMAKE_VERSION=4.4-wds"} | |
366 | - | |
367 | - configuration "linux or bsd" | |
368 | - defines { "LUA_USE_POSIX", "LUA_USE_DLOPEN" } | |
369 | - links { "m" } | |
370 | - linkoptions { "-rdynamic" } | |
51 | + files | |
52 | + { | |
53 | + "*.txt", "**.lua", | |
54 | + "src/**.h", "src/**.c", | |
55 | + "src/host/scripts.c" | |
56 | + } | |
371 | 57 | |
372 | - configuration "linux" | |
373 | - links { "dl" } | |
58 | + excludes | |
59 | + { | |
60 | + "src/premake.lua", | |
61 | + "src/host/lua-5.1.4/src/lua.c", | |
62 | + "src/host/lua-5.1.4/src/luac.c", | |
63 | + "src/host/lua-5.1.4/src/print.c", | |
64 | + "src/host/lua-5.1.4/**.lua", | |
65 | + "src/host/lua-5.1.4/etc/*.c", | |
66 | + "src/host/hgtip.h", | |
67 | + "packages/**", | |
68 | + "samples/**", | |
69 | + "tests/**", | |
70 | + } | |
374 | 71 | |
375 | - configuration "macosx" | |
376 | - defines { "LUA_USE_MACOSX" } | |
377 | - links { "CoreServices.framework" } | |
72 | + configuration "Debug" | |
73 | + targetdir "bin/debug" | |
74 | + defines "_DEBUG" | |
75 | + flags { "Symbols" } | |
378 | 76 | |
379 | - configuration { "macosx", "gmake" } | |
380 | - buildoptions { "-mmacosx-version-min=10.4" } | |
381 | - linkoptions { "-mmacosx-version-min=10.4" } | |
77 | + configuration "Release or Publish" | |
78 | + targetdir "bin/release" | |
79 | + defines "NDEBUG" | |
80 | + flags { "OptimizeSize" } | |
382 | 81 | |
383 | - configuration { "solaris" } | |
384 | - linkoptions { "-Wl,--export-dynamic" } | |
82 | + configuration "vs*" | |
83 | + defines { "_CRT_SECURE_NO_WARNINGS" } | |
84 | + | |
85 | + configuration "vs2005" | |
86 | + defines {"_CRT_SECURE_NO_DEPRECATE" } | |
87 | + | |
88 | + configuration "windows" | |
89 | + links { "ole32" } | |
90 | + files { "src/host/premake4.rc" } | |
91 | + | |
92 | + configuration {"windows", "Publish"} | |
93 | + defines { "HAVE_HGTIP", "PREMAKE_VERSION=4.4-wds"} | |
94 | + | |
95 | + configuration "linux or bsd" | |
96 | + defines { "LUA_USE_POSIX", "LUA_USE_DLOPEN" } | |
97 | + links { "m" } | |
98 | + linkoptions { "-rdynamic" } | |
99 | + | |
100 | + configuration "linux" | |
101 | + links { "dl" } | |
102 | + | |
103 | + configuration "macosx" | |
104 | + defines { "LUA_USE_MACOSX" } | |
105 | + links { "CoreServices.framework" } | |
106 | + | |
107 | + configuration { "macosx", "gmake" } | |
108 | + buildoptions { "-mmacosx-version-min=10.4" } | |
109 | + linkoptions { "-mmacosx-version-min=10.4" } | |
110 | + | |
111 | + configuration { "solaris" } | |
112 | + linkoptions { "-Wl,--export-dynamic" } | |
385 | 113 | |
386 | 114 | |
387 | 115 |
@@ -389,10 +117,10 @@ | ||
389 | 117 | -- A more thorough cleanup. |
390 | 118 | -- |
391 | 119 | |
392 | - if _ACTION == "clean" then | |
393 | - os.rmdir("bin") | |
394 | - os.rmdir("build") | |
395 | - end | |
120 | + if _ACTION == "clean" then | |
121 | + os.rmdir("bin") | |
122 | + os.rmdir("build") | |
123 | + end | |
396 | 124 | |
397 | 125 | |
398 | 126 |
@@ -402,15 +130,15 @@ | ||
402 | 130 | -- in preparation for deployment. |
403 | 131 | -- |
404 | 132 | |
405 | - newoption { | |
406 | - trigger = "to", | |
407 | - value = "path", | |
408 | - description = "Set the output location for the generated files" | |
409 | - } | |
410 | - newoption { | |
411 | - trigger = "xp", | |
412 | - description = "Enable XP-compatible build for newer Visual Studio versions." | |
413 | - } | |
133 | + newoption { | |
134 | + trigger = "to", | |
135 | + value = "path", | |
136 | + description = "Set the output location for the generated files" | |
137 | + } | |
138 | + newoption { | |
139 | + trigger = "xp", | |
140 | + description = "Enable XP-compatible build for newer Visual Studio versions." | |
141 | + } | |
414 | 142 | |
415 | 143 | |
416 | 144 |
@@ -420,13 +148,13 @@ | ||
420 | 148 | -- a release build. |
421 | 149 | -- |
422 | 150 | |
423 | - dofile("scripts/embed.lua") | |
151 | + dofile("scripts/embed.lua") | |
424 | 152 | |
425 | - newaction { | |
426 | - trigger = "embed", | |
427 | - description = "Embed scripts in scripts.c; required before release builds", | |
428 | - execute = doembed | |
429 | - } | |
153 | + newaction { | |
154 | + trigger = "embed", | |
155 | + description = "Embed scripts in scripts.c; required before release builds", | |
156 | + execute = doembed | |
157 | + } | |
430 | 158 | |
431 | 159 | |
432 | 160 | -- |
@@ -435,10 +163,281 @@ | ||
435 | 163 | -- |
436 | 164 | |
437 | 165 | |
438 | - dofile("scripts/release.lua") | |
166 | + dofile("scripts/release.lua") | |
439 | 167 | |
440 | - newaction { | |
441 | - trigger = "release", | |
442 | - description = "Prepare a new release (incomplete)", | |
443 | - execute = dorelease | |
444 | - } | |
168 | + newaction { | |
169 | + trigger = "release", | |
170 | + description = "Prepare a new release (incomplete)", | |
171 | + execute = dorelease | |
172 | + } | |
173 | + | |
174 | +--[[ | |
175 | + This part of the premake4.lua modifies the core premake4 behavior a little. | |
176 | + | |
177 | + It does the following (in order of appearence below): | |
178 | + | |
179 | + - New option --sdkver to override <WindowsTargetPlatformVersion> on modern VS | |
180 | + - New option --clang to request ClangCL toolset on modern VS | |
181 | + - New option --xp to request XP-compatible toolset on modern VS | |
182 | + - On older premake4 versions it will provide a premake.project.getbasename | |
183 | + function, furthermore two other functions get patched to make use of it | |
184 | + - premake.project.getbasename() gets overridden to insert a marker into the | |
185 | + created file name, based on the chosen action | |
186 | + Example: foobar.vcxproj becomes foobar.vs2022.vcxproj etc ... | |
187 | + The purpose of this exercise is to allow for projects/solutions of several | |
188 | + Visual Studio versions to reside in the same folder | |
189 | + - Options "dotnet" gets removed | |
190 | + - The "platform" option has some allowed values removed | |
191 | + - The "os" option has some allowed values removed | |
192 | + - The actions are trimmed to what we know can work | |
193 | +]] | |
194 | + | |
195 | +newoption { trigger = "sdkver", value = "SDKVER", description = "Allows to override SDK version (VS2015 through VS2022)" } | |
196 | +newoption { trigger = "clang", description = "Allows to use clang-cl as compiler and lld-link as linker (VS2019 and VS2022)" } | |
197 | +newoption { trigger = "xp", description = "Allows to use a supported XP toolset for some VS versions" } | |
198 | + | |
199 | +do | |
200 | + -- This is mainly to support older premake4 builds | |
201 | + if not premake.project.getbasename then | |
202 | + print "Magic happens for old premake4 versions without premake.project.getbasename() ..." | |
203 | + -- override the function to establish the behavior we'd get after patching Premake to have premake.project.getbasename | |
204 | + premake.project.getbasename = function(prjname, pattern) | |
205 | + return pattern:gsub("%%%%", prjname) | |
206 | + end | |
207 | + -- obviously we also need to overwrite the following to generate functioning VS solution files | |
208 | + premake.vstudio.projectfile = function(prj) | |
209 | + local pattern | |
210 | + if prj.language == "C#" then | |
211 | + pattern = "%%.csproj" | |
212 | + else | |
213 | + pattern = iif(_ACTION > "vs2008", "%%.vcxproj", "%%.vcproj") | |
214 | + end | |
215 | + | |
216 | + local fname = premake.project.getbasename(prj.name, pattern) | |
217 | + fname = path.join(prj.location, fname) | |
218 | + return fname | |
219 | + end | |
220 | + -- we simply overwrite the original function on older Premake versions | |
221 | + premake.project.getfilename = function(prj, pattern) | |
222 | + local fname = premake.project.getbasename(prj.name, pattern) | |
223 | + fname = path.join(prj.location, fname) | |
224 | + return path.getrelative(os.getcwd(), fname) | |
225 | + end | |
226 | + end | |
227 | + -- Make UUID generation for filters deterministic | |
228 | + if os.str2uuid ~= nil then | |
229 | + local vc2010 = premake.vstudio.vc2010 | |
230 | + vc2010.filteridgroup = function(prj) | |
231 | + local filters = { } | |
232 | + local filterfound = false | |
233 | + | |
234 | + for file in premake.project.eachfile(prj) do | |
235 | + -- split the path into its component parts | |
236 | + local folders = string.explode(file.vpath, "/", true) | |
237 | + local path = "" | |
238 | + for i = 1, #folders - 1 do | |
239 | + -- element is only written if there *are* filters | |
240 | + if not filterfound then | |
241 | + filterfound = true | |
242 | + _p(1,"<ItemGroup>") | |
243 | + end | |
244 | + | |
245 | + path = path .. folders[i] | |
246 | + | |
247 | + -- have I seen this path before? | |
248 | + if not filters[path] then | |
249 | + local seed = path .. (prj.uuid or "") | |
250 | + local deterministic_uuid = os.str2uuid(seed) | |
251 | + filters[path] = true | |
252 | + _p(2, '<Filter Include="%s">', path) | |
253 | + _p(3, "<UniqueIdentifier>{%s}</UniqueIdentifier>", deterministic_uuid) | |
254 | + _p(2, "</Filter>") | |
255 | + end | |
256 | + | |
257 | + -- prepare for the next subfolder | |
258 | + path = path .. "\\" | |
259 | + end | |
260 | + end | |
261 | + | |
262 | + if filterfound then | |
263 | + _p(1,"</ItemGroup>") | |
264 | + end | |
265 | + end | |
266 | + end | |
267 | + -- Name the project files after their VS version | |
268 | + local orig_getbasename = premake.project.getbasename | |
269 | + premake.project.getbasename = function(prjname, pattern) | |
270 | + -- 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 | |
271 | + if _ACTION then | |
272 | + name_map = {vs2005 = "vs8", vs2008 = "vs9", vs2010 = "vs10", vs2012 = "vs11", vs2013 = "vs12", vs2015 = "vs14", vs2017 = "vs15", vs2019 = "vs16", vs2022 = "vs17"} | |
273 | + if name_map[_ACTION] then | |
274 | + pattern = pattern:gsub("%%%%", "%%%%." .. name_map[_ACTION]) | |
275 | + else | |
276 | + pattern = pattern:gsub("%%%%", "%%%%." .. _ACTION) | |
277 | + end | |
278 | + end | |
279 | + return orig_getbasename(prjname, pattern) | |
280 | + end | |
281 | + -- Premake4 sets the PDB file name for the compiler's PDB to the default | |
282 | + -- value used by the linker's PDB. This causes error C1052 on VS2017. Fix it. | |
283 | + -- But this also fixes up certain other areas of the generated project. The idea | |
284 | + -- here is to catch the original _p() invocations, evaluate the arguments and | |
285 | + -- then act based on those, using orig_p() as a standin during a call to the | |
286 | + -- underlying premake.vs2010_vcxproj() function ;-) | |
287 | + local orig_premake_vs2010_vcxproj = premake.vs2010_vcxproj | |
288 | + premake.vs2010_vcxproj = function(prj) | |
289 | + -- The whole stunt below is necessary in order to modify the resource_compile() | |
290 | + -- output. Given it's a local function we have to go through hoops. | |
291 | + local orig_p = _G._p | |
292 | + local besilent = false | |
293 | + -- We patch the global _p() function | |
294 | + _G._p = function(indent, msg, first, ...) | |
295 | + -- Look for non-empty messages and narrow it down by the indent values | |
296 | + if msg ~= nil then | |
297 | + if msg:match("<ProgramDataBaseFileName>[^<]+</ProgramDataBaseFileName>") then | |
298 | + return -- we want to suppress these | |
299 | + end | |
300 | + if indent == 2 then | |
301 | + if msg == '<ClCompile Include=\"%s\">' and first == "delayload-stubs\\ntdll-delayed-stubs.c" then | |
302 | + orig_p(indent, msg, first, ...) -- what was originally supposed to be output | |
303 | + orig_p(indent+1, "<ExcludedFromBuild>true</ExcludedFromBuild>") | |
304 | + return | |
305 | + end | |
306 | + if msg == "<RootNamespace>%s</RootNamespace>" then | |
307 | + local sdkmap = {vs2015 = "8.1", vs2017 = "10.0.17763.0", vs2019 = "10.0", vs2022 = "10.0"} | |
308 | + if (not _ACTION) or (not sdkmap[_ACTION]) then -- should not happen, but tread carefully anyway | |
309 | + orig_p(indent, msg, first, ...) -- what was originally supposed to be output | |
310 | + return | |
311 | + end | |
312 | + local sdkver = _OPTIONS["sdkver"] or sdkmap[_ACTION] | |
313 | + orig_p(indent, msg, first, ...) -- what was originally supposed to be output | |
314 | + orig_p(indent, "<WindowsTargetPlatformVersion>%s</WindowsTargetPlatformVersion>", sdkver) | |
315 | + return | |
316 | + end | |
317 | + if msg == "<PlatformToolset>%s</PlatformToolset>" then | |
318 | + if (_OPTIONS["clang"] ~= nil) and (_ACTION == "vs2017") then | |
319 | + if _OPTIONS["xp"] ~= nil then | |
320 | + print "WARNING: The --clang option takes precedence over --xp, therefore picking v141_clang_c2 toolset." | |
321 | + end | |
322 | + 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." | |
323 | + orig_p(indent, msg, "v141_clang_c2") | |
324 | + return | |
325 | + elseif (_OPTIONS["clang"] ~= nil) and (_ACTION >= "vs2019") then | |
326 | + if _OPTIONS["xp"] ~= nil then | |
327 | + print "WARNING: The --clang option takes precedence over --xp, therefore picking ClangCL toolset." | |
328 | + end | |
329 | + orig_p(indent, msg, "ClangCL") | |
330 | + return | |
331 | + elseif _OPTIONS["xp"] ~= nil then | |
332 | + local toolsets = { vs2012 = "v110", vs2013 = "v120", vs2015 = "v140", vs2017 = "v141", vs2019 = "v142", vs2022 = "v143" } | |
333 | + local toolset = toolsets[_ACTION] | |
334 | + if toolset then | |
335 | + if _OPTIONS["xp"] and toolset >= "v141" then | |
336 | + toolset = "v141" -- everything falls back to the VS2017 XP toolset for more recent VS | |
337 | + end | |
338 | + orig_p(indent,"<PlatformToolset>%s_xp</PlatformToolset>", toolset) | |
339 | + return | |
340 | + end | |
341 | + end | |
342 | + end | |
343 | + elseif indent == 3 then | |
344 | + -- This is what vanilla VS would output it as, so let's try to align with that | |
345 | + if msg == "<PrecompiledHeader></PrecompiledHeader>" then | |
346 | + orig_p(indent, "<PrecompiledHeader>") | |
347 | + orig_p(indent, "</PrecompiledHeader>") | |
348 | + return | |
349 | + end | |
350 | + end | |
351 | + end | |
352 | + if not besilent then -- should we be silent (i.e. suppress default output)? | |
353 | + orig_p(indent, msg, first, ...) | |
354 | + end | |
355 | + end | |
356 | + orig_premake_vs2010_vcxproj(prj) | |
357 | + _G._p = orig_p -- restore in any case | |
358 | + end | |
359 | + -- ... same as above but for VS200x this time | |
360 | + local function wrap_remove_pdb_attribute(origfunc) | |
361 | + local fct = function(cfg) | |
362 | + local old_captured = io.captured -- save io.captured state | |
363 | + io.capture() -- this sets io.captured = "" | |
364 | + origfunc(cfg) | |
365 | + local captured = io.endcapture() | |
366 | + assert(captured ~= nil) | |
367 | + captured = captured:gsub('%s+ProgramDataBaseFileName=\"[^"]+\"', "") | |
368 | + if old_captured ~= nil then | |
369 | + io.captured = old_captured .. captured -- restore outer captured state, if any | |
370 | + else | |
371 | + io.write(captured) | |
372 | + end | |
373 | + end | |
374 | + return fct | |
375 | + end | |
376 | + premake.vstudio.vc200x.VCLinkerTool = wrap_remove_pdb_attribute(premake.vstudio.vc200x.VCLinkerTool) | |
377 | + premake.vstudio.vc200x.toolmap.VCLinkerTool = premake.vstudio.vc200x.VCLinkerTool -- this is important as well | |
378 | + premake.vstudio.vc200x.VCCLCompilerTool = wrap_remove_pdb_attribute(premake.vstudio.vc200x.VCCLCompilerTool) | |
379 | + premake.vstudio.vc200x.toolmap.VCCLCompilerTool = premake.vstudio.vc200x.VCCLCompilerTool -- this is important as well | |
380 | + -- Override the object directory paths ... don't make them "unique" inside premake4 | |
381 | + local orig_gettarget = premake.gettarget | |
382 | + premake.gettarget = function(cfg, direction, pathstyle, namestyle, system) | |
383 | + local r = orig_gettarget(cfg, direction, pathstyle, namestyle, system) | |
384 | + if (cfg.objectsdir) and (cfg.objdir) then | |
385 | + cfg.objectsdir = cfg.objdir | |
386 | + end | |
387 | + return r | |
388 | + end | |
389 | + -- Silently suppress generation of the .user files ... | |
390 | + local orig_generate = premake.generate | |
391 | + premake.generate = function(obj, filename, callback) | |
392 | + if filename:find(".vcproj.user") or filename:find(".vcxproj.user") then | |
393 | + return | |
394 | + end | |
395 | + orig_generate(obj, filename, callback) | |
396 | + end | |
397 | + -- Fix up premake.getlinks() to not do stupid stuff with object files we pass | |
398 | + local orig_premake_getlinks = premake.getlinks | |
399 | + premake.getlinks = function(cfg, kind, part) | |
400 | + local origret = orig_premake_getlinks(cfg, kind, part) | |
401 | + local ret = {} | |
402 | + for k,v in ipairs(origret) do | |
403 | + local dep = v:gsub(".obj.lib", ".obj") | |
404 | + dep = dep:gsub(".lib.lib", ".lib") | |
405 | + table.insert(ret, dep) | |
406 | + end | |
407 | + return ret | |
408 | + end | |
409 | + | |
410 | + -- Remove an option altogether or some otherwise accepted values for that option | |
411 | + local function remove_allowed_optionvalues(option, values_toremove) | |
412 | + if premake.option.list[option] ~= nil then | |
413 | + if values_toremove == nil then | |
414 | + premake.option.list[option] = nil | |
415 | + return | |
416 | + end | |
417 | + if premake.option.list.platform["allowed"] ~= nil then | |
418 | + local allowed = premake.option.list[option].allowed | |
419 | + for i = #allowed, 1, -1 do | |
420 | + if values_toremove[allowed[i][1]] then | |
421 | + table.remove(allowed, i) | |
422 | + end | |
423 | + end | |
424 | + end | |
425 | + end | |
426 | + end | |
427 | + | |
428 | + local function remove_action(action) | |
429 | + if premake.action.list[action] ~= nil then | |
430 | + premake.action.list[action] = nil | |
431 | + end | |
432 | + end | |
433 | + | |
434 | + -- Remove some unwanted/outdated options | |
435 | + remove_allowed_optionvalues("dotnet") | |
436 | + remove_allowed_optionvalues("platform", { universal = 0, universal32 = 0, universal64 = 0, ps3 = 0, xbox360 = 0, }) | |
437 | + remove_allowed_optionvalues("os") -- ... , { bsd = 0, haiku = 0, linux = 0, macosx = 0, solaris = 0, } | |
438 | + remove_allowed_optionvalues("cc") | |
439 | + -- ... and actions (mainly because they are untested) | |
440 | + 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 | |
441 | + remove_action(k) | |
442 | + end | |
443 | +end |