sdl_projects.lua 16 KB

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