| 1 | --
|
|---|
| 2 | -- Embed the Lua scripts into src/host/scripts.c as static data buffers.
|
|---|
| 3 | -- Embeds minified versions of the actual scripts by default, rather than
|
|---|
| 4 | -- bytecode, as bytecodes are not portable to different architectures. Use
|
|---|
| 5 | -- the `--bytecode` flag to override.
|
|---|
| 6 | --
|
|---|
| 7 |
|
|---|
| 8 | local scriptCount = 0
|
|---|
| 9 |
|
|---|
| 10 | local function loadScript(fname)
|
|---|
| 11 | fname = path.getabsolute(fname)
|
|---|
| 12 | local f = io.open(fname, "rb")
|
|---|
| 13 | local s = assert(f:read("*all"))
|
|---|
| 14 | f:close()
|
|---|
| 15 | return s
|
|---|
| 16 | end
|
|---|
| 17 |
|
|---|
| 18 |
|
|---|
| 19 | local function stripScript(s)
|
|---|
| 20 | -- strip tabs
|
|---|
| 21 | local result = s:gsub("[\t]", "")
|
|---|
| 22 |
|
|---|
| 23 | -- strip any CRs
|
|---|
| 24 | result = result:gsub("[\r]", "")
|
|---|
| 25 |
|
|---|
| 26 | -- strip out block comments
|
|---|
| 27 | result = result:gsub("[^\"']%-%-%[%[.-%]%]", "")
|
|---|
| 28 | result = result:gsub("[^\"']%-%-%[=%[.-%]=%]", "")
|
|---|
| 29 | result = result:gsub("[^\"']%-%-%[==%[.-%]==%]", "")
|
|---|
| 30 |
|
|---|
| 31 | -- strip out inline comments
|
|---|
| 32 | result = result:gsub("\n%-%-[^\n]*", "\n")
|
|---|
| 33 |
|
|---|
| 34 | -- strip duplicate line feeds
|
|---|
| 35 | result = result:gsub("\n+", "\n")
|
|---|
| 36 |
|
|---|
| 37 | -- strip out leading comments
|
|---|
| 38 | result = result:gsub("^%-%-[^\n]*\n", "")
|
|---|
| 39 |
|
|---|
| 40 | return result
|
|---|
| 41 | end
|
|---|
| 42 |
|
|---|
| 43 |
|
|---|
| 44 | local function outputScript(result, script)
|
|---|
| 45 | local data = script.data
|
|---|
| 46 | local length = #data
|
|---|
| 47 |
|
|---|
| 48 | if length > 0 then
|
|---|
| 49 | script.table = string.format("builtin_script_%d", scriptCount)
|
|---|
| 50 | scriptCount = scriptCount + 1
|
|---|
| 51 |
|
|---|
| 52 | buffered.writeln(result, "// ".. script.name)
|
|---|
| 53 | buffered.writeln(result, "static const unsigned char " .. script.table .. "[] = {")
|
|---|
| 54 |
|
|---|
| 55 | for i = 1, length do
|
|---|
| 56 | buffered.write(result, string.format("%3d, ", data:byte(i)))
|
|---|
| 57 | if (i % 32 == 0) then
|
|---|
| 58 | buffered.writeln(result)
|
|---|
| 59 | end
|
|---|
| 60 | end
|
|---|
| 61 |
|
|---|
| 62 | buffered.writeln(result, "};")
|
|---|
| 63 | buffered.writeln(result)
|
|---|
| 64 | end
|
|---|
| 65 | end
|
|---|
| 66 |
|
|---|
| 67 |
|
|---|
| 68 | local function addScript(result, filename, name, data)
|
|---|
| 69 | if not data then
|
|---|
| 70 | if not path.hasextension(filename, ".lua") then
|
|---|
| 71 | data = loadScript(filename)
|
|---|
| 72 | elseif _OPTIONS["bytecode"] then
|
|---|
| 73 | verbosef("Compiling... " .. filename)
|
|---|
| 74 | local output = path.replaceextension(filename, ".luac")
|
|---|
| 75 | local res, err = os.compile(filename, output);
|
|---|
| 76 | if res ~= nil then
|
|---|
| 77 | data = loadScript(output)
|
|---|
| 78 | os.remove(output)
|
|---|
| 79 | else
|
|---|
| 80 | print(err)
|
|---|
| 81 | print("Embedding source instead.")
|
|---|
| 82 | data = stripScript(loadScript(filename))
|
|---|
| 83 | end
|
|---|
| 84 | else
|
|---|
| 85 | data = stripScript(loadScript(filename))
|
|---|
| 86 | end
|
|---|
| 87 | end
|
|---|
| 88 |
|
|---|
| 89 | local script = {}
|
|---|
| 90 | script.filename = filename
|
|---|
| 91 | script.name = name
|
|---|
| 92 | script.data = data
|
|---|
| 93 | table.insert(result, script)
|
|---|
| 94 | end
|
|---|
| 95 |
|
|---|
| 96 |
|
|---|
| 97 | -- Prepare the file header
|
|---|
| 98 |
|
|---|
| 99 | local result = buffered.new()
|
|---|
| 100 | buffered.writeln(result, "/* Premake's Lua scripts, as static data buffers for release mode builds */")
|
|---|
| 101 | buffered.writeln(result, "/* DO NOT EDIT - this file is autogenerated - see BUILD.txt */")
|
|---|
| 102 | buffered.writeln(result, "/* To regenerate this file, run: premake5 embed */")
|
|---|
| 103 | buffered.writeln(result, "")
|
|---|
| 104 | buffered.writeln(result, '#include "host/premake.h"')
|
|---|
| 105 | buffered.writeln(result, "")
|
|---|
| 106 |
|
|---|
| 107 | -- Find all of the _manifest.lua files within the project
|
|---|
| 108 |
|
|---|
| 109 | local mask = path.join(_MAIN_SCRIPT_DIR, "**/_manifest.lua")
|
|---|
| 110 | local manifests = os.matchfiles(mask)
|
|---|
| 111 |
|
|---|
| 112 | -- Find all of the _user_modules.lua files within the project
|
|---|
| 113 |
|
|---|
| 114 | local userModuleFiles = {}
|
|---|
| 115 | userModuleFiles = table.join(userModuleFiles, os.matchfiles(path.join(_MAIN_SCRIPT_DIR, "**/_user_modules.lua")))
|
|---|
| 116 | userModuleFiles = table.join(userModuleFiles, os.matchfiles(path.join(_MAIN_SCRIPT_DIR, "_user_modules.lua")))
|
|---|
| 117 |
|
|---|
| 118 |
|
|---|
| 119 | -- Generate table of embedded content.
|
|---|
| 120 | local contentTable = {}
|
|---|
| 121 | local nativeTable = {}
|
|---|
| 122 |
|
|---|
| 123 | print("Compiling... ")
|
|---|
| 124 | for mi = 1, #manifests do
|
|---|
| 125 | local manifestName = manifests[mi]
|
|---|
| 126 | local manifestDir = path.getdirectory(manifestName)
|
|---|
| 127 | local moduleName = path.getbasename(manifestDir)
|
|---|
| 128 | local baseDir = path.getdirectory(manifestDir)
|
|---|
| 129 |
|
|---|
| 130 | local files = dofile(manifests[mi])
|
|---|
| 131 | for fi = 1, #files do
|
|---|
| 132 | local filename = path.join(manifestDir, files[fi])
|
|---|
| 133 | addScript(contentTable, filename, path.getrelative(baseDir, filename))
|
|---|
| 134 | end
|
|---|
| 135 |
|
|---|
| 136 | -- find native code in modules.
|
|---|
| 137 | if moduleName ~= "src" then
|
|---|
| 138 | local nativeFile = path.join(manifestDir, 'native', moduleName .. '.c')
|
|---|
| 139 | if os.isfile(nativeFile) then
|
|---|
| 140 | local pretty_name = moduleName:gsub("^%l", string.upper)
|
|---|
| 141 | table.insert(nativeTable, pretty_name)
|
|---|
| 142 | end
|
|---|
| 143 | end
|
|---|
| 144 | end
|
|---|
| 145 |
|
|---|
| 146 | addScript(contentTable, path.join(_SCRIPT_DIR, "../src/_premake_main.lua"), "src/_premake_main.lua")
|
|---|
| 147 | addScript(contentTable, path.join(_SCRIPT_DIR, "../src/_manifest.lua"), "src/_manifest.lua")
|
|---|
| 148 |
|
|---|
| 149 | -- Add the list of modules
|
|---|
| 150 |
|
|---|
| 151 | local modules = dofile("../src/_modules.lua")
|
|---|
| 152 | for _, userModules in ipairs(userModuleFiles) do
|
|---|
| 153 | modules = table.join(modules, dofile(userModules))
|
|---|
| 154 | end
|
|---|
| 155 |
|
|---|
| 156 | addScript(contentTable, "_modules.lua", "src/_modules.lua", "return {" .. table.implode(modules, '"', '"', ', ') .. "}")
|
|---|
| 157 |
|
|---|
| 158 | -- Embed the actual script contents
|
|---|
| 159 |
|
|---|
| 160 | print("Embedding...")
|
|---|
| 161 | for mi = 1, #contentTable do
|
|---|
| 162 | outputScript(result, contentTable[mi])
|
|---|
| 163 | end
|
|---|
| 164 |
|
|---|
| 165 | -- Generate an index of the script file names. Script names are stored
|
|---|
| 166 | -- relative to the directory containing the manifest, i.e. the main
|
|---|
| 167 | -- Xcode script, which is at $/modules/xcode/xcode.lua is stored as
|
|---|
| 168 | -- "xcode/xcode.lua".
|
|---|
| 169 | buffered.writeln(result, "const buildin_mapping builtin_scripts[] = {")
|
|---|
| 170 |
|
|---|
| 171 | for mi = 1, #contentTable do
|
|---|
| 172 | if contentTable[mi].table then
|
|---|
| 173 | buffered.writeln(result, string.format('\t{"%s", %s, sizeof(%s)},', contentTable[mi].name, contentTable[mi].table, contentTable[mi].table))
|
|---|
| 174 | else
|
|---|
| 175 | buffered.writeln(result, string.format('\t{"%s", NULL, 0},', contentTable[mi].name))
|
|---|
| 176 | end
|
|---|
| 177 | end
|
|---|
| 178 |
|
|---|
| 179 | buffered.writeln(result, "\t{NULL, NULL, 0}")
|
|---|
| 180 | buffered.writeln(result, "};")
|
|---|
| 181 | buffered.writeln(result, "")
|
|---|
| 182 |
|
|---|
| 183 | -- write out the registerModules method.
|
|---|
| 184 |
|
|---|
| 185 | for _, name in ipairs(nativeTable) do
|
|---|
| 186 | buffered.writeln(result, string.format("extern void register%s(lua_State* L);", name))
|
|---|
| 187 | end
|
|---|
| 188 | buffered.writeln(result, "")
|
|---|
| 189 | buffered.writeln(result, "void registerModules(lua_State* L)")
|
|---|
| 190 | buffered.writeln(result, "{")
|
|---|
| 191 | buffered.writeln(result, "\t(void)(L);")
|
|---|
| 192 | for _, name in ipairs(nativeTable) do
|
|---|
| 193 | buffered.writeln(result, string.format("\tregister%s(L);", name))
|
|---|
| 194 | end
|
|---|
| 195 | buffered.writeln(result, "}")
|
|---|
| 196 | buffered.writeln(result, "")
|
|---|
| 197 |
|
|---|
| 198 | -- Write it all out. Check against the current contents of scripts.c first,
|
|---|
| 199 | -- and only overwrite it if there are actual changes.
|
|---|
| 200 |
|
|---|
| 201 | print("Writing...")
|
|---|
| 202 | local scriptsFile = path.getabsolute(path.join(_SCRIPT_DIR, "../src/scripts.c"))
|
|---|
| 203 | local output = buffered.tostring(result)
|
|---|
| 204 |
|
|---|
| 205 | local f, err = os.writefile_ifnotequal(output, scriptsFile);
|
|---|
| 206 | if (f < 0) then
|
|---|
| 207 | error(err, 0)
|
|---|
| 208 | elseif (f > 0) then
|
|---|
| 209 | printf("Generated %s...", path.getrelative(os.getcwd(), scriptsFile))
|
|---|
| 210 | end
|
|---|