cscg22-gearboy

CSCG 2022 Challenge 'Gearboy'
git clone https://git.sinitax.com/sinitax/cscg22-gearboy
Log | Files | Refs | sfeed.txt

premake4.lua (19887B)


      1-- Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
      2--
      3-- This software is provided 'as-is', without any express or implied
      4-- warranty.  In no event will the authors be held liable for any damages
      5-- arising from the use of this software.
      6--
      7-- Permission is granted to anyone to use this software for any purpose,
      8-- including commercial applications, and to alter it and redistribute it
      9-- freely.
     10--
     11-- Meta-build system using premake created and maintained by
     12-- Benjamin Henning <b.henning@digipen.edu>
     13
     14--[[
     15premake4.lua
     16
     17	This script sets up the entire premake system. It's responsible for executing
     18	all of the definition scripts for the SDL2 library and the entire test suite,
     19	or demos for the iOS platform. It handles each specific platform and uses the
     20	setup state to generate both the configuration header file needed to build
     21	SDL2 and the premake lua script to generate the target project files.
     22]]
     23
     24-- string utility functions
     25dofile "util/sdl_string.lua"
     26-- utility file wrapper for some useful functions
     27dofile "util/sdl_file.lua"
     28-- system for defining SDL projects
     29dofile "util/sdl_projects.lua"
     30-- offers a utility function for finding dependencies specifically on windows
     31dofile "util/sdl_depends.lua"
     32-- system for generating a *config.h file used to build the SDL2 library
     33dofile "util/sdl_gen_config.lua"
     34-- functions to handle complicated dependency checks using CMake-esque functions
     35dofile "util/sdl_check_compile.lua"
     36-- a list of dependency functions for the SDL2 project and any other projects
     37dofile "util/sdl_dependency_checkers.lua"
     38
     39-- the following are various options for configuring the meta-build system
     40newoption {
     41	trigger = "to",
     42	value   = "path",
     43	description = "Set the base output directory for the generated and executed lua file."
     44}
     45
     46newoption {
     47	trigger = "mingw",
     48	description = "Runs the premake generation script targeted to MinGW."
     49}
     50
     51newoption {
     52	trigger = "cygwin",
     53	description = "Runs the premake generation script targeted to Cygwin."
     54}
     55
     56newoption {
     57	trigger = "ios",
     58	description = "Runs the premake generation script targeted to iOS."
     59}
     60
     61-- determine the localized destination path
     62local baseLoc = "./"
     63if _OPTIONS["to"] then
     64	baseLoc = _OPTIONS["to"]:gsub("\\", "/")
     65end
     66
     67local deps = SDL_getDependencies()
     68for _,v in ipairs(deps) do
     69	newoption {
     70		trigger = v:lower(),
     71		description = "Force on the dependency: " .. v
     72	}
     73end
     74
     75-- clean action
     76if _ACTION == "clean" then
     77	-- this is kept the way it is because premake's default method of cleaning the
     78	-- build tree is not very good standalone, whereas the following correctly
     79	-- cleans every build option
     80	print("Cleaning the build environment...")
     81	os.rmdir(baseLoc .. "/SDL2")
     82	os.rmdir(baseLoc .. "/SDL2main")
     83	os.rmdir(baseLoc .. "/SDL2test")
     84	os.rmdir(baseLoc .. "/tests")
     85	os.rmdir(baseLoc .. "/Demos")
     86	os.rmdir(baseLoc .. "/ipch") -- sometimes shows up
     87	os.remove(baseLoc .. "/SDL.sln")
     88	os.remove(baseLoc .. "/SDL.suo")
     89	os.remove(baseLoc .. "/SDL.v11.suo")
     90	os.remove(baseLoc .. "/SDL.sdf")
     91	os.remove(baseLoc .. "/SDL.ncb")
     92	os.remove(baseLoc .. "/SDL-gen.lua")
     93	os.remove(baseLoc .. "/SDL_config_premake.h")
     94	os.remove(baseLoc .. "/Makefile")
     95	os.rmdir(baseLoc .. "/SDL.xcworkspace")
     96	os.exit()
     97end
     98
     99-- only run through standard execution if not in help mode
    100if _OPTIONS["help"] == nil then
    101	-- load all of the project definitions
    102	local results = os.matchfiles("projects/**.lua")
    103	for _,dir in ipairs(results) do
    104		dofile(dir)
    105	end
    106
    107	-- figure out which configuration template to use
    108	local premakeConfigHeader = baseLoc .. "/SDL_config_premake.h"
    109	-- minimal configuration is the default
    110	local premakeTemplateHeader = "./config/SDL_config_minimal.template.h"
    111	if SDL_getos() == "windows" or SDL_getos() == "mingw" then
    112		premakeTemplateHeader = "./config/SDL_config_windows.template.h"
    113	elseif SDL_getos() == "macosx" then
    114		premakeTemplateHeader = "./config/SDL_config_macosx.template.h"
    115	elseif SDL_getos() == "ios" then
    116		premakeTemplateHeader = "./config/SDL_config_iphoneos.template.h"
    117	elseif os.get() == "linux" then
    118		premakeTemplateHeader = "./config/SDL_config_linux.template.h"
    119	elseif SDL_getos() == "cygwin" then
    120		premakeTemplateHeader = "./config/SDL_config_cygwin.template.h"
    121	end
    122
    123	local genFile = baseLoc .. "/SDL-gen.lua"
    124	local file = fileopen(genFile, "wt")
    125	print("Generating " .. genFile .. "...")
    126	-- begin generating the config header file
    127	startGeneration(premakeConfigHeader, premakeTemplateHeader)
    128
    129	-- begin generating the actual premake script
    130	file:print(0, "-- Premake script generated by Simple DirectMedia Layer meta-build script")
    131	file:print(1, 'solution "SDL"')
    132	local platforms = { }
    133	local platformsIndexed = { }
    134		for n,p in pairs(projects) do
    135			if p.platforms and #p.platforms ~= 0 then
    136				for k,v in pairs(p.platforms) do
    137					platforms[v] = true
    138				end
    139			end
    140		end
    141		for n,v in pairs(platforms) do
    142			platformsIndexed[#platformsIndexed + 1] = n
    143		end
    144		file:print(2, implode(platformsIndexed, 'platforms {', '"', '"', ', ', '}'))
    145		file:print(2, 'configurations { "Debug", "Release" }')
    146		for n,p in pairs(projects) do
    147			if p.compat then
    148				local proj = {}
    149				if p.projectLocation ~= nil then
    150					proj.location = p.projectLocation .. "/" .. p.name
    151				else
    152					proj.location = p.name .. "/"
    153				end
    154				proj.includedirs = { path.getrelative(baseLoc,
    155					path.getdirectory(premakeConfigHeader)),
    156					path.getrelative(baseLoc, "../include") }
    157				proj.libdirs = { }
    158				proj.files = { }
    159				local links = { }
    160				local dbgCopyTable = { }
    161				local relCopyTable = { }
    162				-- custom links that shouldn't exist...
    163				-- (these should always happen before dependencies)
    164				if p.customLinks ~= nil then
    165					for k,lnk in pairs(p.customLinks) do
    166						table.insert(links, lnk)
    167					end
    168				end
    169				-- setup project dependencies
    170				local dependencyLocs = { }
    171				if p.projectDependencies ~= nil and #p.projectDependencies ~= 0 then
    172					for k,projname in pairs(p.projectDependencies) do
    173						local depproj = projects[projname]
    174						-- validation that it exists and can be linked to
    175						if depproj ~= nil and (depproj.kind == "SharedLib" or depproj.kind == "StaticLib") then
    176							if depproj.kind == "SharedLib" then
    177								local deplocation = nil
    178								if depproj.projectLocation ~= nil then
    179									deplocation = depproj.projectLocation .. "/" .. p.name
    180								else
    181									deplocation = depproj.name .. "/"
    182								end
    183								table.insert(dependencyLocs, { location = deplocation, name = projname })
    184							else -- static lib
    185								-- we are now dependent on everything the static lib is dependent on
    186								if depproj.customLinks ~= nil then
    187									for k,lnk in pairs(depproj.customLinks) do
    188										table.insert(links, lnk)
    189									end
    190								end
    191								-- also include links from dependencies
    192								for i,d in pairs(depproj.dependencyTree) do
    193									if d.links then
    194										for k,v in pairs(d.links) do
    195											local propPath = v:gsub("\\", "/")
    196											table.insert(links, propPath)
    197										end
    198									end
    199								end
    200							end
    201							-- finally, depend on the project itself
    202							table.insert(links, projname)
    203						elseif depproj == nil then
    204							print("Warning: Missing external dependency for project: ".. p.name ..
    205								". Be sure you setup project dependencies in a logical order.")
    206						else
    207							print("Warning: Cannot link " .. p.name .. " to second project " ..
    208								projname .. " because the second project is not a library.")
    209						end
    210					end
    211				end
    212				-- iterate across all root directories, matching source directories
    213				local dirs = createDirTable(p.sourcedir)
    214				-- but first, handle any files specifically set in the project, rather than
    215				-- its dependencies
    216				-- register c and h files in this directory
    217				if (p.files ~= nil and #p.files ~= 0) or (p.paths ~= nil and #p.paths ~= 0) then
    218					-- handle all lists of files
    219					if p.files ~= nil and #p.files ~= 0 then
    220						for k,filepat in pairs(p.files) do
    221							for k,f in pairs(os.matchfiles(p.sourcedir .. filepat)) do
    222								table.insert(proj.files, path.getrelative(baseLoc, f))
    223							end
    224						end
    225					end -- end props files if
    226					-- add all .c/.h files from each path
    227					-- handle all related paths
    228					if p.paths ~= nil and #p.paths ~= 0 then
    229						for j,filepat in ipairs(p.paths) do
    230							for k,f in pairs(os.matchfiles(p.sourcedir .. filepat .. "*.c")) do
    231								table.insert(proj.files, path.getrelative(baseLoc, f))
    232							end
    233							for k,f in pairs(os.matchfiles(p.sourcedir .. filepat .. "*.h")) do
    234								table.insert(proj.files, path.getrelative(baseLoc, f))
    235							end
    236							-- mac osx
    237							for k,f in pairs(os.matchfiles(p.sourcedir .. filepat .. "*.m")) do
    238								table.insert(proj.files, path.getrelative(baseLoc, f))
    239							end
    240						end
    241					end -- end of props paths if
    242				end -- end of check for files/paths in main project
    243				-- if this project has any configuration flags, add them to the current file
    244				if p.config then
    245					addConfig(p.config)
    246				end
    247				-- now, handle files and paths for dependencies
    248				for i,props in ipairs(p.dependencyTree) do
    249					if props.compat then
    250						-- register c and h files in this directory
    251						-- handle all lists of files
    252						if props.files ~= nil and #props.files ~= 0 then
    253							for k,filepat in pairs(props.files) do
    254								for k,f in pairs(os.matchfiles(p.sourcedir .. filepat)) do
    255									table.insert(proj.files, path.getrelative(baseLoc, f))
    256								end
    257							end
    258						end -- end props files if
    259						-- add all .c/.h files from each path
    260						-- handle all related paths
    261						if props.paths ~= nil and #props.paths ~= 0 then
    262							for j,filepat in ipairs(props.paths) do
    263								for k,f in pairs(os.matchfiles(p.sourcedir .. filepat .. "*.c")) do
    264									table.insert(proj.files, path.getrelative(baseLoc, f))
    265								end
    266								for k,f in pairs(os.matchfiles(p.sourcedir .. filepat .. "*.h")) do
    267									table.insert(proj.files, path.getrelative(baseLoc, f))
    268								end
    269								-- mac osx
    270								for k,f in pairs(os.matchfiles(p.sourcedir .. filepat .. "*.m")) do
    271									table.insert(proj.files, path.getrelative(baseLoc, f))
    272								end
    273							end
    274						end -- end of props paths if
    275						-- if this dependency has any special configuration flags, add 'em
    276						if props.config then
    277							addConfig(props.config)
    278						end -- end of props config if check
    279					end -- end check for compatibility
    280				end -- end of props loop
    281				--local debugConfig = configuration("Debug")
    282				local debugConfig = {}
    283				local releaseConfig = {}
    284				debugConfig.defines = { "USING_PREMAKE_CONFIG_H", "_DEBUG" }
    285				releaseConfig.defines = { "USING_PREMAKE_CONFIG_H", "NDEBUG" }
    286				-- setup per-project defines
    287				if p.defines ~= nil then
    288					for k,def in pairs(p.defines) do
    289						table.insert(debugConfig.defines, def)
    290						table.insert(releaseConfig.defines, def)
    291					end
    292				end
    293				debugConfig.buildoptions = { }
    294				if SDL_getos() == "windows" then
    295					table.insert(debugConfig.buildoptions, "/MDd")
    296				end
    297				debugConfig.linkoptions = { }
    298				releaseConfig.buildoptions = {}
    299				releaseConfig.linkoptions = {}
    300				local baseBuildDir = "/Build"
    301				if os.get() == "windows" then
    302					baseBuildDir = "/Win32"
    303				end
    304				debugConfig.flags = { "Symbols" }
    305				debugConfig.targetdir = proj.location .. baseBuildDir .. "/Debug"
    306				releaseConfig.flags = { "OptimizeSpeed" }
    307				releaseConfig.targetdir = proj.location .. baseBuildDir .. "/Release"
    308				-- setup postbuild options
    309				local dbgPostbuildcommands = { }
    310				local relPostbuildcommands = { }
    311				-- handle copying depended shared libraries to correct folders
    312				if os.get() == "windows" then
    313					for k,deploc in pairs(dependencyLocs) do
    314						table.insert(dbgCopyTable, { src = deploc.location .. baseBuildDir .. "/Debug/" .. deploc.name .. ".dll",
    315							dst = debugConfig.targetdir .. "/" .. deploc.name .. ".dll" })
    316						table.insert(relCopyTable, { src = deploc.location .. baseBuildDir .. "/Release/" .. deploc.name .. ".dll",
    317							dst = releaseConfig.targetdir .. "/" .. deploc.name .. ".dll" })
    318					end
    319				end
    320				if p.copy ~= nil then
    321					for k,file in pairs(p.copy) do
    322						-- the following builds relative paths native to the current system for copying, other
    323						-- than the copy command itself, this is essentially cross-platform for paths
    324					
    325						-- all custom copies should be relative to the current working directory
    326						table.insert(dbgCopyTable, { src = path.getrelative(baseLoc, p.sourcedir .. "/" .. file), dst = debugConfig.targetdir .. "/" .. file })
    327						table.insert(relCopyTable, { src = path.getrelative(baseLoc, p.sourcedir .. "/" .. file), dst = releaseConfig.targetdir .. "/" .. file })
    328					end
    329				end
    330				for k,file in pairs(dbgCopyTable) do
    331					-- all copies should be relative to project location, based on platform
    332					local relLocation = "./"
    333					--if os.get() == "windows" then
    334						relLocation = proj.location
    335					--end
    336					local fromPath = "./" .. path.getrelative(relLocation, file.src)
    337					local toPath = "./" .. path.getrelative(relLocation, file.dst)
    338					local toPathParent = path.getdirectory(toPath)
    339					local copyCommand = "cp"
    340					local destCheck = "if [ ! -d \\\"" .. toPathParent .. "\\\" ]; then mkdir -p \\\"" .. toPathParent .. "\\\"; fi"
    341					if SDL_getos() ~= "windows" and fromPath:find("*") ~= nil then
    342						-- to path must be a directory for * copies
    343						toPath = path.getdirectory(toPath)
    344					end
    345					if SDL_getos() == "windows" then
    346						fromPath = path.translate(fromPath, "/"):gsub("/", "\\\\")
    347						toPath = path.translate(toPath, "/"):gsub("/", "\\\\")
    348						toPathParent = path.translate(toPathParent, "/"):gsub("/", "\\\\")
    349						copyCommand = "copy"
    350						destCheck = "if not exist \\\"" .. toPathParent .. "\\\" ( mkdir \\\"" .. toPathParent .. "\\\" )"
    351					else
    352						fromPath = path.translate(fromPath, nil):gsub("\\", "/")
    353						toPath = path.translate(toPath, nil):gsub("\\", "/")
    354					end
    355					-- command will check for destination directory to exist and, if it doesn't,
    356					-- it will make the directory and then copy over any assets
    357					local quotedFromPath = fromPath
    358					if SDL_getos() == "windows" or fromPath:find("*") == nil then
    359						quotedFromPath = '\\"' .. quotedFromPath .. '\\"'
    360					end
    361					table.insert(dbgPostbuildcommands, destCheck)
    362					table.insert(dbgPostbuildcommands,
    363						copyCommand .. " " ..
    364						quotedFromPath .. " \\\"" ..
    365						toPath .. "\\\"")
    366				end
    367				for k,file in pairs(relCopyTable) do
    368					-- all copies should be relative to project location, based on platform
    369					local relLocation = "./"
    370					relLocation = proj.location
    371					local fromPath = "./" .. path.getrelative(relLocation, file.src)
    372					local toPath = "./" .. path.getrelative(relLocation, file.dst)
    373					local toPathParent = path.getdirectory(toPath)
    374					local copyCommand = "cp"
    375					local destCheck = "if [ ! -d \\\"" .. toPathParent .. "\\\" ]; then mkdir -p \\\"" .. toPathParent .. "\\\"; fi"
    376					if SDL_getos() ~= "windows" and fromPath:find("*") ~= nil then
    377						-- to path must be a directory for * copies
    378						toPath = path.getdirectory(toPath)
    379					end
    380					if SDL_getos() == "windows" then
    381						fromPath = path.translate(fromPath, "/"):gsub("/", "\\\\")
    382						toPath = path.translate(toPath, "/"):gsub("/", "\\\\")
    383						toPathParent = path.translate(toPathParent, "/"):gsub("/", "\\\\")
    384						copyCommand = "copy"
    385						destCheck = "if not exist \\\"" .. toPathParent .. "\\\" ( mkdir \\\"" .. toPathParent .. "\\\" )"
    386					else
    387						fromPath = path.translate(fromPath, nil):gsub("\\", "/")
    388						toPath = path.translate(toPath, nil):gsub("\\", "/")
    389					end
    390					-- command will check for destination directory to exist and, if it doesn't,
    391					-- it will make the directory and then copy over any assets
    392					local quotedFromPath = fromPath
    393					if SDL_getos() == "windows" or fromPath:find("*") == nil then
    394						quotedFromPath = '\\"' .. quotedFromPath .. '\\"'
    395					end
    396					table.insert(relPostbuildcommands, destCheck)
    397					table.insert(relPostbuildcommands,
    398						copyCommand .. " " ..
    399						quotedFromPath .. " \\\"" ..
    400						toPath .. "\\\"")
    401				end
    402				debugConfig.postbuildcommands = dbgPostbuildcommands
    403				debugConfig.links = links
    404				releaseConfig.postbuildcommands = relPostbuildcommands
    405				releaseConfig.links = links -- release links?
    406				for i,d in pairs(p.dependencyTree) do
    407					if d.includes then
    408						for k,v in pairs(d.includes) do
    409							local propPath = v:gsub("\\", "/")
    410							proj.includedirs[propPath] = propPath
    411						end
    412					end
    413					if d.libs then
    414						for k,v in pairs(d.libs) do
    415							local propPath = v:gsub("\\", "/")
    416							proj.libdirs[propPath] = propPath
    417						end
    418					end
    419					if d.links then
    420						for k,v in pairs(d.links) do
    421							local propPath = v:gsub("\\", "/")
    422							debugConfig.links[#debugConfig.links + 1] = propPath
    423						end
    424					end
    425				end
    426				if #proj.files > 0 then
    427					file:print(1, 'project "' .. p.name .. '"')
    428					file:print(2, 'targetname "' .. p.name .. '"')
    429					-- note: commented out because I think this hack is unnecessary
    430					--if iOSMode and p.kind == "ConsoleApp" then
    431						-- hack for iOS where we cannot build "tools"/ConsoleApps in
    432						-- Xcode for iOS, so we convert them over to WindowedApps
    433					--	p.kind = "WindowedApp"
    434					--end
    435					file:print(2, 'kind "' .. p.kind .. '"')
    436					file:print(2, 'language "' .. p.language .. '"')
    437					file:print(2, 'location "' .. proj.location .. '"')
    438					file:print(2, 'flags { "NoExceptions" }') -- NoRTTI
    439					file:print(2, 'buildoptions { }')--"/GS-" }')
    440					file:print(2, implode(proj.includedirs, 'includedirs {', '"', '"', ', ', '}'))
    441					file:print(2, implode(proj.libdirs, 'libdirs {', '"', '"', ', ', '}'))
    442					file:print(2, implode(proj.files, 'files {', '"', '"', ', ', '}'))
    443					-- debug configuration
    444					file:print(2, 'configuration "Debug"')
    445					file:print(3, 'targetdir "' .. debugConfig.targetdir .. '"')
    446					-- debug dir is relative to the solution's location
    447					file:print(3, 'debugdir "' .. debugConfig.targetdir .. '"')
    448					file:print(3, implode(debugConfig.defines, 'defines {', '"', '"', ', ', '}'))
    449					file:print(3, implode(debugConfig.links, "links {", '"', '"', ', ', "}"))
    450					if SDL_getos() == "mingw" then
    451						-- static runtime
    452						file:print(3, 'linkoptions { "-lmingw32 -static-libgcc" }')
    453					end
    454					if SDL_getos() == "cygwin" then
    455						file:print(3, 'linkoptions { "-static-libgcc" }')
    456					end
    457					file:print(3, implode(debugConfig.flags, "flags {", '"', '"', ', ', "}"))
    458					file:print(3, implode(debugConfig.postbuildcommands, "postbuildcommands {", '"', '"', ', ', "}"))
    459					-- release configuration
    460					file:print(2, 'configuration "Release"')
    461					file:print(3, 'targetdir "' .. releaseConfig.targetdir .. '"')
    462					-- debug dir is relative to the solution's location
    463					file:print(3, 'debugdir "' .. releaseConfig.targetdir .. '"')
    464					file:print(3, implode(releaseConfig.defines, 'defines {', '"', '"', ', ', '}'))
    465					file:print(3, implode(releaseConfig.links, "links {", '"', '"', ', ', "}"))
    466					if SDL_getos() == "mingw" then
    467						-- static runtime
    468						file:print(3, 'linkoptions { "-lmingw32 -static-libgcc" }')
    469					end
    470					file:print(3, implode(releaseConfig.flags, "flags {", '"', '"', ', ', "}"))
    471					file:print(3, implode(releaseConfig.postbuildcommands, "postbuildcommands {", '"', '"', ', ', "}"))
    472				end -- end check for valid project (files to build)
    473			end -- end compatibility check for projects
    474		end -- end for loop for projects
    475
    476	endGeneration() -- finish generating the config header file
    477	file:close()
    478
    479	-- generation is over, now execute the generated file, setup the premake
    480	-- solution, and let premake execute the action and generate the project files
    481	dofile(genFile)
    482end -- end check for not being in help mode