sdl_projects.lua (16074B)
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--[[ 15sdl_projects.lua 16 17 This file contains all the functions which are needed to define any project 18 within the meta-build system. Many of these functions serve as 19 pseudo-replacements for many similarly named premake functions, and that is 20 intentional. Even the implementation of these functions are intended to look 21 similar to regular premake code. These functions serve to dramatically 22 simplify the project definition process to just a few lines of code, versus 23 the many more needed for projects defined purely with premake. 24 25 This approach is possible because this meta-build system adds another layer of 26 indirection to the premake system, creating a sort of 'meta-meta-build' 27 system. Nevertheless, there is a lot more flexibility because the meta-build 28 system itself can be used to check for dependencies in a much more complex way 29 than premake originally intended. All of the functions useful to the project 30 definition system are contained in this file and are documented. 31]] 32 33projects = { } 34 35local currentProject = nil 36local currentDep = nil 37local nextFuncCompat = true -- by default, unless state otherwise changed 38local dependencyFunctions = { } 39local dependencyResults = { } -- for when the dependencies are executed 40 41-- query whether this function is compatible; resets internal state of 42-- compatibility to true until SDL_isos is called again 43local function oscompat() 44 local compat = nextFuncCompat 45 nextFuncCompat = true 46 return compat 47end 48 49-- determine whether the specific OS name is within a pattern. 50local function osmatch(name, pattern) 51 local checks = pattern:explode('|') 52 for i,v in pairs(checks) do 53 if name == v then 54 return true 55 end 56 end 57 return false 58end 59 60-- Registers a dependency checker function based on a name. This function is 61-- used in order to determine compatibility with the current system for a given 62-- SDL_dependency. See SDL_depfunc for more information. 63-- 64-- Specifies a function which will be invoked upon determining whether this 65-- dependency is valid for the current system setup (ie, whether the system 66-- has the right architecture, operating system, or even if it's installed). 67-- The dependency function takes no arguments, but it must return the following 68-- values: 69-- 70-- <foundDep> [includePaths] [libPaths] [inputLibLibraries] 71-- 72-- The last three are optional, unless foundDep is true. The name should be 73-- descriptive of the outside dependency, since it may be shown to the user. 74-- This function is intended to be used only after invoking SDL_dependency. 75function SDL_registerDependencyChecker(name, func) 76 dependencyFunctions[name:lower()] = func 77end 78 79-- Initializes the definition of a SDL project given the name of the project. 80function SDL_project(name) 81 if not oscompat() then return end 82 currentProject = { } 83 currentProject.name = name 84 currentProject.compat = true 85 projects[name] = currentProject 86 currentProject.dependencyTree = { } 87 -- stores which dependencies have already been checked on behalf of this 88 -- project 89 currentProject.dependencyValues = { } 90 currentDep = nil 91end 92 93-- Specifies the build kind of the SDL project (e.g. StaticLib, SharedLib, 94-- ConsoleApp, etc.), based on premake presets. 95function SDL_kind(k) 96 if not oscompat() then return end 97 currentProject.kind = k 98end 99 100-- Specifies which platforms this project supports. Note: this list is not the 101-- exact list of supported platforms in the generated project. The list of 102-- platforms this project supports will be the unique list of all combined 103-- projects for this SDL solution. Thus, only one project needs to actually 104-- maintain a list. This function is additive, that is, everytime it is called 105-- it adds it to a unique list of platforms 106function SDL_platforms(tbl) 107 if not oscompat() then return end 108 if not currentProject.platforms then 109 currentProject.platforms = { } 110 end 111 for k,v in pairs(tbl) do 112 currentProject.platforms[#currentProject.platforms + 1] = v 113 end 114end 115 116-- Specifies the programming language of the project, such as C or C++. 117function SDL_language(k) 118 if not oscompat() then return end 119 currentProject.language = k 120end 121 122-- Specifies the root directory in which the meta-build system should search for 123-- source files, given the paths and files added. 124function SDL_sourcedir(src) 125 if not oscompat() then return end 126 currentProject.sourcedir = src 127end 128 129-- Specifies the destination location of where the IDE files related to the 130-- project should be saved after generation. 131function SDL_projectLocation(loc) 132 if not oscompat() then return end 133 currentProject.projectLocation = loc 134end 135 136-- Specifies a table of files that should be copied from the source directory 137-- to the end result build directory of the binary file. 138function SDL_copy(tbl) 139 if not oscompat() then return end 140 currentProject.copy = tbl 141end 142 143-- Specifies a list of other SDL projects in this workspace the currently active 144-- project is dependent on. If the dependent project is a library, the binary 145-- result will be copied from its directory to the build directory of the 146-- currently active project automatically. 147function SDL_projectDependencies(tbl) 148 if not oscompat() then return end 149 currentProject.projectDependencies = tbl 150end 151 152-- Specifies a list of compiler-level preprocessor definitions that should be 153-- set in the resulting project upon compile time. This adds to the current 154-- table of defines. 155function SDL_defines(tbl) 156 if not oscompat() then return end 157 if not currentProject.defines then 158 currentProject.defines = { } 159 end 160 for k,v in pairs(tbl) do 161 currentProject.defines[#currentProject.defines + 1] = v 162 end 163end 164 165-- Initializes an outside dependency this project has, such as X11 or DirectX. 166-- This function, once invoked, may change the behavior of other SDL 167-- project-related functions, so be sure to be familiar with all the functions 168-- and any specified behavior when used around SDL_dependency. 169function SDL_dependency(name) 170 if not oscompat() then return end 171 currentDep = { nil, compat = true, } 172 currentDep.name = name 173 table.insert(currentProject.dependencyTree, currentDep) 174end 175 176-- Special function for getting the current OS. This factors in whether the 177-- metabuild system is in MinGW, Cygwin, or iOS mode. 178function SDL_getos() 179 if _OPTIONS["ios"] ~= nil then 180 return "ios" 181 elseif _OPTIONS["mingw"] ~= nil then 182 return "mingw" 183 elseif _OPTIONS["cygwin"] ~= nil then 184 return "cygwin" 185 end 186 return os.get() 187end 188 189-- Specifies which operating system this dependency targets, such as windows or 190-- macosx, as per premake presets. 191function SDL_os(name) 192 if not oscompat() then return end 193 if not currentProject then return end 194 if not currentDep then 195 currentProject.opsys = name 196 currentProject.compat = osmatch(SDL_getos(), name) 197 else 198 currentDep.opsys = name 199 currentDep.compat = osmatch(SDL_getos(), name) 200 end 201end 202 203-- Specifies which operating system this dependency does not targets. This is 204-- for nearly platform-independent projects or dependencies that will not work 205-- on specific systems, such as ios. 206function SDL_notos(name) 207 if not oscompat() then return end 208 if not currentProject then return end 209 if not currentDep then 210 currentProject.opsys = "~" .. name 211 currentProject.compat = not osmatch(SDL_getos(), name) 212 else 213 currentDep.opsys = "~" .. name 214 currentDep.compat = not osmatch(SDL_getos(), name) 215 end 216end 217 218-- Changes the internal state of function compatibility based on whether the 219-- current os is the one expected; the next function will be affected by this 220-- change, but no others. The name can be a pattern using '|' to separate 221-- multiple operating systems, such as: 222-- SDL_isos("windows|macosx") 223function SDL_isos(name) 224 nextFuncCompat = osmatch(SDL_getos(), name) 225end 226 227-- Same as SDL_isos, except it negates the internal state for exclusion 228-- checking. 229function SDL_isnotos(name) 230 nextFuncCompat = not osmatch(SDL_getos(), name) 231end 232 233-- Changes the internal state of function compatibility based on whether the 234-- current system is running a 64bit Operating System and architecture; the 235-- next function will be affected by this change, but none thereafter. 236function SDL_is64bit() 237 nextFuncCompat = os.is64bit() 238end 239 240-- Same as SDL_is64bit, except it negates the internal state for 241-- exclusion checking. 242function SDL_isnot64bit() 243 nextFuncCompat = not os.is64bit() 244end 245 246-- Look at SDL_depfunc and SDL_notdepfunc for detailed information about this 247-- function. 248local function SDL_depfunc0(funcname, exclude) 249 if not oscompat() then return end 250 if not currentDep.compat then return end 251 local force = _OPTIONS[funcname:lower()] ~= nil 252 local func = dependencyFunctions[funcname:lower()] 253 if not func then 254 print("Warning: could not find dependency function named: " .. funcname) 255 currentDep.compat = false 256 return 257 end 258 local cachedFuncResults = dependencyResults[funcname:lower()] 259 local depFound, depInc, depLib, depInput 260 if cachedFuncResults then 261 depFound = cachedFuncResults.depFound 262 -- just skip the rest of the function, the user was already warned 263 -- exclude mode varies the compatibility slightly 264 if force then 265 depFound = true 266 end 267 if not depFound and not exclude then 268 currentDep.compat = false 269 return 270 elseif depFound and exclude then 271 currentDep.compat = false 272 return 273 end 274 depInc = cachedFuncResults.depInc 275 depLib = cachedFuncResults.depLib 276 depInput = cachedFuncResults.depInput 277 else 278 local result = func() 279 if result.found then 280 depFound = result.found 281 else 282 depFound = false 283 end 284 if force then 285 depFound = true 286 end 287 if result.incDirs then 288 depInc = result.incDirs 289 else 290 depInc = { } 291 end 292 if result.libDirs then 293 depLib = result.libDirs 294 else 295 depLib = { } 296 end 297 if result.libs then 298 depInput = result.libs 299 else 300 depInput = { } 301 end 302 cachedFuncResults = { } 303 cachedFuncResults.depFound = depFound 304 cachedFuncResults.depInc = depInc 305 cachedFuncResults.depLib = depLib 306 cachedFuncResults.depInput = depInput 307 dependencyResults[funcname:lower()] = cachedFuncResults 308 if not depFound and not exclude then 309 currentDep.compat = false 310 return 311 elseif depFound and exclude then 312 currentDep.compat = false 313 return 314 end 315 end 316 -- we only want to embed this dependency if we're not in exclude mode 317 if depFound and not exclude then 318 local dependency = { } 319 if not currentDep.includes then 320 currentDep.includes = { } 321 end 322 for k,v in pairs(depInc) do 323 currentDep.includes[v] = v 324 end 325 if not currentDep.libs then 326 currentDep.libs = { } 327 end 328 for k,v in pairs(depLib) do 329 currentDep.libs[v] = v 330 end 331 if not currentDep.links then 332 currentDep.links = { } 333 end 334 for k,v in pairs(depInput) do 335 currentDep.links[v] = v 336 end 337 else -- end of dependency found check 338 -- if we are not excluding this dependency, then print a warning 339 -- if not found 340 if not exclude then 341 print("Warning: could not find dependency: " .. funcname) 342 end 343 currentDep.compat = exclude 344 end 345end 346 347-- Given a dependency name, this function will register the dependency and try 348-- to pair it with a dependency function that was registered through 349-- SDL_registerDependencyChecker. If the function is not found, compatibility 350-- will automatically be dropped for this project and a warning will be printed 351-- to the standard output. Otherwise, the dependency function will be invoked 352-- and compatibility for the project will be updated. If the project currently 353-- is not compatible based on the Operating System or previous dependency, the 354-- dependency function will not be checked at all and this function will 355-- silently return. 356function SDL_depfunc(funcname) 357 SDL_depfunc0(funcname, false) 358end 359 360-- Same as SDL_depfunc, except this forces dependency on the function failing, 361-- rather than succeeding. This is useful for situations where two different 362-- files are required based on whether a dependency is found (such as the 363-- joystick and haptic systems). 364function SDL_notdepfunc(funcname) 365 SDL_depfunc0(funcname, true) 366end 367 368-- Determines whether the specified dependency is supported without actually 369-- executing the dependency or changing the internal states of the current 370-- project or dependency definition. This function will only work if the 371-- dependency has already been checked and its results cached within the 372-- definition system. This function returns true if the dependency is known to 373-- be supported, or false if otherwise (or if it cannot be known at this time). 374function SDL_assertdepfunc(funcname) 375 -- if forced, then of course it's on 376 if _OPTIONS[funcname:lower()] then 377 return true 378 end 379 local results = dependencyResults[funcname:lower()] 380 if not results or not results.depFound then 381 -- either not excuted yet, doesn't exist, or wasn't found 382 print("Warning: required dependency not found: " .. funcname .. 383 ". Make sure your dependencies are in a logical order.") 384 return false 385 end 386 return true 387end 388 389-- Returns a list of currently registered dependencies. The values within the 390-- table will be sorted, but their names will be lowercased due to internal 391-- handling of case-insensitive dependency names. 392function SDL_getDependencies() 393 local deps = { } 394 for k,_ in pairs(dependencyFunctions) do 395 deps[#deps + 1] = k 396 end 397 table.sort(deps) 398 return deps 399end 400 401-- Specifies a list of libraries that should always be linked to in this 402-- project, regardless of a dependency function. If after a dependency 403-- declaration, these files will only be included in the project if the 404-- dependency is compatible with the native system, given SDL_os usage and any 405-- sort of custom dependency function. 406function SDL_links(tbl) 407 if not oscompat() then return end 408 if currentDep and not currentDep.compat then return end 409 if currentProject.customLinks == nil then 410 currentProject.customLinks = { } 411 end 412 for i,v in ipairs(tbl) do 413 currentProject.customLinks[#currentProject.customLinks + 1] = v 414 end 415end 416 417-- Specifies a list of configuration values that are assigned as preprocessor 418-- definitions in the SDL configuration header, used to globally configure 419-- features during the building of the SDL library. If after a dependency 420-- declaration, these files will only be included in the project if the 421-- dependency is compatible with the native system, given SDL_os usage and any 422-- sort of custom dependency function. 423function SDL_config(tbl) 424 if not oscompat() then return end 425 if not currentDep then 426 currentProject.config = tbl 427 return 428 end 429 if not currentDep.compat then return end 430 currentDep.config = tbl 431end 432 433-- Specifies a list of paths where all .c, .h, and .m files should be included 434-- for compiling, where the source directory is the root. If after a dependency 435-- declaration, these files will only be included in the project if the 436-- dependency is compatible with the native system, given SDL_os usage and any 437-- sort of custom dependency function. 438function SDL_paths(tbl) 439 if not oscompat() then return end 440 if not currentDep then 441 currentProject.paths = tbl 442 return 443 end 444 if not currentDep.compat then return end 445 currentDep.paths = tbl 446end 447 448-- Specifies a list of files found within the source directory that this project 449-- should include during compile time. If after a dependency declaration, these 450-- files will only be included in the project if the dependency is compatible 451-- with the native system, given SDL_os usage and any sort of custom dependency 452-- function. 453function SDL_files(tbl) 454 if not oscompat() then return end 455 if not currentDep then 456 currentProject.files = tbl 457 return 458 end 459 if not currentDep.compat then return end 460 currentDep.files = tbl 461end