From 6bbbd0193a5fbcb39e5a30d96f7320e47a59eaec Mon Sep 17 00:00:00 2001 From: kento2 Date: Fri, 3 Apr 2026 23:13:20 +0200 Subject: [PATCH] . --- files/.config/lxterminal/lxterminal.conf | 4 +- files/.cwmrc | 10 +- files/.local/bin/read-superdisk | 2 + files/.premake/ninja/LICENSE | 22 + files/.premake/ninja/README.md | 44 ++ files/.premake/ninja/_manifest.lua | 4 + files/.premake/ninja/_preload.lua | 61 ++ files/.premake/ninja/ninja.lua | 785 +++++++++++++++++++++++ files/.premake/premake-system.lua | 1 + files/.zshrc | 2 + 10 files changed, 928 insertions(+), 7 deletions(-) create mode 100755 files/.local/bin/read-superdisk create mode 100644 files/.premake/ninja/LICENSE create mode 100644 files/.premake/ninja/README.md create mode 100644 files/.premake/ninja/_manifest.lua create mode 100644 files/.premake/ninja/_preload.lua create mode 100644 files/.premake/ninja/ninja.lua create mode 100644 files/.premake/premake-system.lua diff --git a/files/.config/lxterminal/lxterminal.conf b/files/.config/lxterminal/lxterminal.conf index 1a0cde0..78bab38 100644 --- a/files/.config/lxterminal/lxterminal.conf +++ b/files/.config/lxterminal/lxterminal.conf @@ -28,8 +28,8 @@ cursorunderline=false audiblebell=false visualbell=false tabpos=top -geometry_columns=80 -geometry_rows=24 +geometry_columns=81 +geometry_rows=25 hidescrollbar=true hidemenubar=true hideclosebutton=false diff --git a/files/.cwmrc b/files/.cwmrc index 811cf33..b11f5ce 100644 --- a/files/.cwmrc +++ b/files/.cwmrc @@ -8,7 +8,7 @@ fontname "Iosevka:pixelsize=14:bold" # Appearance borderwidth 2 -color activeborder "#ff0000" +color activeborder "#009960" color inactiveborder "#565656" color urgencyborder "#cc241d" @@ -24,7 +24,7 @@ gap 8 8 8 8 # Size of manually tiled Windows in % htile 50 -vtile 50 +vtile 55 # How many pixels a window gets moved by moveamount 50 @@ -83,15 +83,15 @@ bind-key 4-a group-toggle-all # What follows is rather self-explanatory bind-key 4-r restart -bind-key 4-q quit +bind-key 4MS-q quit bind-key 4S-d window-close bind-key 4-u window-hide bind-key 4-g window-fullscreen bind-key 4-m window-maximize -bind-key 4-t window-htile -bind-key 4S-t window-vtile +bind-key 4C-t window-htile +bind-key 4-t window-vtile # Cycle/reverse cycle through windows bind-key 4-j window-cycle diff --git a/files/.local/bin/read-superdisk b/files/.local/bin/read-superdisk new file mode 100755 index 0000000..63c1c7b --- /dev/null +++ b/files/.local/bin/read-superdisk @@ -0,0 +1,2 @@ +#!/bin/sh +sg_raw "${1:-/dev/sr0}" EA 00 00 00 00 00 01 diff --git a/files/.premake/ninja/LICENSE b/files/.premake/ninja/LICENSE new file mode 100644 index 0000000..b71e184 --- /dev/null +++ b/files/.premake/ninja/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +Copyright (c) 2015 Dmitry Ivanov + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + diff --git a/files/.premake/ninja/README.md b/files/.premake/ninja/README.md new file mode 100644 index 0000000..397574f --- /dev/null +++ b/files/.premake/ninja/README.md @@ -0,0 +1,44 @@ +# premake-ninja + +[Premake](https://github.com/premake/premake-core) module to support [Ninja](https://github.com/martine/ninja), because it's awesome. +Note recent version of premake handles ninja natively + +## Usage (little reminder) +1. Put these files in a "premake-ninja" subdirectory of [Premake search paths](https://premake.github.io/docs/Locating-Scripts/).
+ +2. Adapt your premake5.lua script, or better: create/adapt your [premake-system.lua](https://premake.github.io/docs/System-Scripts/) + +```lua +require "premake-ninja/premake-ninja" +``` + +3. Generate ninja files + +```sh +premake5 premake-ninja +``` +On msys2 (mingw) +```sh +premake5 premake-ninja --cc=gcc --shell=posix +``` + +4. Run ninja + +For each project - configuration pair, we create separate .ninja file. For solution we create build.ninja file which imports other .ninja files with subninja command. + +Build.ninja file sets phony targets for configuration names so you can build them from command line. And default target is the first configuration name in your project (usually default). + +General from: +```sh +ninja $(YourProjectName)_$(ConfigName) +``` +as example: +```sh +ninja myapp_Release +``` + +### Tested on ![ubuntu-badge](https://github.com/jimon/premake-ninja/actions/workflows/ubuntu.yml/badge.svg) ![windows-badge](https://github.com/jimon/premake-ninja/actions/workflows/windows.yml/badge.svg) ![macos-badge](https://github.com/jimon/premake-ninja/actions/workflows/macos.yml/badge.svg) + +### Extra Tests + +Part of integration tests of several generators in https://github.com/Jarod42/premake-sample-projects ![Premake5 ubuntu ninja badge](https://github.com/Jarod42/premake-sample-projects/actions/workflows/premake5-ubuntu-ninja.yml/badge.svg)![Premake5 window ninja badge](https://github.com/Jarod42/premake-sample-projects/actions/workflows/premake5-windows-ninja.yml/badge.svg) diff --git a/files/.premake/ninja/_manifest.lua b/files/.premake/ninja/_manifest.lua new file mode 100644 index 0000000..add6037 --- /dev/null +++ b/files/.premake/ninja/_manifest.lua @@ -0,0 +1,4 @@ +return { + '_preload.lua', + 'premake-ninja.lua', +} diff --git a/files/.premake/ninja/_preload.lua b/files/.premake/ninja/_preload.lua new file mode 100644 index 0000000..8ba3e0e --- /dev/null +++ b/files/.premake/ninja/_preload.lua @@ -0,0 +1,61 @@ +-- +-- Name: premake-ninja/_preload.lua +-- Purpose: Define the ninja action. +-- Author: Dmitry Ivanov +-- Created: 2015/07/04 +-- Copyright: (c) 2015 Dmitry Ivanov +-- + +local p = premake + +newaction { + -- Metadata for the command line and help system + trigger = 'ninja', + shortname = 'ninja', + description = 'Ninja is a small build system with a focus on speed', + + -- The capabilities of this action + valid_kinds = { 'ConsoleApp', 'WindowedApp', 'SharedLib', 'StaticLib', 'None' }, -- Not supported: Makefile, Packaging, SharedItems, Utility + valid_languages = { 'C', 'C++' }, + valid_tools = { cc = { 'gcc', 'clang', 'msc', 'emcc' } }, + + toolset = iif( + os.target() == 'windows', + 'msc-v142', -- Visual Studio 2019 + iif(os.target() == 'macosx', 'clang', 'gcc') + ), + + -- Workspace and project generation logic + onWorkspace = function(wks) + p.eol('\r\n') + p.indent(' ') + p.generate(wks, 'build.ninja', p.modules.ninja.generateWorkspace) + end, + onProject = function(prj) + p.eol('\r\n') + p.indent(' ') + p.modules.ninja.generateProject(prj) + end, + onBranch = function(prj) + p.eol('\r\n') + p.indent(' ') + p.modules.ninja.generateProject(prj) + end, + onCleanSolution = function(sln) + -- TODO + end, + onCleanProject = function(prj) + -- TODO + end, + onCleanTarget = function(prj) + -- TODO + end, +} + +-- +-- Decide when the full module should be loaded. +-- + +return function(cfg) + return (_ACTION == 'premake-ninja') +end diff --git a/files/.premake/ninja/ninja.lua b/files/.premake/ninja/ninja.lua new file mode 100644 index 0000000..0b738c7 --- /dev/null +++ b/files/.premake/ninja/ninja.lua @@ -0,0 +1,785 @@ +-- +-- Name: premake-ninja/ninja.lua +-- Purpose: Define the ninja action. +-- Author: Dmitry Ivanov +-- Created: 2015/07/04 +-- Copyright: (c) 2015 Dmitry Ivanov +-- + +local p = premake +local tree = p.tree +local project = p.project +local config = p.config +local fileconfig = p.fileconfig + +-- Some toolset fixes/helper +p.tools.clang.objectextension = '.o' +p.tools.gcc.objectextension = '.o' +p.tools.msc.objectextension = '.obj' + +p.tools.clang.tools.rc = p.tools.clang.tools.rc or 'windres' + +p.tools.msc.gettoolname = function(cfg, name) + local map = { cc = 'cl', cxx = 'cl', ar = 'lib', rc = 'rc' } + return map[name] +end + +-- Ninja module +premake.modules.ninja = {} +local ninja = p.modules.ninja + +ninja.handlers = {} + +function ninja.register_handler(kind, compilation_rules, target_rules) + ninja.handlers[kind] = { compilation_rules = compilation_rules, target_rules = target_rules } +end + +local function get_key(cfg, name) + local name = name or cfg.project.name + + if cfg.platform then + return name .. '_' .. cfg.buildcfg .. '_' .. cfg.platform + else + return name .. '_' .. cfg.buildcfg + end +end + +local build_cache = {} + +function ninja.add_build(cfg, out, implicit_outputs, command, inputs, implicit_inputs, dependencies, vars) + implicit_outputs = ninja.list(table.translate(implicit_outputs, ninja.esc)) + if #implicit_outputs > 0 then + implicit_outputs = ' |' .. implicit_outputs + else + implicit_outputs = '' + end + + inputs = ninja.list(table.translate(inputs, ninja.esc)) + + implicit_inputs = ninja.list(table.translate(implicit_inputs, ninja.esc)) + if #implicit_inputs > 0 then + implicit_inputs = ' |' .. implicit_inputs + else + implicit_inputs = '' + end + + dependencies = ninja.list(table.translate(dependencies, ninja.esc)) + if #dependencies > 0 then + dependencies = ' ||' .. dependencies + else + dependencies = '' + end + build_line = 'build ' .. ninja.esc(out) .. implicit_outputs .. ': ' .. command .. inputs .. implicit_inputs .. dependencies + + local cached = build_cache[out] + if cached ~= nil then + if build_line == cached.build_line and table.equals(vars or {}, cached.vars or {}) then + -- custom_command/copy rule are identical for each configuration (contrary to other rules) + -- So we can compare extra parameter + if command == 'custom_command' or command == 'copy' then + p.outln('# INFO: Rule ignored, same as ' .. cached.cfg_key) + else + local cfg_key = cfg and get_key(cfg) or 'Global scope' + p.warn(cached.cfg_key .. ' and ' .. cfg_key .. ' both generate (differently?) ' .. out .. '. Ignoring ' .. cfg_key) + p.outln('# WARNING: Rule ignored, using the one from ' .. cached.cfg_key) + end + else + local cfg_key = cfg and get_key(cfg) or 'Global scope' + p.warn(cached.cfg_key .. ' and ' .. cfg_key .. ' both generate differently ' .. out .. '. Ignoring ' .. cfg_key) + p.outln('# ERROR: Rule ignored, using the one from ' .. cached.cfg_key) + end + p.outln('# ' .. build_line) + for i, var in ipairs(vars or {}) do + p.outln('# ' .. var) + end + return + end + p.outln(build_line) + for i, var in ipairs(vars or {}) do + p.outln(' ' .. var) + end + build_cache[out] = { + cfg_key = cfg and get_key(cfg) or 'Global scope', + build_line = build_line, + vars = vars, + } +end + +local function build_command(commands, command_sep) + command_sep = command_sep or '&&' + if #commands > 1 then + local command = iif(os.shell() == 'cmd', 'cmd /c ', 'sh -c ') + return command .. ninja.quote(table.implode(commands, '', '', ' ' .. command_sep .. '$\n ')) + else + return commands[1] + end +end + +function ninja.emit_rule(name, command, description, opts) + opts = opts or {} + p.outln('rule ' .. name) + p.outln(' command = ' .. command) + p.outln(' description = ' .. description) + for key, value in pairs(opts) do + p.outln(' ' .. key .. ' = ' .. value) + end + p.outln('') +end + +function ninja.emit_flags(name, value) + p.outln(name .. '=' .. value) +end + +function ninja.esc(value) + value = value:gsub('%$', '$$') -- TODO maybe there is better way + value = value:gsub(':', '$:') + value = value:gsub('\n', '$\n') + value = value:gsub(' ', '$ ') + return value +end + +function ninja.quote(value) + value = value:gsub('\\', '\\\\') + value = value:gsub("'", "\\'") + value = value:gsub('"', '\\"') + + return '"' .. value .. '"' +end + +-- in some cases we write file names in rule commands directly +-- so we need to propely escape them +function ninja.shesc(value) + if type(value) == 'table' then + return table.translate(value, ninja.shesc) + end + + if value:find(' ') or value:find('"') or value:find('(', 1, true) or value:find(')') or value:find('|') or value:find('&') then + return ninja.quote(value) + end + return value +end + +function ninja.can_generate(prj) + return p.action.supports(prj.kind) and prj.kind ~= p.NONE +end + +-- generate solution that will call ninja for projects +function ninja.generateWorkspace(wks) + local oldGetDefaultSeparator = path.getDefaultSeparator + path.getDefaultSeparator = function() + return '/' + end + + p.outln('# solution build file') + p.outln('# generated with premake ninja') + p.outln('') + + p.outln('# build projects') + local cfgs = {} -- key is concatenated name or variant name, value is string of outputs names + local key = '' + local cfg_first = nil + local cfg_first_lib = nil + local subninjas = {} + + for prj in p.workspace.eachproject(wks) do + if ninja.can_generate(prj) then + for cfg in p.project.eachconfig(prj) do + key = get_key(cfg) + + if not cfgs[cfg.buildcfg] then + cfgs[cfg.buildcfg] = {} + end + table.insert(cfgs[cfg.buildcfg], key) + + -- set first configuration name + if wks.defaultplatform == nil then + if (cfg_first == nil) and (cfg.kind == p.CONSOLEAPP or cfg.kind == p.WINDOWEDAPP) then + cfg_first = key + end + end + if (cfg_first_lib == nil) and (cfg.kind == p.STATICLIB or cfg.kind == p.SHAREDLIB) then + cfg_first_lib = key + end + if prj.name == wks.startproject then + if wks.defaultplatform == nil then + cfg_first = key + elseif cfg.platform == wks.defaultplatform then + if cfg_first == nil then + cfg_first = key + end + end + end + + -- include other ninja file + table.insert(subninjas, ninja.esc(ninja.projectCfgFilename(cfg, true))) + p.outln('subninja ' .. ninja.esc(ninja.projectCfgFilename(cfg, true))) + end + end + end + + if cfg_first == nil then + cfg_first = cfg_first_lib + end + + p.outln('') + + p.outln('# targets') + for cfg, outputs in spairs(cfgs) do + p.outln('build ' .. ninja.esc(cfg) .. ': phony' .. ninja.list(table.translate(outputs, ninja.esc))) + end + p.outln('') + + if wks.editorintegration then + -- we need to filter out the 'file' argument, since we already output + -- the script separately. + local args = {} + for _, arg in ipairs(_ARGV) do + if not (arg:startswith('--file') or arg:startswith('/file')) then + table.insert(args, arg) + end + end + table.sort(args) + + p.outln('# Rule') + ninja.emit_rule('premake', ninja.shesc(p.workspace.getrelative(wks, _PREMAKE_COMMAND)) .. ' --file=$in ' .. table.concat(ninja.shesc(args), ' '), 'run premake', { generator = 'true', restat = 'true' }) + ninja.add_build(nil, 'build.ninja', subninjas, 'premake', { p.workspace.getrelative(wks, _MAIN_SCRIPT) }, {}, {}, {}) + p.outln('') + end + + if cfg_first then + p.outln('# default target') + p.outln('default ' .. ninja.esc(cfg_first)) + p.outln('') + end + + path.getDefaultSeparator = oldGetDefaultSeparator +end + +function ninja.list(value) + if #value > 0 then + return ' ' .. table.concat(value, ' ') + else + return '' + end +end + +local function shouldcompileasc(filecfg) + if filecfg.compileas and filecfg.compileas ~= 'Default' then + return p.languages.isc(filecfg.compileas) + end + return path.iscfile(filecfg.abspath) +end + +local function shouldcompileascpp(filecfg) + if filecfg.compileas and filecfg.compileas ~= 'Default' then + return p.languages.iscpp(filecfg.compileas) + end + return path.iscppfile(filecfg.abspath) +end + +local function getFileDependencies(cfg) + local dependencies = {} + if #cfg.prebuildcommands > 0 or cfg.prebuildmessage then + dependencies = { 'prebuild_' .. get_key(cfg) } + end + for i = 1, #cfg.dependson do + local dependpostfix = '' + if cfg.platform then + dependpostfix = '_' .. cfg.platform + end + + table.insert(dependencies, cfg.dependson[i] .. '_' .. cfg.buildcfg .. dependpostfix) + end + return dependencies +end + +local function getcflags(toolset, cfg, filecfg) + p.escaper(ninja.shesc) + local buildopt = ninja.list(filecfg.buildoptions) + local cppflags = ninja.list(toolset.getcppflags(filecfg)) + local cflags = ninja.list(toolset.getcflags(filecfg)) + local defines = ninja.list(table.join(toolset.getdefines(filecfg.defines, filecfg), toolset.getundefines(filecfg.undefines))) + local includes = ninja.list(toolset.getincludedirs(cfg, filecfg.includedirs, filecfg.externalincludedirs, filecfg.frameworkdirs, filecfg.includedirsafter)) + local forceincludes = ninja.list(toolset.getforceincludes(cfg)) + p.escaper(nil) + + return buildopt .. cppflags .. cflags .. defines .. includes .. forceincludes +end + +local function getcxxflags(toolset, cfg, filecfg) + p.escaper(ninja.shesc) + local buildopt = ninja.list(filecfg.buildoptions) + local cppflags = ninja.list(toolset.getcppflags(filecfg)) + local cxxflags = ninja.list(toolset.getcxxflags(filecfg)) + local defines = ninja.list(table.join(toolset.getdefines(filecfg.defines, filecfg), toolset.getundefines(filecfg.undefines))) + local includes = ninja.list(toolset.getincludedirs(cfg, filecfg.includedirs, filecfg.externalincludedirs, filecfg.frameworkdirs, filecfg.includedirsafter)) + local forceincludes = ninja.list(toolset.getforceincludes(cfg)) + p.escaper(nil) + + return buildopt .. cppflags .. cxxflags .. defines .. includes .. forceincludes +end + +local function getldflags(toolset, cfg) + local ldflags = ninja.list(table.join(toolset.getLibraryDirectories(cfg), toolset.getrunpathdirs(cfg, table.join(cfg.runpathdirs, config.getsiblingtargetdirs(cfg))), toolset.getldflags(cfg), cfg.linkoptions)) + + -- experimental feature, change install_name of shared libs + --[[ + if toolset == p.tools.clang and cfg.kind == p.SHAREDLIB and cfg.buildtarget.name:endswith('.dylib') then + ldflags = ldflags .. ' -install_name ' .. cfg.buildtarget.name + end + --]] + + return ldflags +end + +local function getresflags(toolset, cfg, filecfg) + p.escaper(ninja.shesc) + local defines = ninja.list(toolset.getdefines(table.join(filecfg.defines, filecfg.resdefines), filecfg)) + local includes = ninja.list(toolset.getincludedirs(cfg, table.join(filecfg.externalincludedirs, filecfg.includedirsafter, filecfg.includedirs, filecfg.resincludedirs), {}, {}, {})) + local options = ninja.list(cfg.resoptions) + p.escaper(nil) + + return defines .. includes .. options +end + +local function prebuild_rule(cfg) + if #cfg.prebuildcommands > 0 or cfg.prebuildmessage then + local commands = {} + if cfg.prebuildmessage then + commands = { os.translateCommandsAndPaths('{ECHO} ' .. cfg.prebuildmessage, cfg.workspace.basedir, cfg.workspace.location) } + end + commands = table.join(commands, os.translateCommandsAndPaths(cfg.prebuildcommands, cfg.workspace.basedir, cfg.workspace.location)) + ninja.emit_rule('run_prebuild', build_command(commands, ';'), 'prebuild') + end +end + +local function prelink_rule(cfg) + if #cfg.prelinkcommands > 0 or cfg.prelinkmessage then + local commands = {} + if cfg.prelinkmessage then + commands = { os.translateCommandsAndPaths('{ECHO} ' .. cfg.prelinkmessage, cfg.workspace.basedir, cfg.workspace.location) } + end + commands = table.join(commands, os.translateCommandsAndPaths(cfg.prelinkcommands, cfg.workspace.basedir, cfg.workspace.location)) + ninja.emit_rule('run_prelink', build_command(commands, ';'), 'prelink') + end +end + +local function postbuild_rule(cfg) + if #cfg.postbuildcommands > 0 or cfg.postbuildmessage then + local commands = {} + if cfg.postbuildmessage then + commands = { os.translateCommandsAndPaths('{ECHO} ' .. cfg.postbuildmessage, cfg.workspace.basedir, cfg.workspace.location) } + end + commands = table.join(commands, os.translateCommandsAndPaths(cfg.postbuildcommands, cfg.workspace.basedir, cfg.workspace.location)) + ninja.emit_rule('run_postbuild', build_command(commands, ';'), 'postbuild') + end +end + +local function c_cpp_compilation_rules(cfg, toolset, pch) + ---------------------------------------------------- figure out toolset executables + local cc = toolset.gettoolname(cfg, 'cc') + local cxx = toolset.gettoolname(cfg, 'cxx') + local ar = toolset.gettoolname(cfg, 'ar') + local link = toolset.gettoolname(cfg, iif(cfg.language == 'C', 'cc', 'cxx')) + local rc = toolset.gettoolname(cfg, 'rc') + + -- all paths need to be relative to the workspace output location, + -- and not relative to the project output location. + -- override the toolset getrelative function to achieve this + + local getrelative = p.tools.getrelative + p.tools.getrelative = function(cfg, value) + return p.workspace.getrelative(cfg.workspace, value) + end + + local all_cflags = getcflags(toolset, cfg, cfg) + local all_cxxflags = getcxxflags(toolset, cfg, cfg) + local all_ldflags = getldflags(toolset, cfg) + local all_resflags = getresflags(toolset, cfg, cfg) + + if toolset == p.tools.msc then + ninja.emit_flags('CFLAGS', all_cflags) + local cc_command = cc .. ' $CFLAGS /nologo /showIncludes -c /Tc$in /Fo$out' + ninja.emit_rule('cc', cc_command, 'cc $out', { deps = 'msvc' }) + + ninja.emit_flags('CXXFLAGS', all_cxxflags) + local cxx_command = cxx .. ' $CXXFLAGS /nologo /showIncludes -c /Tp$in /Fo$out' + ninja.emit_rule('cxx', cxx_command, 'cxx $out', { deps = 'msvc' }) + + ninja.emit_flags('CFLAGS', all_cflags) + ninja.emit_rule('clangtidy_cc', build_command({ 'clang-tidy $in -- -x c $CFLAGS', cc_command }, ';'), 'cc $out', { deps = 'msvc' }, ';') + + ninja.emit_flags('CXXFLAGS', all_cxxflags) + ninja.emit_rule('clangtidy_cxx', build_command({ 'clang-tidy $in -- -x c++ $CFLAGS', cxx_command }, ';'), 'cxx $out', { deps = 'msvc' }, ';') + + ninja.emit_flags('RESFLAGS', all_resflags) + ninja.emit_rule('rc', rc .. ' /nologo /fo$out $in $RESFLAGS', 'rc $out') + + if cfg.kind == p.STATICLIB then + ninja.emit_rule('ar', ar .. ' @$out.rsp /nologo -OUT:$out', 'ar $out', { rspfile = '$out.rsp', rspfile_content = '$in_newline' }) + else + ninja.emit_rule('link', link .. ' @$out.rsp ' .. ninja.list(ninja.shesc(toolset.getlinks(cfg, true))) .. ' /link ' .. all_ldflags .. ' /nologo /out:$out', 'link $out', { rspfile = '$out.rsp', rspfile_content = '$in_newline' }) + end + elseif toolset == p.tools.clang or toolset == p.tools.gcc or toolset == p.tools.emcc then + local force_include = pch and (' -include ' .. ninja.shesc(pch.placeholder)) or '' + + if pch then + ninja.emit_rule('build_pch', iif(cfg.language == 'C', cc .. all_cflags .. ' -x c-header', cxx .. all_cxxflags .. ' -x c++-header') .. ' -H -MF $out.d -c -o $out $in', 'build_pch $out', { depfile = '$out.d', deps = 'gcc' }) + end + + ninja.emit_flags('CFLAGS', all_cflags) + local cc_command = cc .. ' $CFLAGS' .. force_include .. ' -x c -MF $out.d -c -o $out $in' + ninja.emit_rule('cc', cc_command, 'cc $out', { depfile = '$out.d', deps = 'gcc' }) + + ninja.emit_flags('CXXFLAGS', all_cxxflags) + local cxx_command = cxx .. ' $CXXFLAGS' .. force_include .. ' -x c++ -MF $out.d -c -o $out $in' + ninja.emit_rule('cxx', cxx_command, 'cxx $out', { depfile = '$out.d', deps = 'gcc' }) + + ninja.emit_flags('CFLAGS', all_cflags) + ninja.emit_rule('clangtidy_cc', build_command({ 'clang-tidy $in -- -x c $CFLAGS' .. force_include, cc_command }, ';'), 'cc $out', { depfile = '$out.d', deps = 'gcc' }) + + ninja.emit_flags('CXXFLAGS', all_cxxflags) + ninja.emit_rule('clangtidy_cxx', build_command({ 'clang-tidy $in -- -x c++ $CFLAGS' .. force_include, cxx_command }, ';'), 'cxx $out', { depfile = '$out.d', deps = 'gcc' }) + + ninja.emit_flags('RESFLAGS', all_resflags) + if rc then + ninja.emit_rule('rc', rc .. ' -i $in -o $out $RESFLAGS', 'rc $out') + end + + if ar and cfg.kind == p.STATICLIB then + if os.target() == 'macosx' then -- doesn't support response file + ninja.emit_rule('ar', ar .. ' rcs $out $in', 'ar $out') + else + ninja.emit_rule('ar', ar .. ' rcs $out @$out.rsp', 'ar $out', { rspfile = '$out.rsp', rspfile_content = '$in_newline' }) + end + else + local groups = iif(cfg.linkgroups == premake.ON, { '-Wl,--start-group ', ' -Wl,--end-group' }, { '', '' }) + ninja.emit_rule('link', link .. ' -o $out ' .. groups[1] .. '@$out.rsp' .. ninja.list(ninja.shesc(toolset.getlinks(cfg, true, true))) .. all_ldflags .. groups[2], 'link $out', { rspfile = '$out.rsp', rspfile_content = '$in_newline' }) + end + end + + p.tools.getrelative = getrelative +end + +local function custom_command_rule() + ninja.emit_rule('custom_command', '$CUSTOM_COMMAND', '$CUSTOM_DESCRIPTION') +end + +local function copy_rule() + ninja.emit_rule('copy', os.translateCommands('{COPYFILE} $in $out'), 'copy $in $out') +end + +local function collect_generated_files(prj, cfg) + local generated_files = {} + tree.traverse(project.getsourcetree(prj), { + onleaf = function(node, depth) + function append_to_generated_files(filecfg) + local outputs = project.getrelative(prj.workspace, filecfg.buildoutputs) + generated_files = table.join(generated_files, outputs) + end + local filecfg = fileconfig.getconfig(node, cfg) + if not filecfg or filecfg.excludefrombuild then + return + end + local rule = p.global.getRuleForFile(node.name, prj.rules) + if fileconfig.hasCustomBuildRule(filecfg) then + append_to_generated_files(filecfg) + elseif rule then + local environ = table.shallowcopy(filecfg.environ) + + if rule.propertydefinition then + p.rule.prepareEnvironment(rule, environ, cfg) + p.rule.prepareEnvironment(rule, environ, filecfg) + end + local rulecfg = p.context.extent(rule, environ) + append_to_generated_files(rulecfg) + end + end, + }, false, 1) + return generated_files +end + +local function pch_build(cfg, pch) + local pch_dependency = {} + if pch then + pch_dependency = { pch.gch } + ninja.add_build(cfg, pch.gch, {}, 'build_pch', { pch.input }, {}, {}, {}) + end + return pch_dependency +end + +local function custom_command_build(prj, cfg, filecfg, filename, file_dependencies) + local outputs = project.getrelative(prj.workspace, filecfg.buildoutputs) + local output = outputs[1] + table.remove(outputs, 1) + local commands = {} + if filecfg.buildmessage then + commands = { os.translateCommandsAndPaths('{ECHO} ' .. filecfg.buildmessage, prj.workspace.basedir, prj.workspace.location) } + end + commands = table.join(commands, os.translateCommandsAndPaths(filecfg.buildcommands, prj.workspace.basedir, prj.workspace.location)) + if #commands > 1 then + commands = 'sh -c ' .. ninja.quote(table.implode(commands, '', '', ';')) + else + commands = commands[1] + end + + ninja.add_build(cfg, output, outputs, 'custom_command', { filename }, project.getrelative(prj.workspace, filecfg.buildinputs), file_dependencies, { 'CUSTOM_COMMAND = ' .. commands, 'CUSTOM_DESCRIPTION = custom build ' .. ninja.shesc(output) }) +end + +local function compile_file_build(cfg, filecfg, toolset, pch_dependency, regular_file_dependencies, objfiles, extrafiles) + local obj_file = filecfg.objname .. (toolset.objectextension or '.o') + local obj_dir = project.getrelative(cfg.workspace, cfg.objdir) + local filepath = project.getrelative(cfg.workspace, filecfg.abspath) + local has_custom_settings = fileconfig.hasFileSettings(filecfg) + local use_clangtidy = filecfg.clangtidy or (filecfg.clangtidy == nil and cfg.clangtidy) + + if use_clangtidy and toolset == p.tools.msc then + premake.warnOnce('clang-tidy_msc', 'Turn off clang-tidy when using msc (flags might differ too much between the tools).') + use_clangtidy = false + end + + if filecfg.buildaction == 'None' then + return + elseif filecfg.buildaction == 'Copy' then + local target = project.getrelative(cfg.workspace, path.join(cfg.targetdir, filecfg.name)) + ninja.add_build(cfg, target, {}, 'copy', { filepath }, {}, {}, {}) + extrafiles[#extrafiles + 1] = target + elseif shouldcompileasc(filecfg) then + local objfilename = obj_dir .. '/' .. obj_file + objfiles[#objfiles + 1] = objfilename + local vars = {} + if has_custom_settings then + vars = { 'CFLAGS = $CFLAGS ' .. getcflags(toolset, cfg, filecfg) } + end + ninja.add_build(cfg, objfilename, {}, iif(use_clangtidy, 'clangtidy_cc', 'cc'), { filepath }, pch_dependency, regular_file_dependencies, vars) + elseif shouldcompileascpp(filecfg) then + local objfilename = obj_dir .. '/' .. obj_file + objfiles[#objfiles + 1] = objfilename + local vars = {} + if has_custom_settings then + vars = { 'CXXFLAGS = $CXXFLAGS ' .. getcxxflags(toolset, cfg, filecfg) } + end + ninja.add_build(cfg, objfilename, {}, iif(use_clangtidy, 'clangtidy_cxx', 'cxx'), { filepath }, pch_dependency, regular_file_dependencies, vars) + elseif path.isresourcefile(filecfg.abspath) then + local objfilename = obj_dir .. '/' .. filecfg.basename .. '.res' + objfiles[#objfiles + 1] = objfilename + local resflags = {} + if has_custom_settings then + resflags = { 'RESFLAGS = $RESFLAGS ' .. getresflags(toolset, cfg, filecfg) } + end + local rc = toolset.gettoolname(cfg, 'rc') + if rc then + ninja.add_build(cfg, objfilename, {}, 'rc', { filepath }, {}, {}, resflags) + else + p.warnOnce(filepath, string.format('Ignored resource: "%s"', filepath)) + end + end +end + +local function files_build(prj, cfg, toolset, pch_dependency, regular_file_dependencies, file_dependencies) + local objfiles = {} + local extrafiles = {} + tree.traverse(project.getsourcetree(prj), { + onleaf = function(node, depth) + local filecfg = fileconfig.getconfig(node, cfg) + if not filecfg or filecfg.excludefrombuild then + return + end + local rule = p.global.getRuleForFile(node.name, prj.rules) + local filepath = project.getrelative(cfg.workspace, node.abspath) + + if fileconfig.hasCustomBuildRule(filecfg) then + custom_command_build(prj, cfg, filecfg, filepath, file_dependencies) + elseif rule then + local environ = table.shallowcopy(filecfg.environ) + + if rule.propertydefinition then + p.rule.prepareEnvironment(rule, environ, cfg) + p.rule.prepareEnvironment(rule, environ, filecfg) + end + local rulecfg = p.context.extent(rule, environ) + custom_command_build(prj, cfg, rulecfg, filepath, file_dependencies) + else + compile_file_build(cfg, filecfg, toolset, pch_dependency, regular_file_dependencies, objfiles, extrafiles) + end + end, + }, false, 1) + p.outln('') + + return objfiles, extrafiles +end + +local function generated_files_build(cfg, generated_files, key) + local final_dependency = {} + if #generated_files > 0 then + p.outln('# generated files') + ninja.add_build(cfg, 'generated_files_' .. key, {}, 'phony', generated_files, {}, {}, {}) + final_dependency = { 'generated_files_' .. key } + end + return final_dependency +end + +-- generate project + config build file +function ninja.generateProjectCfg(cfg) + local oldGetDefaultSeparator = path.getDefaultSeparator + path.getDefaultSeparator = function() + return '/' + end + + local prj = cfg.project + local key = get_key(cfg) + local toolset, toolset_version = p.tools.canonical(cfg.toolset) + + if not toolset then + p.error('Unknown toolset ' .. cfg.toolset) + end + + -- Some toolset fixes + cfg.gccprefix = cfg.gccprefix or '' + + p.outln('# project build file') + p.outln('# generated with premake ninja') + p.outln('') + + -- premake-ninja relies on scoped rules + -- and they were added in ninja v1.6 + p.outln('ninja_required_version = 1.6') + p.outln('') + + local is_c_or_cpp = cfg.language == p.C or cfg.language == p.CPP + + ---------------------------------------------------- figure out settings + local pch = nil + if is_c_or_cpp and toolset ~= p.tools.msc then + pch = p.tools.gcc.getpch(cfg) + if pch then + pch = { + input = pch, + placeholder = project.getrelative(cfg.workspace, path.join(cfg.objdir, path.getname(pch))), + gch = project.getrelative(cfg.workspace, path.join(cfg.objdir, path.getname(pch) .. '.gch')), + } + end + end + + ---------------------------------------------------- write rules + p.outln('# core rules for ' .. cfg.name) + prebuild_rule(cfg) + prelink_rule(cfg) + postbuild_rule(cfg) + + if is_c_or_cpp then + c_cpp_compilation_rules(cfg, toolset, pch) + else + local handler = ninja.handlers[cfg.language] + if not handler then + p.error('expected registered ninja handler action for target ' .. cfg.language) + end + handler.compilation_rules(cfg, toolset) + end + + copy_rule() + custom_command_rule() + + ---------------------------------------------------- build all files + p.outln('# build files') + + local pch_dependency = is_c_or_cpp and pch_build(cfg, pch) or {} + + local generated_files = collect_generated_files(prj, cfg) + + local file_dependencies = getFileDependencies(cfg) + local regular_file_dependencies = table.join(iif(#generated_files > 0, { 'generated_files_' .. key }, {}), file_dependencies) + + local obj_dir = project.getrelative(cfg.workspace, cfg.objdir) + local objfiles, extrafiles = files_build(prj, cfg, toolset, pch_dependency, regular_file_dependencies, file_dependencies) + local final_dependency = generated_files_build(cfg, generated_files, key) + + ---------------------------------------------------- build final target + if #cfg.prebuildcommands > 0 or cfg.prebuildmessage then + p.outln('# prebuild') + ninja.add_build(cfg, 'prebuild_' .. get_key(cfg), {}, 'run_prebuild', {}, {}, {}, {}) + end + local prelink_dependency = {} + if #cfg.prelinkcommands > 0 or cfg.prelinkmessage then + p.outln('# prelink') + ninja.add_build(cfg, 'prelink_' .. get_key(cfg), {}, 'run_prelink', {}, objfiles, final_dependency, {}) + prelink_dependency = { 'prelink_' .. get_key(cfg) } + end + if #cfg.postbuildcommands > 0 or cfg.postbuildmessage then + p.outln('# postbuild') + ninja.add_build(cfg, 'postbuild_' .. get_key(cfg), {}, 'run_postbuild', {}, { ninja.outputFilename(cfg) }, {}, {}) + end + + if is_c_or_cpp then + -- we don't pass getlinks(cfg) through dependencies + -- because system libraries are often not in PATH so ninja can't find them + local libs = table.translate(config.getlinks(cfg, 'siblings', 'fullpath'), function(p) + return project.getrelative(cfg.workspace, path.join(cfg.project.location, p)) + end) + local cfg_output = ninja.outputFilename(cfg) + local extra_outputs = {} + local command_rule = '' + if cfg.kind == p.STATICLIB then + p.outln('# link static lib') + command_rule = 'ar' + elseif cfg.kind == p.SHAREDLIB then + p.outln('# link shared lib') + command_rule = 'link' + extra_outputs = iif(os.target() == 'windows', { path.replaceextension(cfg_output, '.lib'), path.replaceextension(cfg_output, '.exp') }, {}) + elseif (cfg.kind == p.CONSOLEAPP) or (cfg.kind == p.WINDOWEDAPP) then + p.outln('# link executable') + command_rule = 'link' + else + p.error("ninja action doesn't support this kind of target " .. cfg.kind) + end + + local deps = table.join(final_dependency, extrafiles, prelink_dependency) + ninja.add_build(cfg, cfg_output, extra_outputs, command_rule, table.join(objfiles, libs), {}, deps, {}) + outputs = { cfg_output } + else + local handler = ninja.handlers[cfg.language] + if not handler then + p.error('expected registered ninja handler action for target ' .. cfg.language) + end + outputs = handler.target_rules(cfg, toolset) + end + + p.outln('') + if #cfg.postbuildcommands > 0 or cfg.postbuildmessage then + ninja.add_build(cfg, key, {}, 'phony', { 'postbuild_' .. get_key(cfg) }, {}, {}, {}) + else + ninja.add_build(cfg, key, {}, 'phony', outputs, {}, {}, {}) + end + p.outln('') + + path.getDefaultSeparator = oldGetDefaultSeparator +end + +-- return name of output binary relative to build folder +function ninja.outputFilename(cfg) + return project.getrelative(cfg.workspace, cfg.buildtarget.directory) .. '/' .. cfg.buildtarget.name +end + +-- return name of build file for configuration +function ninja.projectCfgFilename(cfg, relative) + if relative ~= nil then + relative = project.getrelative(cfg.workspace, cfg.location) .. '/' + else + relative = '' + end + return relative .. get_key(cfg, cfg.project.filename) .. '.ninja' +end + +-- generate all build files for every project configuration +function ninja.generateProject(prj) + if not ninja.can_generate(prj) then + return + end + for cfg in project.eachconfig(prj) do + p.generate(cfg, ninja.projectCfgFilename(cfg), ninja.generateProjectCfg) + end +end + +include('_preload.lua') + +return ninja diff --git a/files/.premake/premake-system.lua b/files/.premake/premake-system.lua new file mode 100644 index 0000000..59754b4 --- /dev/null +++ b/files/.premake/premake-system.lua @@ -0,0 +1 @@ +require "ninja/ninja" \ No newline at end of file diff --git a/files/.zshrc b/files/.zshrc index f6ad1b8..ca41f04 100644 --- a/files/.zshrc +++ b/files/.zshrc @@ -33,3 +33,5 @@ mktags() { ctags `lr -t 'name=~".c$"'` } printf '%s +%s+ %s\n' \ "$(date +%d%b%Y | tr [:upper:] [:lower:])" "$(hostname)" \ "$((cat /sys/class/power_supply/BAT0/capacity 2>/dev/null && echo %) | tr -d '\n')" + +test -d ~/Downloads && rmdir ~/Downloads