premake/util/sdl_projects.lua
changeset 7925 f090a47eb7f7
child 8149 681eb46b8ac4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/premake/util/sdl_projects.lua	Sun Nov 10 00:38:37 2013 -0500
@@ -0,0 +1,461 @@
+-- Copyright (C) 1997-2011 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>
+
+--[[
+sdl_projects.lua
+
+	This file contains all the functions which are needed to define any project
+	within the meta-build system. Many of these functions serve as
+	pseudo-replacements for many similarly named premake functions, and that is
+	intentional. Even the implementation of these functions are intended to look
+	similar to regular premake code. These functions serve to dramatically
+	simplify the project definition process to just a few lines of code, versus
+	the many more needed for projects defined purely with premake.
+
+	This approach is possible because this meta-build system adds another layer of
+	indirection to the premake system, creating a sort of 'meta-meta-build'
+	system. Nevertheless, there is a lot more flexibility because the meta-build
+	system itself can be used to check for dependencies in a much more complex way
+	than premake originally intended. All of the functions useful to the project
+	definition system are contained in this file and are documented.
+]]
+
+projects = { }
+
+local currentProject = nil
+local currentDep = nil
+local nextFuncCompat = true -- by default, unless state otherwise changed
+local dependencyFunctions = { }
+local dependencyResults = { } -- for when the dependencies are executed
+
+-- query whether this function is compatible; resets internal state of
+-- compatibility to true until SDL_isos is called again
+local function oscompat()
+	local compat = nextFuncCompat
+	nextFuncCompat = true
+	return compat
+end
+
+-- determine whether the specific OS name is within a pattern.
+local function osmatch(name, pattern)
+	local checks = pattern:explode('|')
+	for i,v in pairs(checks) do
+		if name == v then
+			return true
+		end
+	end
+	return false
+end
+
+-- Registers a dependency checker function based on a name. This function is
+-- used in order to determine compatibility with the current system for a given
+-- SDL_dependency. See SDL_depfunc for more information.
+--
+-- Specifies a function which will be invoked upon determining whether this
+-- dependency is valid for the current system setup (ie, whether the system
+-- has the right architecture, operating system, or even if it's installed).
+-- The dependency function takes no arguments, but it must return the following
+-- values:
+--
+--   <foundDep> [includePaths] [libPaths] [inputLibLibraries]
+--
+-- The last three are optional, unless foundDep is true. The name should be
+-- descriptive of the outside dependency, since it may be shown to the user.
+-- This function is intended to be used only after invoking SDL_dependency.
+function SDL_registerDependencyChecker(name, func)
+	dependencyFunctions[name:lower()] = func
+end
+
+-- Initializes the definition of a SDL project given the name of the project.
+function SDL_project(name)
+	if not oscompat() then return end
+	currentProject = { }
+	currentProject.name = name
+	currentProject.compat = true
+	projects[name] = currentProject
+	currentProject.dependencyTree = { }
+	-- stores which dependencies have already been checked on behalf of this
+	-- project
+	currentProject.dependencyValues = { }
+	currentDep = nil
+end
+
+-- Specifies the build kind of the SDL project (e.g. StaticLib, SharedLib,
+-- ConsoleApp, etc.), based on premake presets.
+function SDL_kind(k)
+	if not oscompat() then return end
+	currentProject.kind = k
+end
+
+-- Specifies which platforms this project supports. Note: this list is not the
+-- exact list of supported platforms in the generated project. The list of
+-- platforms this project supports will be the unique list of all combined
+-- projects for this SDL solution. Thus, only one project needs to actually
+-- maintain a list. This function is additive, that is, everytime it is called
+-- it adds it to a unique list of platforms
+function SDL_platforms(tbl)
+	if not oscompat() then return end
+	if not currentProject.platforms then
+		currentProject.platforms = { }
+	end
+	for k,v in pairs(tbl) do
+		currentProject.platforms[#currentProject.platforms + 1] = v
+	end
+end
+
+-- Specifies the programming language of the project, such as C or C++.
+function SDL_language(k)
+	if not oscompat() then return end
+	currentProject.language = k
+end
+
+-- Specifies the root directory in which the meta-build system should search for
+-- source files, given the paths and files added.
+function SDL_sourcedir(src)
+	if not oscompat() then return end
+	currentProject.sourcedir = src
+end
+
+-- Specifies the destination location of where the IDE files related to the
+-- project should be saved after generation.
+function SDL_projectLocation(loc)
+	if not oscompat() then return end
+	currentProject.projectLocation = loc
+end
+
+-- Specifies a table of files that should be copied from the source directory
+-- to the end result build directory of the binary file.
+function SDL_copy(tbl)
+	if not oscompat() then return end
+	currentProject.copy = tbl
+end
+
+-- Specifies a list of other SDL projects in this workspace the currently active
+-- project is dependent on. If the dependent project is a library, the binary
+-- result will be copied from its directory to the build directory of the
+-- currently active project automatically.
+function SDL_projectDependencies(tbl)
+	if not oscompat() then return end
+	currentProject.projectDependencies = tbl
+end
+
+-- Specifies a list of compiler-level preprocessor definitions that should be
+-- set in the resulting project upon compile time. This adds to the current
+-- table of defines.
+function SDL_defines(tbl)
+	if not oscompat() then return end
+	if not currentProject.defines then
+		currentProject.defines = { }
+	end
+	for k,v in pairs(tbl) do
+		currentProject.defines[#currentProject.defines + 1] = v
+	end
+end
+
+-- Initializes an outside dependency this project has, such as X11 or DirectX.
+-- This function, once invoked, may change the behavior of other SDL
+-- project-related functions, so be sure to be familiar with all the functions
+-- and any specified behavior when used around SDL_dependency.
+function SDL_dependency(name)
+	if not oscompat() then return end
+	currentDep = { nil, compat = true, }
+	currentDep.name = name
+	table.insert(currentProject.dependencyTree, currentDep)
+end
+
+-- Special function for getting the current OS. This factors in whether the
+-- metabuild system is in MinGW, Cygwin, or iOS mode.
+function SDL_getos()
+	if _OPTIONS["ios"] ~= nil then
+		return "ios"
+	elseif _OPTIONS["mingw"] ~= nil then
+		return "mingw"
+	elseif _OPTIONS["cygwin"] ~= nil then
+		return "cygwin"
+	end
+	return os.get()
+end
+
+-- Specifies which operating system this dependency targets, such as windows or
+-- macosx, as per premake presets.
+function SDL_os(name)
+	if not oscompat() then return end
+	if not currentProject then return end
+	if not currentDep then
+		currentProject.opsys = name
+		currentProject.compat = osmatch(SDL_getos(), name)
+	else
+		currentDep.opsys = name
+		currentDep.compat = osmatch(SDL_getos(), name)
+	end
+end
+
+-- Specifies which operating system this dependency does not targets. This is
+-- for nearly platform-independent projects or dependencies that will not work
+-- on specific systems, such as ios.
+function SDL_notos(name)
+	if not oscompat() then return end
+	if not currentProject then return end
+	if not currentDep then
+		currentProject.opsys = "~" .. name
+		currentProject.compat = not osmatch(SDL_getos(), name)
+	else
+		currentDep.opsys = "~" .. name
+		currentDep.compat = not osmatch(SDL_getos(), name)
+	end
+end
+
+-- Changes the internal state of function compatibility based on whether the
+-- current os is the one expected; the next function will be affected by this
+-- change, but no others. The name can be a pattern using '|' to separate
+-- multiple operating systems, such as:
+--   SDL_isos("windows|macosx")
+function SDL_isos(name)
+	nextFuncCompat = osmatch(SDL_getos(), name)
+end
+
+-- Same as SDL_isos, except it negates the internal state for exclusion
+-- checking.
+function SDL_isnotos(name)
+	nextFuncCompat = not osmatch(SDL_getos(), name)
+end
+
+-- Changes the internal state of function compatibility based on whether the
+-- current system is running a 64bit Operating System and architecture; the
+-- next function will be affected by this change, but none thereafter.
+function SDL_is64bit()
+	nextFuncCompat = os.is64bit()
+end
+
+-- Same as SDL_is64bit, except it negates the internal state for
+-- exclusion checking.
+function SDL_isnot64bit()
+	nextFuncCompat = not os.is64bit()
+end
+
+-- Look at SDL_depfunc and SDL_notdepfunc for detailed information about this
+-- function.
+local function SDL_depfunc0(funcname, exclude)
+	if not oscompat() then return end
+	if not currentDep.compat then return end
+	local force = _OPTIONS[funcname:lower()] ~= nil
+	local func = dependencyFunctions[funcname:lower()]
+	if not func then
+		print("Warning: could not find dependency function named: " .. funcname)
+		currentDep.compat = false
+		return
+	end
+	local cachedFuncResults = dependencyResults[funcname:lower()]
+	local depFound, depInc, depLib, depInput
+	if cachedFuncResults then
+		depFound = cachedFuncResults.depFound
+		-- just skip the rest of the function, the user was already warned
+		-- exclude mode varies the compatibility slightly
+		if force then
+			depFound = true
+		end
+		if not depFound and not exclude then
+			currentDep.compat = false
+			return
+		elseif depFound and exclude then
+			currentDep.compat = false
+			return
+		end
+		depInc = cachedFuncResults.depInc
+		depLib = cachedFuncResults.depLib
+		depInput = cachedFuncResults.depInput
+	else
+		local result = func()
+		if result.found then
+			depFound = result.found
+		else
+			depFound = false
+		end
+		if force then
+			depFound = true
+		end
+		if result.incDirs then
+			depInc = result.incDirs
+		else
+			depInc = { }
+		end
+		if result.libDirs then
+			depLib = result.libDirs
+		else
+			depLib = { }
+		end
+		if result.libs then
+			depInput = result.libs
+		else
+			depInput = { }
+		end
+		cachedFuncResults = { }
+		cachedFuncResults.depFound = depFound
+		cachedFuncResults.depInc = depInc
+		cachedFuncResults.depLib = depLib
+		cachedFuncResults.depInput = depInput
+		dependencyResults[funcname:lower()] = cachedFuncResults
+		if not depFound and not exclude then
+			currentDep.compat = false
+			return
+		elseif depFound and exclude then
+			currentDep.compat = false
+			return
+		end
+	end
+	-- we only want to embed this dependency if we're not in exclude mode
+	if depFound and not exclude then
+		local dependency = { }
+		if not currentDep.includes then
+			currentDep.includes = { }
+		end
+		for k,v in pairs(depInc) do
+			currentDep.includes[v] = v
+		end
+		if not currentDep.libs then
+			currentDep.libs = { }
+		end
+		for k,v in pairs(depLib) do
+			currentDep.libs[v] = v
+		end
+		if not currentDep.links then
+			currentDep.links = { }
+		end
+		for k,v in pairs(depInput) do
+			currentDep.links[v] = v
+		end
+	else -- end of dependency found check
+		-- if we are not excluding this dependency, then print a warning
+		-- if not found
+		if not exclude then
+			print("Warning: could not find dependency: " .. funcname)
+		end
+		currentDep.compat = exclude
+	end
+end
+
+-- Given a dependency name, this function will register the dependency and try
+-- to pair it with a dependency function that was registered through
+-- SDL_registerDependencyChecker. If the function is not found, compatibility
+-- will automatically be dropped for this project and a warning will be printed
+-- to the standard output. Otherwise, the dependency function will be invoked
+-- and compatibility for the project will be updated. If the project currently
+-- is not compatible based on the Operating System or previous dependency, the
+-- dependency function will not be checked at all and this function will
+-- silently return.
+function SDL_depfunc(funcname)
+	SDL_depfunc0(funcname, false)
+end
+
+-- Same as SDL_depfunc, except this forces dependency on the function failing,
+-- rather than succeeding. This is useful for situations where two different
+-- files are required based on whether a dependency is found (such as the
+-- joystick and haptic systems).
+function SDL_notdepfunc(funcname)
+	SDL_depfunc0(funcname, true)
+end
+
+-- Determines whether the specified dependency is supported without actually
+-- executing the dependency or changing the internal states of the current
+-- project or dependency definition. This function will only work if the
+-- dependency has already been checked and its results cached within the
+-- definition system. This function returns true if the dependency is known to
+-- be supported, or false if otherwise (or if it cannot be known at this time).
+function SDL_assertdepfunc(funcname)
+	-- if forced, then of course it's on
+	if _OPTIONS[funcname:lower()] then
+		return true
+	end
+	local results = dependencyResults[funcname:lower()]
+	if not results or not results.depFound then
+		-- either not excuted yet, doesn't exist, or wasn't found
+		print("Warning: required dependency not found: " .. funcname ..
+			". Make sure your dependencies are in a logical order.")
+		return false
+	end
+	return true
+end
+
+-- Returns a list of currently registered dependencies. The values within the
+-- table will be sorted, but their names will be lowercased due to internal
+-- handling of case-insensitive dependency names.
+function SDL_getDependencies()
+	local deps = { }
+	for k,_ in pairs(dependencyFunctions) do
+		deps[#deps + 1] = k
+	end
+	table.sort(deps)
+	return deps
+end
+
+-- Specifies a list of libraries that should always be linked to in this
+-- project, regardless of a dependency function. If after a dependency
+-- declaration, these files will only be included in the project if the
+-- dependency is compatible with the native system, given SDL_os usage and any
+-- sort of custom dependency function.
+function SDL_links(tbl)
+	if not oscompat() then return end
+	if currentDep and not currentDep.compat then return end
+	if currentProject.customLinks == nil then
+		currentProject.customLinks = { }
+	end
+	for i,v in ipairs(tbl) do
+		currentProject.customLinks[#currentProject.customLinks + 1] = v
+	end
+end
+
+-- Specifies a list of configuration values that are assigned as preprocessor
+-- definitions in the SDL configuration header, used to globally configure
+-- features during the building of the SDL library. If after a dependency
+-- declaration, these files will only be included in the project if the
+-- dependency is compatible with the native system, given SDL_os usage and any
+-- sort of custom dependency function.
+function SDL_config(tbl)
+	if not oscompat() then return end
+	if not currentDep then
+		currentProject.config = tbl
+		return
+	end
+	if not currentDep.compat then return end
+	currentDep.config = tbl
+end
+
+-- Specifies a list of paths where all .c, .h, and .m files should be included
+-- for compiling, where the source directory is the root. If after a dependency
+-- declaration, these files will only be included in the project if the
+-- dependency is compatible with the native system, given SDL_os usage and any
+-- sort of custom dependency function.
+function SDL_paths(tbl)
+	if not oscompat() then return end
+	if not currentDep then
+		currentProject.paths = tbl
+		return
+	end
+	if not currentDep.compat then return end
+	currentDep.paths = tbl
+end
+
+-- Specifies a list of files found within the source directory that this project
+-- should include during compile time. If after a dependency declaration, these
+-- files will only be included in the project if the dependency is compatible
+-- with the native system, given SDL_os usage and any sort of custom dependency
+-- function.
+function SDL_files(tbl)
+	if not oscompat() then return end
+	if not currentDep then
+		currentProject.files = tbl
+		return
+	end
+	if not currentDep.compat then return end
+	currentDep.files = tbl
+end
\ No newline at end of file