Initial community commit

This commit is contained in:
Jef 2024-09-24 14:54:57 +02:00
parent 537bcbc862
commit fc06254474
16440 changed files with 4239995 additions and 2 deletions

View file

@ -0,0 +1,45 @@
# PREMAKE RELEASE CHECKLIST
## PREP
* Create a new release branch `release/v5.0-beta1`
* Update `CHANGES.txt`
* Set version at top of file
* `premake5 --file=scripts/changes.lua --since=<last_release_rev> changes`
* Review and clean up as needed
* Update `README.md`
* "Commits since last release" badge (once out of prerelease replace `v5.0.0-alphaXX` with `latest`)
* Update version in `src/host/premake.h`
* Update version in `website/src/pages/download.js`
* Commit changes and push release branch; wait for CI to pass
* Prep release announcement from change log
## RELEASE
* Run `premake5 package <release branch name> source` (from Posix ideally)
* On each platform, run `premake5 package <release branch name> binary`
* Submit Windows binary to [Microsoft malware analysis](https://www.microsoft.com/en-us/wdsi/filesubmission/)
* Push any remaining changes; tag release branch
* Create new release on GitHub from `CHANGES.txt`; upload files
* Post announcement to `@premakeapp`
## CYCLE
* Update version in `src/host/premake.h` (e.x `"5.0.0-dev"`)
* Commit
* Merge release branch to master
* Delete release branch

View file

@ -0,0 +1,69 @@
---
-- Output a list of merged PRs since last release in the CHANGES.txt format.
---
local usage = "Usage: premake5 --file=scripts/changes.lua --since=<rev> changes"
local sinceRev = _OPTIONS["since"]
if not sinceRev then
print(usage)
error("Missing `--since`", 0)
end
local function parsePullRequestId(line)
return line:match("#%d+%s")
end
local function parseTitle(line)
return line:match("||(.+)")
end
local function parseAuthor(line)
return line:match("%s([^%s]-)/")
end
local function parseLog(line)
local pr = parsePullRequestId(line)
local title = parseTitle(line)
local author = parseAuthor(line)
return string.format("* PR %s %s (@%s)", pr, title, author)
end
local function gatherChanges()
local cmd = string.format('git log HEAD "^%s" --merges --first-parent --format="%%s||%%b"', _OPTIONS["since"])
local output = os.outputof(cmd)
changes = {}
for line in output:gmatch("[^\r\n]+") do
table.insert(changes, parseLog(line))
end
return changes
end
local function generateChanges()
local changes = gatherChanges()
table.sort(changes)
for i = 1, #changes do
print(changes[i])
end
end
newaction {
trigger = "changes",
description = "Generate list of git merges in CHANGES.txt format",
execute = generateChanges
}
newoption {
trigger = "since",
value = "revision",
description = "Log merges since this revision"
}

View file

@ -0,0 +1,14 @@
---
-- Validate documentation for Premkake APIs.
---
local count = 0
for k,v in pairs(premake.field._loweredList) do
local docfilepath = "../website/docs/" .. k .. ".md"
local exists = os.isfile(docfilepath)
if not exists then
print("Missing documentation file for: ", k)
count = count + 1
end
end
os.exit(count)

View file

@ -0,0 +1,210 @@
--
-- Embed the Lua scripts into src/host/scripts.c as static data buffers.
-- Embeds minified versions of the actual scripts by default, rather than
-- bytecode, as bytecodes are not portable to different architectures. Use
-- the `--bytecode` flag to override.
--
local scriptCount = 0
local function loadScript(fname)
fname = path.getabsolute(fname)
local f = io.open(fname, "rb")
local s = assert(f:read("*all"))
f:close()
return s
end
local function stripScript(s)
-- strip tabs
local result = s:gsub("[\t]", "")
-- strip any CRs
result = result:gsub("[\r]", "")
-- strip out block comments
result = result:gsub("[^\"']%-%-%[%[.-%]%]", "")
result = result:gsub("[^\"']%-%-%[=%[.-%]=%]", "")
result = result:gsub("[^\"']%-%-%[==%[.-%]==%]", "")
-- strip out inline comments
result = result:gsub("\n%-%-[^\n]*", "\n")
-- strip duplicate line feeds
result = result:gsub("\n+", "\n")
-- strip out leading comments
result = result:gsub("^%-%-[^\n]*\n", "")
return result
end
local function outputScript(result, script)
local data = script.data
local length = #data
if length > 0 then
script.table = string.format("builtin_script_%d", scriptCount)
scriptCount = scriptCount + 1
buffered.writeln(result, "// ".. script.name)
buffered.writeln(result, "static const unsigned char " .. script.table .. "[] = {")
for i = 1, length do
buffered.write(result, string.format("%3d, ", data:byte(i)))
if (i % 32 == 0) then
buffered.writeln(result)
end
end
buffered.writeln(result, "};")
buffered.writeln(result)
end
end
local function addScript(result, filename, name, data)
if not data then
if not path.hasextension(filename, ".lua") then
data = loadScript(filename)
elseif _OPTIONS["bytecode"] then
verbosef("Compiling... " .. filename)
local output = path.replaceextension(filename, ".luac")
local res, err = os.compile(filename, output);
if res ~= nil then
data = loadScript(output)
os.remove(output)
else
print(err)
print("Embedding source instead.")
data = stripScript(loadScript(filename))
end
else
data = stripScript(loadScript(filename))
end
end
local script = {}
script.filename = filename
script.name = name
script.data = data
table.insert(result, script)
end
-- Prepare the file header
local result = buffered.new()
buffered.writeln(result, "/* Premake's Lua scripts, as static data buffers for release mode builds */")
buffered.writeln(result, "/* DO NOT EDIT - this file is autogenerated - see BUILD.txt */")
buffered.writeln(result, "/* To regenerate this file, run: premake5 embed */")
buffered.writeln(result, "")
buffered.writeln(result, '#include "host/premake.h"')
buffered.writeln(result, "")
-- Find all of the _manifest.lua files within the project
local mask = path.join(_MAIN_SCRIPT_DIR, "**/_manifest.lua")
local manifests = os.matchfiles(mask)
-- Find all of the _user_modules.lua files within the project
local userModuleFiles = {}
userModuleFiles = table.join(userModuleFiles, os.matchfiles(path.join(_MAIN_SCRIPT_DIR, "**/_user_modules.lua")))
userModuleFiles = table.join(userModuleFiles, os.matchfiles(path.join(_MAIN_SCRIPT_DIR, "_user_modules.lua")))
-- Generate table of embedded content.
local contentTable = {}
local nativeTable = {}
print("Compiling... ")
for mi = 1, #manifests do
local manifestName = manifests[mi]
local manifestDir = path.getdirectory(manifestName)
local moduleName = path.getbasename(manifestDir)
local baseDir = path.getdirectory(manifestDir)
local files = dofile(manifests[mi])
for fi = 1, #files do
local filename = path.join(manifestDir, files[fi])
addScript(contentTable, filename, path.getrelative(baseDir, filename))
end
-- find native code in modules.
if moduleName ~= "src" then
local nativeFile = path.join(manifestDir, 'native', moduleName .. '.c')
if os.isfile(nativeFile) then
local pretty_name = moduleName:gsub("^%l", string.upper)
table.insert(nativeTable, pretty_name)
end
end
end
addScript(contentTable, path.join(_SCRIPT_DIR, "../src/_premake_main.lua"), "src/_premake_main.lua")
addScript(contentTable, path.join(_SCRIPT_DIR, "../src/_manifest.lua"), "src/_manifest.lua")
-- Add the list of modules
local modules = dofile("../src/_modules.lua")
for _, userModules in ipairs(userModuleFiles) do
modules = table.join(modules, dofile(userModules))
end
addScript(contentTable, "_modules.lua", "src/_modules.lua", "return {" .. table.implode(modules, '"', '"', ', ') .. "}")
-- Embed the actual script contents
print("Embedding...")
for mi = 1, #contentTable do
outputScript(result, contentTable[mi])
end
-- Generate an index of the script file names. Script names are stored
-- relative to the directory containing the manifest, i.e. the main
-- Xcode script, which is at $/modules/xcode/xcode.lua is stored as
-- "xcode/xcode.lua".
buffered.writeln(result, "const buildin_mapping builtin_scripts[] = {")
for mi = 1, #contentTable do
if contentTable[mi].table then
buffered.writeln(result, string.format('\t{"%s", %s, sizeof(%s)},', contentTable[mi].name, contentTable[mi].table, contentTable[mi].table))
else
buffered.writeln(result, string.format('\t{"%s", NULL, 0},', contentTable[mi].name))
end
end
buffered.writeln(result, "\t{NULL, NULL, 0}")
buffered.writeln(result, "};")
buffered.writeln(result, "")
-- write out the registerModules method.
for _, name in ipairs(nativeTable) do
buffered.writeln(result, string.format("extern void register%s(lua_State* L);", name))
end
buffered.writeln(result, "")
buffered.writeln(result, "void registerModules(lua_State* L)")
buffered.writeln(result, "{")
buffered.writeln(result, "\t(void)(L);")
for _, name in ipairs(nativeTable) do
buffered.writeln(result, string.format("\tregister%s(L);", name))
end
buffered.writeln(result, "}")
buffered.writeln(result, "")
-- Write it all out. Check against the current contents of scripts.c first,
-- and only overwrite it if there are actual changes.
print("Writing...")
local scriptsFile = path.getabsolute(path.join(_SCRIPT_DIR, "../src/scripts.c"))
local output = buffered.tostring(result)
local f, err = os.writefile_ifnotequal(output, scriptsFile);
if (f < 0) then
error(err, 0)
elseif (f > 0) then
printf("Generated %s...", path.getrelative(os.getcwd(), scriptsFile))
end

View file

@ -0,0 +1,293 @@
---
-- Create a source or binary release package.
---
---
-- Helper function: run a command while hiding its output.
---
local function execQuiet(cmd, ...)
cmd = string.format(cmd, ...) .. " > _output_.log 2> _error_.log"
local z = os.execute(cmd)
os.remove("_output_.log")
os.remove("_error_.log")
return z
end
---
-- Check the command line arguments, and show some help if needed.
---
local allowedCompilers = {}
if os.ishost("windows") then
allowedCompilers = {
"vs2019",
"vs2017",
"vs2015",
"vs2013",
"vs2012",
"vs2010",
"vs2008",
"vs2005",
}
elseif os.ishost("linux") or os.ishost("bsd") then
allowedCompilers = {
"gcc",
"clang",
}
elseif os.ishost("macosx") then
allowedCompilers = {
"clang",
}
else
error("Unsupported host os", 0)
end
local usage = 'usage is: package <branch> <type> [<compiler>]\n' ..
' <branch> is the name of the release branch to target\n' ..
' <type> is one of "source" or "binary"\n' ..
' <compiler> (default: ' .. allowedCompilers[1] .. ') is one of ' .. table.implode(allowedCompilers, "", "", " ")
if #_ARGS ~= 2 and #_ARGS ~= 3 then
error(usage, 0)
end
local branch = _ARGS[1]
local kind = _ARGS[2]
local compiler = _ARGS[3] or allowedCompilers[1]
if kind ~= "source" and kind ~= "binary" then
print("Invalid package kind: "..kind)
error(usage, 0)
end
if not table.contains(allowedCompilers, compiler) then
print("Invalid compiler: "..compiler)
error(usage, 0)
end
local compilerIsVS = compiler:startswith("vs")
--
-- Make sure I've got what I've need to be happy.
--
local required = { "git" }
if not compilerIsVS then
table.insert(required, "make")
table.insert(required, compiler)
end
for _, value in ipairs(required) do
local z = execQuiet("%s --version", value)
if not z then
error("required tool '" .. value .. "' not found", 0)
end
end
--
-- Figure out what I'm making.
--
os.chdir("..")
local text = os.outputof(string.format('git show %s:src/host/premake.h', branch))
local _, _, version = text:find('VERSION%s*"([%w%p]+)"')
local pkgName = "premake-" .. version
local pkgExt = ".zip"
if kind == "binary" then
pkgName = pkgName .. "-" .. os.host()
if not os.istarget("windows") then
pkgExt = ".tar.gz"
end
else
pkgName = pkgName .. "-src"
end
--
-- Make sure I'm sure.
--
printf("")
printf("I am about to create a %s package", kind:upper())
printf(" ...named release/%s%s", pkgName, pkgExt)
printf(" ...from the %s branch", branch)
printf("")
printf("Does this look right to you? If so, press [Enter] to begin.")
io.read()
--
-- Pull down the release branch.
--
print("Preparing release folder")
os.mkdir("release")
os.chdir("release")
os.rmdir(pkgName)
print("Cloning source code")
local z = execQuiet("git clone .. %s -b %s --recurse-submodules --depth 1 --shallow-submodules", pkgName, branch)
if not z then
error("clone failed", 0)
end
os.chdir(pkgName)
--
-- Bootstrap Premake in the newly cloned repository
--
print("Bootstrapping Premake...")
if compilerIsVS then
z = os.execute("Bootstrap.bat " .. compiler)
else
z = os.execute("make -j -f Bootstrap.mak " .. os.host())
end
if not z then
error("Failed to Bootstrap Premake", 0)
end
local premakeBin = path.translate("./bin/release/premake5")
--
-- Make absolutely sure the embedded scripts have been updated
--
print("Updating embedded scripts...")
local z = execQuiet("%s embed %s", premakeBin, iif(kind == "source", "", "--bytecode"))
if not z then
error("failed to update the embedded scripts", 0)
end
--
-- Generate a source package.
--
if kind == "source" then
local function genProjects(parameters)
if not execQuiet("%s %s", premakeBin, parameters) then
error("failed to generate project for "..parameters, 0)
end
end
os.rmdir("build")
print("Generating project files...")
local ignoreActions = {
"clean",
"embed",
"package",
"self-test",
"test",
"gmake", -- deprecated
}
local perOSActions = {
"gmake2",
"codelite"
}
for action in premake.action.each() do
if not table.contains(ignoreActions, action.trigger) then
if table.contains(perOSActions, action.trigger) then
local osList = {
{ "windows", },
{ "unix", "linux" },
{ "macosx", },
{ "bsd", },
}
for _, os in ipairs(osList) do
local osTarget = os[2] or os[1]
genProjects(string.format("--to=build/%s.%s --os=%s %s", action.trigger, os[1], osTarget, action.trigger))
end
else
genProjects(string.format("--to=build/%s %s", action.trigger, action.trigger))
end
end
end
print("Creating source code package...")
local excludeList = {
".gitignore",
".gitattributes",
".gitmodules",
".travis.yml",
".editorconfig",
"appveyor.yml",
"Bootstrap.*",
"packages/*",
}
local includeList = {
"build",
"src/scripts.c",
}
if not execQuiet("git rm --cached -r -f --ignore-unmatch "..table.concat(excludeList, ' ')) or
not execQuiet("git add -f "..table.concat(includeList, ' ')) or
not execQuiet("git stash") or
not execQuiet("git archive --format=zip -9 -o ../%s.zip --prefix=%s/ stash@{0}", pkgName, pkgName) or
not execQuiet("git stash drop stash@{0}")
then
error("failed to archive release", 0)
end
os.chdir("..")
end
--
-- Create a binary package for this platform. This step requires a working
-- GNU/Make/GCC environment.
--
if kind == "binary" then
print("Building binary...")
os.chdir("bin/release")
local addCommand = "git add -f premake5%s"
local archiveCommand = "git archive --format=%s -o ../../../%s%s stash@{0} -- ./premake5%s"
if os.ishost("windows") then
addCommand = string.format(addCommand, ".exe")
archiveCommand = string.format(archiveCommand, "zip -9", pkgName, pkgExt, ".exe")
else
addCommand = string.format(addCommand, "")
archiveCommand = string.format(archiveCommand, "tar.gz", pkgName, pkgExt, "")
end
if not execQuiet(addCommand) or
not execQuiet("git stash") or
not execQuiet(archiveCommand) or
not execQuiet("git stash drop stash@{0}")
then
error("failed to archive release", 0)
end
os.chdir("../../..")
end
--
-- Clean up
--
-- Use RMDIR token instead of os.rmdir to force remove .git dir which has read only files
execQuiet(os.translateCommands("{RMDIR} "..pkgName))