premake/util/sdl_projects.lua
changeset 7925 f090a47eb7f7
child 8149 681eb46b8ac4
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/premake/util/sdl_projects.lua	Sun Nov 10 00:38:37 2013 -0500
     1.3 @@ -0,0 +1,461 @@
     1.4 +-- Copyright (C) 1997-2011 Sam Lantinga <slouken@libsdl.org>
     1.5 +--
     1.6 +-- This software is provided 'as-is', without any express or implied
     1.7 +-- warranty.  In no event will the authors be held liable for any damages
     1.8 +-- arising from the use of this software.
     1.9 +--
    1.10 +-- Permission is granted to anyone to use this software for any purpose,
    1.11 +-- including commercial applications, and to alter it and redistribute it
    1.12 +-- freely.
    1.13 +--
    1.14 +-- Meta-build system using premake created and maintained by
    1.15 +-- Benjamin Henning <b.henning@digipen.edu>
    1.16 +
    1.17 +--[[
    1.18 +sdl_projects.lua
    1.19 +
    1.20 +	This file contains all the functions which are needed to define any project
    1.21 +	within the meta-build system. Many of these functions serve as
    1.22 +	pseudo-replacements for many similarly named premake functions, and that is
    1.23 +	intentional. Even the implementation of these functions are intended to look
    1.24 +	similar to regular premake code. These functions serve to dramatically
    1.25 +	simplify the project definition process to just a few lines of code, versus
    1.26 +	the many more needed for projects defined purely with premake.
    1.27 +
    1.28 +	This approach is possible because this meta-build system adds another layer of
    1.29 +	indirection to the premake system, creating a sort of 'meta-meta-build'
    1.30 +	system. Nevertheless, there is a lot more flexibility because the meta-build
    1.31 +	system itself can be used to check for dependencies in a much more complex way
    1.32 +	than premake originally intended. All of the functions useful to the project
    1.33 +	definition system are contained in this file and are documented.
    1.34 +]]
    1.35 +
    1.36 +projects = { }
    1.37 +
    1.38 +local currentProject = nil
    1.39 +local currentDep = nil
    1.40 +local nextFuncCompat = true -- by default, unless state otherwise changed
    1.41 +local dependencyFunctions = { }
    1.42 +local dependencyResults = { } -- for when the dependencies are executed
    1.43 +
    1.44 +-- query whether this function is compatible; resets internal state of
    1.45 +-- compatibility to true until SDL_isos is called again
    1.46 +local function oscompat()
    1.47 +	local compat = nextFuncCompat
    1.48 +	nextFuncCompat = true
    1.49 +	return compat
    1.50 +end
    1.51 +
    1.52 +-- determine whether the specific OS name is within a pattern.
    1.53 +local function osmatch(name, pattern)
    1.54 +	local checks = pattern:explode('|')
    1.55 +	for i,v in pairs(checks) do
    1.56 +		if name == v then
    1.57 +			return true
    1.58 +		end
    1.59 +	end
    1.60 +	return false
    1.61 +end
    1.62 +
    1.63 +-- Registers a dependency checker function based on a name. This function is
    1.64 +-- used in order to determine compatibility with the current system for a given
    1.65 +-- SDL_dependency. See SDL_depfunc for more information.
    1.66 +--
    1.67 +-- Specifies a function which will be invoked upon determining whether this
    1.68 +-- dependency is valid for the current system setup (ie, whether the system
    1.69 +-- has the right architecture, operating system, or even if it's installed).
    1.70 +-- The dependency function takes no arguments, but it must return the following
    1.71 +-- values:
    1.72 +--
    1.73 +--   <foundDep> [includePaths] [libPaths] [inputLibLibraries]
    1.74 +--
    1.75 +-- The last three are optional, unless foundDep is true. The name should be
    1.76 +-- descriptive of the outside dependency, since it may be shown to the user.
    1.77 +-- This function is intended to be used only after invoking SDL_dependency.
    1.78 +function SDL_registerDependencyChecker(name, func)
    1.79 +	dependencyFunctions[name:lower()] = func
    1.80 +end
    1.81 +
    1.82 +-- Initializes the definition of a SDL project given the name of the project.
    1.83 +function SDL_project(name)
    1.84 +	if not oscompat() then return end
    1.85 +	currentProject = { }
    1.86 +	currentProject.name = name
    1.87 +	currentProject.compat = true
    1.88 +	projects[name] = currentProject
    1.89 +	currentProject.dependencyTree = { }
    1.90 +	-- stores which dependencies have already been checked on behalf of this
    1.91 +	-- project
    1.92 +	currentProject.dependencyValues = { }
    1.93 +	currentDep = nil
    1.94 +end
    1.95 +
    1.96 +-- Specifies the build kind of the SDL project (e.g. StaticLib, SharedLib,
    1.97 +-- ConsoleApp, etc.), based on premake presets.
    1.98 +function SDL_kind(k)
    1.99 +	if not oscompat() then return end
   1.100 +	currentProject.kind = k
   1.101 +end
   1.102 +
   1.103 +-- Specifies which platforms this project supports. Note: this list is not the
   1.104 +-- exact list of supported platforms in the generated project. The list of
   1.105 +-- platforms this project supports will be the unique list of all combined
   1.106 +-- projects for this SDL solution. Thus, only one project needs to actually
   1.107 +-- maintain a list. This function is additive, that is, everytime it is called
   1.108 +-- it adds it to a unique list of platforms
   1.109 +function SDL_platforms(tbl)
   1.110 +	if not oscompat() then return end
   1.111 +	if not currentProject.platforms then
   1.112 +		currentProject.platforms = { }
   1.113 +	end
   1.114 +	for k,v in pairs(tbl) do
   1.115 +		currentProject.platforms[#currentProject.platforms + 1] = v
   1.116 +	end
   1.117 +end
   1.118 +
   1.119 +-- Specifies the programming language of the project, such as C or C++.
   1.120 +function SDL_language(k)
   1.121 +	if not oscompat() then return end
   1.122 +	currentProject.language = k
   1.123 +end
   1.124 +
   1.125 +-- Specifies the root directory in which the meta-build system should search for
   1.126 +-- source files, given the paths and files added.
   1.127 +function SDL_sourcedir(src)
   1.128 +	if not oscompat() then return end
   1.129 +	currentProject.sourcedir = src
   1.130 +end
   1.131 +
   1.132 +-- Specifies the destination location of where the IDE files related to the
   1.133 +-- project should be saved after generation.
   1.134 +function SDL_projectLocation(loc)
   1.135 +	if not oscompat() then return end
   1.136 +	currentProject.projectLocation = loc
   1.137 +end
   1.138 +
   1.139 +-- Specifies a table of files that should be copied from the source directory
   1.140 +-- to the end result build directory of the binary file.
   1.141 +function SDL_copy(tbl)
   1.142 +	if not oscompat() then return end
   1.143 +	currentProject.copy = tbl
   1.144 +end
   1.145 +
   1.146 +-- Specifies a list of other SDL projects in this workspace the currently active
   1.147 +-- project is dependent on. If the dependent project is a library, the binary
   1.148 +-- result will be copied from its directory to the build directory of the
   1.149 +-- currently active project automatically.
   1.150 +function SDL_projectDependencies(tbl)
   1.151 +	if not oscompat() then return end
   1.152 +	currentProject.projectDependencies = tbl
   1.153 +end
   1.154 +
   1.155 +-- Specifies a list of compiler-level preprocessor definitions that should be
   1.156 +-- set in the resulting project upon compile time. This adds to the current
   1.157 +-- table of defines.
   1.158 +function SDL_defines(tbl)
   1.159 +	if not oscompat() then return end
   1.160 +	if not currentProject.defines then
   1.161 +		currentProject.defines = { }
   1.162 +	end
   1.163 +	for k,v in pairs(tbl) do
   1.164 +		currentProject.defines[#currentProject.defines + 1] = v
   1.165 +	end
   1.166 +end
   1.167 +
   1.168 +-- Initializes an outside dependency this project has, such as X11 or DirectX.
   1.169 +-- This function, once invoked, may change the behavior of other SDL
   1.170 +-- project-related functions, so be sure to be familiar with all the functions
   1.171 +-- and any specified behavior when used around SDL_dependency.
   1.172 +function SDL_dependency(name)
   1.173 +	if not oscompat() then return end
   1.174 +	currentDep = { nil, compat = true, }
   1.175 +	currentDep.name = name
   1.176 +	table.insert(currentProject.dependencyTree, currentDep)
   1.177 +end
   1.178 +
   1.179 +-- Special function for getting the current OS. This factors in whether the
   1.180 +-- metabuild system is in MinGW, Cygwin, or iOS mode.
   1.181 +function SDL_getos()
   1.182 +	if _OPTIONS["ios"] ~= nil then
   1.183 +		return "ios"
   1.184 +	elseif _OPTIONS["mingw"] ~= nil then
   1.185 +		return "mingw"
   1.186 +	elseif _OPTIONS["cygwin"] ~= nil then
   1.187 +		return "cygwin"
   1.188 +	end
   1.189 +	return os.get()
   1.190 +end
   1.191 +
   1.192 +-- Specifies which operating system this dependency targets, such as windows or
   1.193 +-- macosx, as per premake presets.
   1.194 +function SDL_os(name)
   1.195 +	if not oscompat() then return end
   1.196 +	if not currentProject then return end
   1.197 +	if not currentDep then
   1.198 +		currentProject.opsys = name
   1.199 +		currentProject.compat = osmatch(SDL_getos(), name)
   1.200 +	else
   1.201 +		currentDep.opsys = name
   1.202 +		currentDep.compat = osmatch(SDL_getos(), name)
   1.203 +	end
   1.204 +end
   1.205 +
   1.206 +-- Specifies which operating system this dependency does not targets. This is
   1.207 +-- for nearly platform-independent projects or dependencies that will not work
   1.208 +-- on specific systems, such as ios.
   1.209 +function SDL_notos(name)
   1.210 +	if not oscompat() then return end
   1.211 +	if not currentProject then return end
   1.212 +	if not currentDep then
   1.213 +		currentProject.opsys = "~" .. name
   1.214 +		currentProject.compat = not osmatch(SDL_getos(), name)
   1.215 +	else
   1.216 +		currentDep.opsys = "~" .. name
   1.217 +		currentDep.compat = not osmatch(SDL_getos(), name)
   1.218 +	end
   1.219 +end
   1.220 +
   1.221 +-- Changes the internal state of function compatibility based on whether the
   1.222 +-- current os is the one expected; the next function will be affected by this
   1.223 +-- change, but no others. The name can be a pattern using '|' to separate
   1.224 +-- multiple operating systems, such as:
   1.225 +--   SDL_isos("windows|macosx")
   1.226 +function SDL_isos(name)
   1.227 +	nextFuncCompat = osmatch(SDL_getos(), name)
   1.228 +end
   1.229 +
   1.230 +-- Same as SDL_isos, except it negates the internal state for exclusion
   1.231 +-- checking.
   1.232 +function SDL_isnotos(name)
   1.233 +	nextFuncCompat = not osmatch(SDL_getos(), name)
   1.234 +end
   1.235 +
   1.236 +-- Changes the internal state of function compatibility based on whether the
   1.237 +-- current system is running a 64bit Operating System and architecture; the
   1.238 +-- next function will be affected by this change, but none thereafter.
   1.239 +function SDL_is64bit()
   1.240 +	nextFuncCompat = os.is64bit()
   1.241 +end
   1.242 +
   1.243 +-- Same as SDL_is64bit, except it negates the internal state for
   1.244 +-- exclusion checking.
   1.245 +function SDL_isnot64bit()
   1.246 +	nextFuncCompat = not os.is64bit()
   1.247 +end
   1.248 +
   1.249 +-- Look at SDL_depfunc and SDL_notdepfunc for detailed information about this
   1.250 +-- function.
   1.251 +local function SDL_depfunc0(funcname, exclude)
   1.252 +	if not oscompat() then return end
   1.253 +	if not currentDep.compat then return end
   1.254 +	local force = _OPTIONS[funcname:lower()] ~= nil
   1.255 +	local func = dependencyFunctions[funcname:lower()]
   1.256 +	if not func then
   1.257 +		print("Warning: could not find dependency function named: " .. funcname)
   1.258 +		currentDep.compat = false
   1.259 +		return
   1.260 +	end
   1.261 +	local cachedFuncResults = dependencyResults[funcname:lower()]
   1.262 +	local depFound, depInc, depLib, depInput
   1.263 +	if cachedFuncResults then
   1.264 +		depFound = cachedFuncResults.depFound
   1.265 +		-- just skip the rest of the function, the user was already warned
   1.266 +		-- exclude mode varies the compatibility slightly
   1.267 +		if force then
   1.268 +			depFound = true
   1.269 +		end
   1.270 +		if not depFound and not exclude then
   1.271 +			currentDep.compat = false
   1.272 +			return
   1.273 +		elseif depFound and exclude then
   1.274 +			currentDep.compat = false
   1.275 +			return
   1.276 +		end
   1.277 +		depInc = cachedFuncResults.depInc
   1.278 +		depLib = cachedFuncResults.depLib
   1.279 +		depInput = cachedFuncResults.depInput
   1.280 +	else
   1.281 +		local result = func()
   1.282 +		if result.found then
   1.283 +			depFound = result.found
   1.284 +		else
   1.285 +			depFound = false
   1.286 +		end
   1.287 +		if force then
   1.288 +			depFound = true
   1.289 +		end
   1.290 +		if result.incDirs then
   1.291 +			depInc = result.incDirs
   1.292 +		else
   1.293 +			depInc = { }
   1.294 +		end
   1.295 +		if result.libDirs then
   1.296 +			depLib = result.libDirs
   1.297 +		else
   1.298 +			depLib = { }
   1.299 +		end
   1.300 +		if result.libs then
   1.301 +			depInput = result.libs
   1.302 +		else
   1.303 +			depInput = { }
   1.304 +		end
   1.305 +		cachedFuncResults = { }
   1.306 +		cachedFuncResults.depFound = depFound
   1.307 +		cachedFuncResults.depInc = depInc
   1.308 +		cachedFuncResults.depLib = depLib
   1.309 +		cachedFuncResults.depInput = depInput
   1.310 +		dependencyResults[funcname:lower()] = cachedFuncResults
   1.311 +		if not depFound and not exclude then
   1.312 +			currentDep.compat = false
   1.313 +			return
   1.314 +		elseif depFound and exclude then
   1.315 +			currentDep.compat = false
   1.316 +			return
   1.317 +		end
   1.318 +	end
   1.319 +	-- we only want to embed this dependency if we're not in exclude mode
   1.320 +	if depFound and not exclude then
   1.321 +		local dependency = { }
   1.322 +		if not currentDep.includes then
   1.323 +			currentDep.includes = { }
   1.324 +		end
   1.325 +		for k,v in pairs(depInc) do
   1.326 +			currentDep.includes[v] = v
   1.327 +		end
   1.328 +		if not currentDep.libs then
   1.329 +			currentDep.libs = { }
   1.330 +		end
   1.331 +		for k,v in pairs(depLib) do
   1.332 +			currentDep.libs[v] = v
   1.333 +		end
   1.334 +		if not currentDep.links then
   1.335 +			currentDep.links = { }
   1.336 +		end
   1.337 +		for k,v in pairs(depInput) do
   1.338 +			currentDep.links[v] = v
   1.339 +		end
   1.340 +	else -- end of dependency found check
   1.341 +		-- if we are not excluding this dependency, then print a warning
   1.342 +		-- if not found
   1.343 +		if not exclude then
   1.344 +			print("Warning: could not find dependency: " .. funcname)
   1.345 +		end
   1.346 +		currentDep.compat = exclude
   1.347 +	end
   1.348 +end
   1.349 +
   1.350 +-- Given a dependency name, this function will register the dependency and try
   1.351 +-- to pair it with a dependency function that was registered through
   1.352 +-- SDL_registerDependencyChecker. If the function is not found, compatibility
   1.353 +-- will automatically be dropped for this project and a warning will be printed
   1.354 +-- to the standard output. Otherwise, the dependency function will be invoked
   1.355 +-- and compatibility for the project will be updated. If the project currently
   1.356 +-- is not compatible based on the Operating System or previous dependency, the
   1.357 +-- dependency function will not be checked at all and this function will
   1.358 +-- silently return.
   1.359 +function SDL_depfunc(funcname)
   1.360 +	SDL_depfunc0(funcname, false)
   1.361 +end
   1.362 +
   1.363 +-- Same as SDL_depfunc, except this forces dependency on the function failing,
   1.364 +-- rather than succeeding. This is useful for situations where two different
   1.365 +-- files are required based on whether a dependency is found (such as the
   1.366 +-- joystick and haptic systems).
   1.367 +function SDL_notdepfunc(funcname)
   1.368 +	SDL_depfunc0(funcname, true)
   1.369 +end
   1.370 +
   1.371 +-- Determines whether the specified dependency is supported without actually
   1.372 +-- executing the dependency or changing the internal states of the current
   1.373 +-- project or dependency definition. This function will only work if the
   1.374 +-- dependency has already been checked and its results cached within the
   1.375 +-- definition system. This function returns true if the dependency is known to
   1.376 +-- be supported, or false if otherwise (or if it cannot be known at this time).
   1.377 +function SDL_assertdepfunc(funcname)
   1.378 +	-- if forced, then of course it's on
   1.379 +	if _OPTIONS[funcname:lower()] then
   1.380 +		return true
   1.381 +	end
   1.382 +	local results = dependencyResults[funcname:lower()]
   1.383 +	if not results or not results.depFound then
   1.384 +		-- either not excuted yet, doesn't exist, or wasn't found
   1.385 +		print("Warning: required dependency not found: " .. funcname ..
   1.386 +			". Make sure your dependencies are in a logical order.")
   1.387 +		return false
   1.388 +	end
   1.389 +	return true
   1.390 +end
   1.391 +
   1.392 +-- Returns a list of currently registered dependencies. The values within the
   1.393 +-- table will be sorted, but their names will be lowercased due to internal
   1.394 +-- handling of case-insensitive dependency names.
   1.395 +function SDL_getDependencies()
   1.396 +	local deps = { }
   1.397 +	for k,_ in pairs(dependencyFunctions) do
   1.398 +		deps[#deps + 1] = k
   1.399 +	end
   1.400 +	table.sort(deps)
   1.401 +	return deps
   1.402 +end
   1.403 +
   1.404 +-- Specifies a list of libraries that should always be linked to in this
   1.405 +-- project, regardless of a dependency function. If after a dependency
   1.406 +-- declaration, these files will only be included in the project if the
   1.407 +-- dependency is compatible with the native system, given SDL_os usage and any
   1.408 +-- sort of custom dependency function.
   1.409 +function SDL_links(tbl)
   1.410 +	if not oscompat() then return end
   1.411 +	if currentDep and not currentDep.compat then return end
   1.412 +	if currentProject.customLinks == nil then
   1.413 +		currentProject.customLinks = { }
   1.414 +	end
   1.415 +	for i,v in ipairs(tbl) do
   1.416 +		currentProject.customLinks[#currentProject.customLinks + 1] = v
   1.417 +	end
   1.418 +end
   1.419 +
   1.420 +-- Specifies a list of configuration values that are assigned as preprocessor
   1.421 +-- definitions in the SDL configuration header, used to globally configure
   1.422 +-- features during the building of the SDL library. If after a dependency
   1.423 +-- declaration, these files will only be included in the project if the
   1.424 +-- dependency is compatible with the native system, given SDL_os usage and any
   1.425 +-- sort of custom dependency function.
   1.426 +function SDL_config(tbl)
   1.427 +	if not oscompat() then return end
   1.428 +	if not currentDep then
   1.429 +		currentProject.config = tbl
   1.430 +		return
   1.431 +	end
   1.432 +	if not currentDep.compat then return end
   1.433 +	currentDep.config = tbl
   1.434 +end
   1.435 +
   1.436 +-- Specifies a list of paths where all .c, .h, and .m files should be included
   1.437 +-- for compiling, where the source directory is the root. If after a dependency
   1.438 +-- declaration, these files will only be included in the project if the
   1.439 +-- dependency is compatible with the native system, given SDL_os usage and any
   1.440 +-- sort of custom dependency function.
   1.441 +function SDL_paths(tbl)
   1.442 +	if not oscompat() then return end
   1.443 +	if not currentDep then
   1.444 +		currentProject.paths = tbl
   1.445 +		return
   1.446 +	end
   1.447 +	if not currentDep.compat then return end
   1.448 +	currentDep.paths = tbl
   1.449 +end
   1.450 +
   1.451 +-- Specifies a list of files found within the source directory that this project
   1.452 +-- should include during compile time. If after a dependency declaration, these
   1.453 +-- files will only be included in the project if the dependency is compatible
   1.454 +-- with the native system, given SDL_os usage and any sort of custom dependency
   1.455 +-- function.
   1.456 +function SDL_files(tbl)
   1.457 +	if not oscompat() then return end
   1.458 +	if not currentDep then
   1.459 +		currentProject.files = tbl
   1.460 +		return
   1.461 +	end
   1.462 +	if not currentDep.compat then return end
   1.463 +	currentDep.files = tbl
   1.464 +end
   1.465 \ No newline at end of file