123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482 |
- -- Copyright (C) 1997-2016 Sam Lantinga <slouken@libsdl.org>
- --
- -- This software is provided 'as-is', without any express or implied
- -- warranty. In no event will the authors be held liable for any damages
- -- arising from the use of this software.
- --
- -- Permission is granted to anyone to use this software for any purpose,
- -- including commercial applications, and to alter it and redistribute it
- -- freely.
- --
- -- Meta-build system using premake created and maintained by
- -- Benjamin Henning <b.henning@digipen.edu>
- --[[
- premake4.lua
- This script sets up the entire premake system. It's responsible for executing
- all of the definition scripts for the SDL2 library and the entire test suite,
- or demos for the iOS platform. It handles each specific platform and uses the
- setup state to generate both the configuration header file needed to build
- SDL2 and the premake lua script to generate the target project files.
- ]]
- -- string utility functions
- dofile "util/sdl_string.lua"
- -- utility file wrapper for some useful functions
- dofile "util/sdl_file.lua"
- -- system for defining SDL projects
- dofile "util/sdl_projects.lua"
- -- offers a utility function for finding dependencies specifically on windows
- dofile "util/sdl_depends.lua"
- -- system for generating a *config.h file used to build the SDL2 library
- dofile "util/sdl_gen_config.lua"
- -- functions to handle complicated dependency checks using CMake-esque functions
- dofile "util/sdl_check_compile.lua"
- -- a list of dependency functions for the SDL2 project and any other projects
- dofile "util/sdl_dependency_checkers.lua"
- -- the following are various options for configuring the meta-build system
- newoption {
- trigger = "to",
- value = "path",
- description = "Set the base output directory for the generated and executed lua file."
- }
- newoption {
- trigger = "mingw",
- description = "Runs the premake generation script targeted to MinGW."
- }
- newoption {
- trigger = "cygwin",
- description = "Runs the premake generation script targeted to Cygwin."
- }
- newoption {
- trigger = "ios",
- description = "Runs the premake generation script targeted to iOS."
- }
- -- determine the localized destination path
- local baseLoc = "./"
- if _OPTIONS["to"] then
- baseLoc = _OPTIONS["to"]:gsub("\\", "/")
- end
- local deps = SDL_getDependencies()
- for _,v in ipairs(deps) do
- newoption {
- trigger = v:lower(),
- description = "Force on the dependency: " .. v
- }
- end
- -- clean action
- if _ACTION == "clean" then
- -- this is kept the way it is because premake's default method of cleaning the
- -- build tree is not very good standalone, whereas the following correctly
- -- cleans every build option
- print("Cleaning the build environment...")
- os.rmdir(baseLoc .. "/SDL2")
- os.rmdir(baseLoc .. "/SDL2main")
- os.rmdir(baseLoc .. "/SDL2test")
- os.rmdir(baseLoc .. "/tests")
- os.rmdir(baseLoc .. "/Demos")
- os.rmdir(baseLoc .. "/ipch") -- sometimes shows up
- os.remove(baseLoc .. "/SDL.sln")
- os.remove(baseLoc .. "/SDL.suo")
- os.remove(baseLoc .. "/SDL.v11.suo")
- os.remove(baseLoc .. "/SDL.sdf")
- os.remove(baseLoc .. "/SDL.ncb")
- os.remove(baseLoc .. "/SDL-gen.lua")
- os.remove(baseLoc .. "/SDL_config_premake.h")
- os.remove(baseLoc .. "/Makefile")
- os.rmdir(baseLoc .. "/SDL.xcworkspace")
- os.exit()
- end
- -- only run through standard execution if not in help mode
- if _OPTIONS["help"] == nil then
- -- load all of the project definitions
- local results = os.matchfiles("projects/**.lua")
- for _,dir in ipairs(results) do
- dofile(dir)
- end
- -- figure out which configuration template to use
- local premakeConfigHeader = baseLoc .. "/SDL_config_premake.h"
- -- minimal configuration is the default
- local premakeTemplateHeader = "./config/SDL_config_minimal.template.h"
- if SDL_getos() == "windows" or SDL_getos() == "mingw" then
- premakeTemplateHeader = "./config/SDL_config_windows.template.h"
- elseif SDL_getos() == "macosx" then
- premakeTemplateHeader = "./config/SDL_config_macosx.template.h"
- elseif SDL_getos() == "ios" then
- premakeTemplateHeader = "./config/SDL_config_iphoneos.template.h"
- elseif os.get() == "linux" then
- premakeTemplateHeader = "./config/SDL_config_linux.template.h"
- elseif SDL_getos() == "cygwin" then
- premakeTemplateHeader = "./config/SDL_config_cygwin.template.h"
- end
- local genFile = baseLoc .. "/SDL-gen.lua"
- local file = fileopen(genFile, "wt")
- print("Generating " .. genFile .. "...")
- -- begin generating the config header file
- startGeneration(premakeConfigHeader, premakeTemplateHeader)
- -- begin generating the actual premake script
- file:print(0, "-- Premake script generated by Simple DirectMedia Layer meta-build script")
- file:print(1, 'solution "SDL"')
- local platforms = { }
- local platformsIndexed = { }
- for n,p in pairs(projects) do
- if p.platforms and #p.platforms ~= 0 then
- for k,v in pairs(p.platforms) do
- platforms[v] = true
- end
- end
- end
- for n,v in pairs(platforms) do
- platformsIndexed[#platformsIndexed + 1] = n
- end
- file:print(2, implode(platformsIndexed, 'platforms {', '"', '"', ', ', '}'))
- file:print(2, 'configurations { "Debug", "Release" }')
- for n,p in pairs(projects) do
- if p.compat then
- local proj = {}
- if p.projectLocation ~= nil then
- proj.location = p.projectLocation .. "/" .. p.name
- else
- proj.location = p.name .. "/"
- end
- proj.includedirs = { path.getrelative(baseLoc,
- path.getdirectory(premakeConfigHeader)),
- path.getrelative(baseLoc, "../include") }
- proj.libdirs = { }
- proj.files = { }
- local links = { }
- local dbgCopyTable = { }
- local relCopyTable = { }
- -- custom links that shouldn't exist...
- -- (these should always happen before dependencies)
- if p.customLinks ~= nil then
- for k,lnk in pairs(p.customLinks) do
- table.insert(links, lnk)
- end
- end
- -- setup project dependencies
- local dependencyLocs = { }
- if p.projectDependencies ~= nil and #p.projectDependencies ~= 0 then
- for k,projname in pairs(p.projectDependencies) do
- local depproj = projects[projname]
- -- validation that it exists and can be linked to
- if depproj ~= nil and (depproj.kind == "SharedLib" or depproj.kind == "StaticLib") then
- if depproj.kind == "SharedLib" then
- local deplocation = nil
- if depproj.projectLocation ~= nil then
- deplocation = depproj.projectLocation .. "/" .. p.name
- else
- deplocation = depproj.name .. "/"
- end
- table.insert(dependencyLocs, { location = deplocation, name = projname })
- else -- static lib
- -- we are now dependent on everything the static lib is dependent on
- if depproj.customLinks ~= nil then
- for k,lnk in pairs(depproj.customLinks) do
- table.insert(links, lnk)
- end
- end
- -- also include links from dependencies
- for i,d in pairs(depproj.dependencyTree) do
- if d.links then
- for k,v in pairs(d.links) do
- local propPath = v:gsub("\\", "/")
- table.insert(links, propPath)
- end
- end
- end
- end
- -- finally, depend on the project itself
- table.insert(links, projname)
- elseif depproj == nil then
- print("Warning: Missing external dependency for project: ".. p.name ..
- ". Be sure you setup project dependencies in a logical order.")
- else
- print("Warning: Cannot link " .. p.name .. " to second project " ..
- projname .. " because the second project is not a library.")
- end
- end
- end
- -- iterate across all root directories, matching source directories
- local dirs = createDirTable(p.sourcedir)
- -- but first, handle any files specifically set in the project, rather than
- -- its dependencies
- -- register c and h files in this directory
- if (p.files ~= nil and #p.files ~= 0) or (p.paths ~= nil and #p.paths ~= 0) then
- -- handle all lists of files
- if p.files ~= nil and #p.files ~= 0 then
- for k,filepat in pairs(p.files) do
- for k,f in pairs(os.matchfiles(p.sourcedir .. filepat)) do
- table.insert(proj.files, path.getrelative(baseLoc, f))
- end
- end
- end -- end props files if
- -- add all .c/.h files from each path
- -- handle all related paths
- if p.paths ~= nil and #p.paths ~= 0 then
- for j,filepat in ipairs(p.paths) do
- for k,f in pairs(os.matchfiles(p.sourcedir .. filepat .. "*.c")) do
- table.insert(proj.files, path.getrelative(baseLoc, f))
- end
- for k,f in pairs(os.matchfiles(p.sourcedir .. filepat .. "*.h")) do
- table.insert(proj.files, path.getrelative(baseLoc, f))
- end
- -- mac osx
- for k,f in pairs(os.matchfiles(p.sourcedir .. filepat .. "*.m")) do
- table.insert(proj.files, path.getrelative(baseLoc, f))
- end
- end
- end -- end of props paths if
- end -- end of check for files/paths in main project
- -- if this project has any configuration flags, add them to the current file
- if p.config then
- addConfig(p.config)
- end
- -- now, handle files and paths for dependencies
- for i,props in ipairs(p.dependencyTree) do
- if props.compat then
- -- register c and h files in this directory
- -- handle all lists of files
- if props.files ~= nil and #props.files ~= 0 then
- for k,filepat in pairs(props.files) do
- for k,f in pairs(os.matchfiles(p.sourcedir .. filepat)) do
- table.insert(proj.files, path.getrelative(baseLoc, f))
- end
- end
- end -- end props files if
- -- add all .c/.h files from each path
- -- handle all related paths
- if props.paths ~= nil and #props.paths ~= 0 then
- for j,filepat in ipairs(props.paths) do
- for k,f in pairs(os.matchfiles(p.sourcedir .. filepat .. "*.c")) do
- table.insert(proj.files, path.getrelative(baseLoc, f))
- end
- for k,f in pairs(os.matchfiles(p.sourcedir .. filepat .. "*.h")) do
- table.insert(proj.files, path.getrelative(baseLoc, f))
- end
- -- mac osx
- for k,f in pairs(os.matchfiles(p.sourcedir .. filepat .. "*.m")) do
- table.insert(proj.files, path.getrelative(baseLoc, f))
- end
- end
- end -- end of props paths if
- -- if this dependency has any special configuration flags, add 'em
- if props.config then
- addConfig(props.config)
- end -- end of props config if check
- end -- end check for compatibility
- end -- end of props loop
- --local debugConfig = configuration("Debug")
- local debugConfig = {}
- local releaseConfig = {}
- debugConfig.defines = { "USING_PREMAKE_CONFIG_H", "_DEBUG" }
- releaseConfig.defines = { "USING_PREMAKE_CONFIG_H", "NDEBUG" }
- -- setup per-project defines
- if p.defines ~= nil then
- for k,def in pairs(p.defines) do
- table.insert(debugConfig.defines, def)
- table.insert(releaseConfig.defines, def)
- end
- end
- debugConfig.buildoptions = { }
- if SDL_getos() == "windows" then
- table.insert(debugConfig.buildoptions, "/MDd")
- end
- debugConfig.linkoptions = { }
- releaseConfig.buildoptions = {}
- releaseConfig.linkoptions = {}
- local baseBuildDir = "/Build"
- if os.get() == "windows" then
- baseBuildDir = "/Win32"
- end
- debugConfig.flags = { "Symbols" }
- debugConfig.targetdir = proj.location .. baseBuildDir .. "/Debug"
- releaseConfig.flags = { "OptimizeSpeed" }
- releaseConfig.targetdir = proj.location .. baseBuildDir .. "/Release"
- -- setup postbuild options
- local dbgPostbuildcommands = { }
- local relPostbuildcommands = { }
- -- handle copying depended shared libraries to correct folders
- if os.get() == "windows" then
- for k,deploc in pairs(dependencyLocs) do
- table.insert(dbgCopyTable, { src = deploc.location .. baseBuildDir .. "/Debug/" .. deploc.name .. ".dll",
- dst = debugConfig.targetdir .. "/" .. deploc.name .. ".dll" })
- table.insert(relCopyTable, { src = deploc.location .. baseBuildDir .. "/Release/" .. deploc.name .. ".dll",
- dst = releaseConfig.targetdir .. "/" .. deploc.name .. ".dll" })
- end
- end
- if p.copy ~= nil then
- for k,file in pairs(p.copy) do
- -- the following builds relative paths native to the current system for copying, other
- -- than the copy command itself, this is essentially cross-platform for paths
-
- -- all custom copies should be relative to the current working directory
- table.insert(dbgCopyTable, { src = path.getrelative(baseLoc, p.sourcedir .. "/" .. file), dst = debugConfig.targetdir .. "/" .. file })
- table.insert(relCopyTable, { src = path.getrelative(baseLoc, p.sourcedir .. "/" .. file), dst = releaseConfig.targetdir .. "/" .. file })
- end
- end
- for k,file in pairs(dbgCopyTable) do
- -- all copies should be relative to project location, based on platform
- local relLocation = "./"
- --if os.get() == "windows" then
- relLocation = proj.location
- --end
- local fromPath = "./" .. path.getrelative(relLocation, file.src)
- local toPath = "./" .. path.getrelative(relLocation, file.dst)
- local toPathParent = path.getdirectory(toPath)
- local copyCommand = "cp"
- local destCheck = "if [ ! -d \\\"" .. toPathParent .. "\\\" ]; then mkdir -p \\\"" .. toPathParent .. "\\\"; fi"
- if SDL_getos() ~= "windows" and fromPath:find("*") ~= nil then
- -- to path must be a directory for * copies
- toPath = path.getdirectory(toPath)
- end
- if SDL_getos() == "windows" then
- fromPath = path.translate(fromPath, "/"):gsub("/", "\\\\")
- toPath = path.translate(toPath, "/"):gsub("/", "\\\\")
- toPathParent = path.translate(toPathParent, "/"):gsub("/", "\\\\")
- copyCommand = "copy"
- destCheck = "if not exist \\\"" .. toPathParent .. "\\\" ( mkdir \\\"" .. toPathParent .. "\\\" )"
- else
- fromPath = path.translate(fromPath, nil):gsub("\\", "/")
- toPath = path.translate(toPath, nil):gsub("\\", "/")
- end
- -- command will check for destination directory to exist and, if it doesn't,
- -- it will make the directory and then copy over any assets
- local quotedFromPath = fromPath
- if SDL_getos() == "windows" or fromPath:find("*") == nil then
- quotedFromPath = '\\"' .. quotedFromPath .. '\\"'
- end
- table.insert(dbgPostbuildcommands, destCheck)
- table.insert(dbgPostbuildcommands,
- copyCommand .. " " ..
- quotedFromPath .. " \\\"" ..
- toPath .. "\\\"")
- end
- for k,file in pairs(relCopyTable) do
- -- all copies should be relative to project location, based on platform
- local relLocation = "./"
- relLocation = proj.location
- local fromPath = "./" .. path.getrelative(relLocation, file.src)
- local toPath = "./" .. path.getrelative(relLocation, file.dst)
- local toPathParent = path.getdirectory(toPath)
- local copyCommand = "cp"
- local destCheck = "if [ ! -d \\\"" .. toPathParent .. "\\\" ]; then mkdir -p \\\"" .. toPathParent .. "\\\"; fi"
- if SDL_getos() ~= "windows" and fromPath:find("*") ~= nil then
- -- to path must be a directory for * copies
- toPath = path.getdirectory(toPath)
- end
- if SDL_getos() == "windows" then
- fromPath = path.translate(fromPath, "/"):gsub("/", "\\\\")
- toPath = path.translate(toPath, "/"):gsub("/", "\\\\")
- toPathParent = path.translate(toPathParent, "/"):gsub("/", "\\\\")
- copyCommand = "copy"
- destCheck = "if not exist \\\"" .. toPathParent .. "\\\" ( mkdir \\\"" .. toPathParent .. "\\\" )"
- else
- fromPath = path.translate(fromPath, nil):gsub("\\", "/")
- toPath = path.translate(toPath, nil):gsub("\\", "/")
- end
- -- command will check for destination directory to exist and, if it doesn't,
- -- it will make the directory and then copy over any assets
- local quotedFromPath = fromPath
- if SDL_getos() == "windows" or fromPath:find("*") == nil then
- quotedFromPath = '\\"' .. quotedFromPath .. '\\"'
- end
- table.insert(relPostbuildcommands, destCheck)
- table.insert(relPostbuildcommands,
- copyCommand .. " " ..
- quotedFromPath .. " \\\"" ..
- toPath .. "\\\"")
- end
- debugConfig.postbuildcommands = dbgPostbuildcommands
- debugConfig.links = links
- releaseConfig.postbuildcommands = relPostbuildcommands
- releaseConfig.links = links -- release links?
- for i,d in pairs(p.dependencyTree) do
- if d.includes then
- for k,v in pairs(d.includes) do
- local propPath = v:gsub("\\", "/")
- proj.includedirs[propPath] = propPath
- end
- end
- if d.libs then
- for k,v in pairs(d.libs) do
- local propPath = v:gsub("\\", "/")
- proj.libdirs[propPath] = propPath
- end
- end
- if d.links then
- for k,v in pairs(d.links) do
- local propPath = v:gsub("\\", "/")
- debugConfig.links[#debugConfig.links + 1] = propPath
- end
- end
- end
- if #proj.files > 0 then
- file:print(1, 'project "' .. p.name .. '"')
- file:print(2, 'targetname "' .. p.name .. '"')
- -- note: commented out because I think this hack is unnecessary
- --if iOSMode and p.kind == "ConsoleApp" then
- -- hack for iOS where we cannot build "tools"/ConsoleApps in
- -- Xcode for iOS, so we convert them over to WindowedApps
- -- p.kind = "WindowedApp"
- --end
- file:print(2, 'kind "' .. p.kind .. '"')
- file:print(2, 'language "' .. p.language .. '"')
- file:print(2, 'location "' .. proj.location .. '"')
- file:print(2, 'flags { "NoExceptions" }') -- NoRTTI
- file:print(2, 'buildoptions { }')--"/GS-" }')
- file:print(2, implode(proj.includedirs, 'includedirs {', '"', '"', ', ', '}'))
- file:print(2, implode(proj.libdirs, 'libdirs {', '"', '"', ', ', '}'))
- file:print(2, implode(proj.files, 'files {', '"', '"', ', ', '}'))
- -- debug configuration
- file:print(2, 'configuration "Debug"')
- file:print(3, 'targetdir "' .. debugConfig.targetdir .. '"')
- -- debug dir is relative to the solution's location
- file:print(3, 'debugdir "' .. debugConfig.targetdir .. '"')
- file:print(3, implode(debugConfig.defines, 'defines {', '"', '"', ', ', '}'))
- file:print(3, implode(debugConfig.links, "links {", '"', '"', ', ', "}"))
- if SDL_getos() == "mingw" then
- -- static runtime
- file:print(3, 'linkoptions { "-lmingw32 -static-libgcc" }')
- end
- if SDL_getos() == "cygwin" then
- file:print(3, 'linkoptions { "-static-libgcc" }')
- end
- file:print(3, implode(debugConfig.flags, "flags {", '"', '"', ', ', "}"))
- file:print(3, implode(debugConfig.postbuildcommands, "postbuildcommands {", '"', '"', ', ', "}"))
- -- release configuration
- file:print(2, 'configuration "Release"')
- file:print(3, 'targetdir "' .. releaseConfig.targetdir .. '"')
- -- debug dir is relative to the solution's location
- file:print(3, 'debugdir "' .. releaseConfig.targetdir .. '"')
- file:print(3, implode(releaseConfig.defines, 'defines {', '"', '"', ', ', '}'))
- file:print(3, implode(releaseConfig.links, "links {", '"', '"', ', ', "}"))
- if SDL_getos() == "mingw" then
- -- static runtime
- file:print(3, 'linkoptions { "-lmingw32 -static-libgcc" }')
- end
- file:print(3, implode(releaseConfig.flags, "flags {", '"', '"', ', ', "}"))
- file:print(3, implode(releaseConfig.postbuildcommands, "postbuildcommands {", '"', '"', ', ', "}"))
- end -- end check for valid project (files to build)
- end -- end compatibility check for projects
- end -- end for loop for projects
- endGeneration() -- finish generating the config header file
- file:close()
- -- generation is over, now execute the generated file, setup the premake
- -- solution, and let premake execute the action and generate the project files
- dofile(genFile)
- end -- end check for not being in help mode
|