| 1 | --
|
|---|
| 2 | -- _premake_main.lua
|
|---|
| 3 | -- Script-side entry point for the main program logic.
|
|---|
| 4 | -- Copyright (c) 2002-2015 Jason Perkins and the Premake project
|
|---|
| 5 | --
|
|---|
| 6 |
|
|---|
| 7 | local shorthelp = "Type 'premake5 --help' for help"
|
|---|
| 8 | local versionhelp = "premake5 (Premake Build Script Generator) %s"
|
|---|
| 9 | local startTime = os.clock()
|
|---|
| 10 |
|
|---|
| 11 | -- set a global.
|
|---|
| 12 | _PREMAKE_STARTTIME = startTime
|
|---|
| 13 |
|
|---|
| 14 | -- Load the collection of core scripts, required for everything else to work
|
|---|
| 15 |
|
|---|
| 16 | local modules = dofile("_modules.lua")
|
|---|
| 17 | local manifest = dofile("_manifest.lua")
|
|---|
| 18 | for i = 1, #manifest do
|
|---|
| 19 | dofile(manifest[i])
|
|---|
| 20 | end
|
|---|
| 21 |
|
|---|
| 22 |
|
|---|
| 23 | -- Create namespaces for myself
|
|---|
| 24 |
|
|---|
| 25 | local p = premake
|
|---|
| 26 | p.main = {}
|
|---|
| 27 |
|
|---|
| 28 | local m = p.main
|
|---|
| 29 |
|
|---|
| 30 |
|
|---|
| 31 | -- Keep a table of modules that have been preloaded, and their associated
|
|---|
| 32 | -- "should load" test functions.
|
|---|
| 33 |
|
|---|
| 34 | m._preloaded = {}
|
|---|
| 35 |
|
|---|
| 36 |
|
|---|
| 37 | ---
|
|---|
| 38 | -- Add a new module loader that knows how to use the Premake paths like
|
|---|
| 39 | -- PREMAKE_PATH and the --scripts option, and follows the module/module.lua
|
|---|
| 40 | -- naming convention.
|
|---|
| 41 | ---
|
|---|
| 42 |
|
|---|
| 43 | function m.installModuleLoader()
|
|---|
| 44 | if not os.ishost('windows') then
|
|---|
| 45 | local premakeDir = path.getdirectory(_PREMAKE_COMMAND)
|
|---|
| 46 | package.cpath = package.cpath .. ';' .. premakeDir .. '/?.so'
|
|---|
| 47 | end
|
|---|
| 48 | table.insert(package.searchers, 2, m.moduleLoader)
|
|---|
| 49 | end
|
|---|
| 50 |
|
|---|
| 51 | function m.moduleLoader(name)
|
|---|
| 52 | local dir = path.getdirectory(name)
|
|---|
| 53 | local base = path.getname(name)
|
|---|
| 54 |
|
|---|
| 55 | if dir ~= "." then
|
|---|
| 56 | dir = dir .. "/" .. base
|
|---|
| 57 | else
|
|---|
| 58 | dir = base
|
|---|
| 59 | end
|
|---|
| 60 |
|
|---|
| 61 | local full = dir .. "/" .. base .. ".lua"
|
|---|
| 62 |
|
|---|
| 63 | -- list of paths where to look for the module
|
|---|
| 64 | local paths = {
|
|---|
| 65 | ".modules/" .. full,
|
|---|
| 66 | "modules/" .. full,
|
|---|
| 67 | full,
|
|---|
| 68 | name .. ".lua"
|
|---|
| 69 | }
|
|---|
| 70 |
|
|---|
| 71 | -- try to locate the module
|
|---|
| 72 | for _, p in ipairs(paths) do
|
|---|
| 73 | local file = os.locate(p)
|
|---|
| 74 | if file then
|
|---|
| 75 | local chunk, err = loadfile(file)
|
|---|
| 76 | if chunk then
|
|---|
| 77 | return chunk
|
|---|
| 78 | end
|
|---|
| 79 | if err then
|
|---|
| 80 | return "\n\tload error " .. err
|
|---|
| 81 | end
|
|---|
| 82 | end
|
|---|
| 83 | end
|
|---|
| 84 |
|
|---|
| 85 | -- didn't find the module in supported paths, try the embedded scripts
|
|---|
| 86 | for _, p in ipairs(paths) do
|
|---|
| 87 | local chunk, err = loadfile("$/" .. p)
|
|---|
| 88 | if chunk then
|
|---|
| 89 | return chunk
|
|---|
| 90 | end
|
|---|
| 91 | end
|
|---|
| 92 | end
|
|---|
| 93 |
|
|---|
| 94 |
|
|---|
| 95 | ---
|
|---|
| 96 | -- Prepare the script environment; anything that should be done
|
|---|
| 97 | -- before the system script gets a chance to run.
|
|---|
| 98 | ---
|
|---|
| 99 |
|
|---|
| 100 | function m.prepareEnvironment()
|
|---|
| 101 | math.randomseed(os.time())
|
|---|
| 102 | _PREMAKE_DIR = path.getdirectory(_PREMAKE_COMMAND)
|
|---|
| 103 | p.path = p.path .. ";" .. _PREMAKE_DIR .. ";" .. _MAIN_SCRIPT_DIR
|
|---|
| 104 | end
|
|---|
| 105 |
|
|---|
| 106 |
|
|---|
| 107 | ---
|
|---|
| 108 | -- Load the required core modules that are shipped as part of Premake and
|
|---|
| 109 | -- expected to be present at startup. If a _preload.lua script is present,
|
|---|
| 110 | -- that script is run and the return value (a "should load" test) is cached
|
|---|
| 111 | -- to be called after baking is complete. Otherwise the module's main script
|
|---|
| 112 | -- is run immediately.
|
|---|
| 113 | ---
|
|---|
| 114 |
|
|---|
| 115 | function m.preloadModules()
|
|---|
| 116 | for i = 1, #modules do
|
|---|
| 117 | local name = modules[i]
|
|---|
| 118 | local preloader = name .. "/_preload.lua"
|
|---|
| 119 | preloader = os.locate("modules/" .. preloader) or os.locate(preloader)
|
|---|
| 120 | if preloader then
|
|---|
| 121 | m._preloaded[name] = include(preloader)
|
|---|
| 122 | if not m._preloaded[name] then
|
|---|
| 123 | p.warn("module '%s' should return function from _preload.lua", name)
|
|---|
| 124 | end
|
|---|
| 125 | else
|
|---|
| 126 | require(name)
|
|---|
| 127 | end
|
|---|
| 128 | end
|
|---|
| 129 | end
|
|---|
| 130 |
|
|---|
| 131 |
|
|---|
| 132 | ---
|
|---|
| 133 | -- Look for and run the system-wide configuration script; make sure any
|
|---|
| 134 | -- configuration scoping gets cleared before continuing.
|
|---|
| 135 | ---
|
|---|
| 136 |
|
|---|
| 137 | function m.runSystemScript()
|
|---|
| 138 | dofileopt(_OPTIONS["systemscript"] or { "premake5-system.lua", "premake-system.lua" })
|
|---|
| 139 | filter {}
|
|---|
| 140 | end
|
|---|
| 141 |
|
|---|
| 142 |
|
|---|
| 143 | ---
|
|---|
| 144 | -- Look for a user project script, and set up the related global
|
|---|
| 145 | -- variables if I can find one.
|
|---|
| 146 | ---
|
|---|
| 147 |
|
|---|
| 148 | function m.locateUserScript()
|
|---|
| 149 | local defaults = { "premake5.lua", "premake4.lua" }
|
|---|
| 150 | for i = 1, #defaults do
|
|---|
| 151 | if os.isfile(defaults[i]) then
|
|---|
| 152 | _MAIN_SCRIPT = defaults[i]
|
|---|
| 153 | break
|
|---|
| 154 | end
|
|---|
| 155 | end
|
|---|
| 156 |
|
|---|
| 157 | if not _MAIN_SCRIPT then
|
|---|
| 158 | _MAIN_SCRIPT = defaults[1]
|
|---|
| 159 | end
|
|---|
| 160 |
|
|---|
| 161 | if _OPTIONS.file then
|
|---|
| 162 | _MAIN_SCRIPT = _OPTIONS.file
|
|---|
| 163 | end
|
|---|
| 164 |
|
|---|
| 165 | _MAIN_SCRIPT = path.getabsolute(_MAIN_SCRIPT)
|
|---|
| 166 | _MAIN_SCRIPT_DIR = path.getdirectory(_MAIN_SCRIPT)
|
|---|
| 167 | end
|
|---|
| 168 |
|
|---|
| 169 |
|
|---|
| 170 | ---
|
|---|
| 171 | -- Set the action to be performed from the command line arguments.
|
|---|
| 172 | ---
|
|---|
| 173 |
|
|---|
| 174 | function m.prepareAction()
|
|---|
| 175 | -- The "next-gen" actions have now replaced their deprecated counterparts.
|
|---|
| 176 | -- Provide a warning for a little while before I remove them entirely.
|
|---|
| 177 | if _ACTION and _ACTION:endswith("ng") then
|
|---|
| 178 | p.warnOnce(_ACTION, "'%s' has been deprecated; use '%s' instead", _ACTION, _ACTION:sub(1, -3))
|
|---|
| 179 | end
|
|---|
| 180 | p.action.set(_ACTION)
|
|---|
| 181 |
|
|---|
| 182 | -- Allow the action to initialize stuff.
|
|---|
| 183 | local action = p.action.current()
|
|---|
| 184 | if action then
|
|---|
| 185 | p.action.initialize(action.trigger)
|
|---|
| 186 | end
|
|---|
| 187 | end
|
|---|
| 188 |
|
|---|
| 189 |
|
|---|
| 190 | ---
|
|---|
| 191 | -- If there is a project script available, run it to get the
|
|---|
| 192 | -- project information, available options and actions, etc.
|
|---|
| 193 | ---
|
|---|
| 194 |
|
|---|
| 195 | function m.runUserScript()
|
|---|
| 196 | if os.isfile(_MAIN_SCRIPT) then
|
|---|
| 197 | dofile(_MAIN_SCRIPT)
|
|---|
| 198 | end
|
|---|
| 199 | end
|
|---|
| 200 |
|
|---|
| 201 |
|
|---|
| 202 | ---
|
|---|
| 203 | -- Run the interactive prompt, if requested.
|
|---|
| 204 | ---
|
|---|
| 205 |
|
|---|
| 206 | function m.checkInteractive()
|
|---|
| 207 | if _OPTIONS.interactive then
|
|---|
| 208 | debug.prompt()
|
|---|
| 209 | end
|
|---|
| 210 | end
|
|---|
| 211 |
|
|---|
| 212 |
|
|---|
| 213 | ---
|
|---|
| 214 | -- Validate and process the command line options and arguments.
|
|---|
| 215 | ---
|
|---|
| 216 |
|
|---|
| 217 | function m.processCommandLine()
|
|---|
| 218 | -- Process special options
|
|---|
| 219 | if (_OPTIONS["version"]) then
|
|---|
| 220 | printf(versionhelp, _PREMAKE_VERSION)
|
|---|
| 221 | os.exit(0)
|
|---|
| 222 | end
|
|---|
| 223 |
|
|---|
| 224 | if (_OPTIONS["help"]) then
|
|---|
| 225 | p.showhelp()
|
|---|
| 226 | os.exit(1)
|
|---|
| 227 | end
|
|---|
| 228 |
|
|---|
| 229 | -- Validate the command-line arguments. This has to happen after the
|
|---|
| 230 | -- script has run to allow for project-specific options
|
|---|
| 231 | ok, err = p.option.validate(_OPTIONS)
|
|---|
| 232 | if not ok then
|
|---|
| 233 | print("Error: " .. err)
|
|---|
| 234 | os.exit(1)
|
|---|
| 235 | end
|
|---|
| 236 |
|
|---|
| 237 | -- If no further action is possible, show a short help message
|
|---|
| 238 | if not _OPTIONS.interactive then
|
|---|
| 239 | if not _ACTION then
|
|---|
| 240 | print(shorthelp)
|
|---|
| 241 | os.exit(1)
|
|---|
| 242 | end
|
|---|
| 243 |
|
|---|
| 244 | local action = p.action.current()
|
|---|
| 245 | if not action then
|
|---|
| 246 | print("Error: no such action '" .. _ACTION .. "'")
|
|---|
| 247 | os.exit(1)
|
|---|
| 248 | end
|
|---|
| 249 |
|
|---|
| 250 | if p.action.isConfigurable() and not os.isfile(_MAIN_SCRIPT) then
|
|---|
| 251 | print(string.format("No Premake script (%s) found!", path.getname(_MAIN_SCRIPT)))
|
|---|
| 252 | os.exit(1)
|
|---|
| 253 | end
|
|---|
| 254 | end
|
|---|
| 255 | end
|
|---|
| 256 |
|
|---|
| 257 | ---
|
|---|
| 258 | -- Start up MobDebug and try to hook up with ZeroBrane
|
|---|
| 259 | ---
|
|---|
| 260 |
|
|---|
| 261 | function m.tryHookDebugger()
|
|---|
| 262 |
|
|---|
| 263 | if (_OPTIONS["debugger"]) then
|
|---|
| 264 | print("Loading luasocket...")
|
|---|
| 265 | require('luasocket')
|
|---|
| 266 | print("Starting debugger...")
|
|---|
| 267 | local mobdebug = require('mobdebug')
|
|---|
| 268 | mobdebug.start()
|
|---|
| 269 |
|
|---|
| 270 | end
|
|---|
| 271 | end
|
|---|
| 272 |
|
|---|
| 273 | ---
|
|---|
| 274 | -- Override point, for logic that should run before baking.
|
|---|
| 275 | ---
|
|---|
| 276 |
|
|---|
| 277 | function m.preBake()
|
|---|
| 278 | if p.action.isConfigurable() then
|
|---|
| 279 | print("Building configurations...")
|
|---|
| 280 | end
|
|---|
| 281 | end
|
|---|
| 282 |
|
|---|
| 283 |
|
|---|
| 284 | ---
|
|---|
| 285 | -- "Bake" the project information, preparing it for use by the action.
|
|---|
| 286 | ---
|
|---|
| 287 |
|
|---|
| 288 | function m.bake()
|
|---|
| 289 | if p.action.isConfigurable() then
|
|---|
| 290 | p.oven.bake()
|
|---|
| 291 | end
|
|---|
| 292 | end
|
|---|
| 293 |
|
|---|
| 294 |
|
|---|
| 295 | ---
|
|---|
| 296 | -- Override point, for logic that should run after baking but before
|
|---|
| 297 | -- the configurations are validated.
|
|---|
| 298 | ---
|
|---|
| 299 |
|
|---|
| 300 | function m.postBake()
|
|---|
| 301 | local function shouldLoad(func)
|
|---|
| 302 | for wks in p.global.eachWorkspace() do
|
|---|
| 303 | for prj in p.workspace.eachproject(wks) do
|
|---|
| 304 | for cfg in p.project.eachconfig(prj) do
|
|---|
| 305 | if func(cfg) then
|
|---|
| 306 | return true
|
|---|
| 307 | end
|
|---|
| 308 | end
|
|---|
| 309 | end
|
|---|
| 310 | end
|
|---|
| 311 | end
|
|---|
| 312 |
|
|---|
| 313 | -- any modules need to load to support this project?
|
|---|
| 314 | for module, func in pairs(m._preloaded) do
|
|---|
| 315 | if not package.loaded[module] and shouldLoad(func) then
|
|---|
| 316 | require(module)
|
|---|
| 317 | end
|
|---|
| 318 | end
|
|---|
| 319 | end
|
|---|
| 320 |
|
|---|
| 321 |
|
|---|
| 322 | ---
|
|---|
| 323 | -- Sanity check the current project setup.
|
|---|
| 324 | ---
|
|---|
| 325 |
|
|---|
| 326 | function m.validate()
|
|---|
| 327 | if p.action.isConfigurable() then
|
|---|
| 328 | p.container.validate(p.api.rootContainer())
|
|---|
| 329 | end
|
|---|
| 330 | end
|
|---|
| 331 |
|
|---|
| 332 |
|
|---|
| 333 | ---
|
|---|
| 334 | -- Override point, for logic that should run after validation and
|
|---|
| 335 | -- before the action takes control.
|
|---|
| 336 | ---
|
|---|
| 337 |
|
|---|
| 338 | function m.preAction()
|
|---|
| 339 | local action = p.action.current()
|
|---|
| 340 | printf("Running action '%s'...", action.trigger)
|
|---|
| 341 | end
|
|---|
| 342 |
|
|---|
| 343 |
|
|---|
| 344 | ---
|
|---|
| 345 | -- Hand over control to the action.
|
|---|
| 346 | ---
|
|---|
| 347 |
|
|---|
| 348 | function m.callAction()
|
|---|
| 349 | local action = p.action.current()
|
|---|
| 350 | p.action.call(action.trigger)
|
|---|
| 351 | end
|
|---|
| 352 |
|
|---|
| 353 |
|
|---|
| 354 | ---
|
|---|
| 355 | -- Processing is complete.
|
|---|
| 356 | ---
|
|---|
| 357 |
|
|---|
| 358 | function m.postAction()
|
|---|
| 359 | if p.action.isConfigurable() then
|
|---|
| 360 | local duration = math.floor((os.clock() - startTime) * 1000);
|
|---|
| 361 | printf("Done (%dms).", duration)
|
|---|
| 362 | end
|
|---|
| 363 | end
|
|---|
| 364 |
|
|---|
| 365 |
|
|---|
| 366 |
|
|---|
| 367 | --
|
|---|
| 368 | -- Script-side program entry point.
|
|---|
| 369 | --
|
|---|
| 370 |
|
|---|
| 371 | m.elements = {
|
|---|
| 372 | m.tryHookDebugger,
|
|---|
| 373 | m.installModuleLoader,
|
|---|
| 374 | m.locateUserScript,
|
|---|
| 375 | m.prepareEnvironment,
|
|---|
| 376 | m.preloadModules,
|
|---|
| 377 | m.runSystemScript,
|
|---|
| 378 | m.prepareAction,
|
|---|
| 379 | m.runUserScript,
|
|---|
| 380 | m.checkInteractive,
|
|---|
| 381 | m.processCommandLine,
|
|---|
| 382 | m.preBake,
|
|---|
| 383 | m.bake,
|
|---|
| 384 | m.postBake,
|
|---|
| 385 | m.validate,
|
|---|
| 386 | m.preAction,
|
|---|
| 387 | m.callAction,
|
|---|
| 388 | m.postAction,
|
|---|
| 389 | }
|
|---|
| 390 |
|
|---|
| 391 | function _premake_main()
|
|---|
| 392 | p.callArray(m.elements)
|
|---|
| 393 | return 0
|
|---|
| 394 | end
|
|---|