mirror of
https://github.com/daylinmorgan/forge.git
synced 2024-12-24 19:40:44 -06:00
chore: ccnz -> forge
This commit is contained in:
parent
9dc6353e8b
commit
4485f832f0
13 changed files with 447 additions and 174 deletions
13
.forge.cfg
Normal file
13
.forge.cfg
Normal file
|
@ -0,0 +1,13 @@
|
|||
# example ccnz config file
|
||||
nimble
|
||||
|
||||
[target]
|
||||
x86_64-linux-gnu
|
||||
x86_64-linux-musl
|
||||
x86_64-macos-none
|
||||
x86_64-windows-gnu
|
||||
|
||||
[bin]
|
||||
src/forge
|
||||
src/forgecc
|
||||
|
5
.github/workflows/nightly.yml
vendored
5
.github/workflows/nightly.yml
vendored
|
@ -24,8 +24,9 @@ jobs:
|
|||
name: check latest commit is less than a day
|
||||
if: ${{ github.event_name == 'schedule' }}
|
||||
run: |
|
||||
test -n "$(git rev-list --since="24 hours" HEAD)" \
|
||||
&& echo "quit=true" >> "$GITHUB_OUTPUT"
|
||||
if [[ -n "$(git rev-list --since='24 hours' HEAD)" ]]; then
|
||||
echo "quit=true" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
|
||||
build-artifacts:
|
||||
needs: check-commits
|
||||
|
|
21
LICENSE
Normal file
21
LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2023 Daylin Morgan
|
||||
|
||||
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.
|
|
@ -1,3 +1,10 @@
|
|||
# ccnz compiles nim w/zig
|
||||
# forge
|
||||
|
||||
A toolchain to forge your multi-platform `nim` binaries.
|
||||
|
||||
## install
|
||||
|
||||
```sh
|
||||
nimble install https://github.com/daylinmorgan/forge
|
||||
```
|
||||
|
||||
|
|
46
ccnz.nimble
46
ccnz.nimble
|
@ -1,46 +0,0 @@
|
|||
version = "2023.1001"
|
||||
author = "Daylin Morgan"
|
||||
description = "ccnz compiles nim w/zig"
|
||||
license = "MIT"
|
||||
srcDir = "src"
|
||||
bin = @["ccnz", "ccnzcc"]
|
||||
binDir = "bin"
|
||||
|
||||
|
||||
requires "nim >= 2.0.0",
|
||||
"cligen"
|
||||
|
||||
|
||||
|
||||
import strformat
|
||||
const targets = [
|
||||
"x86_64-linux-gnu",
|
||||
"x86_64-linux-musl",
|
||||
"x86_64-macos-none",
|
||||
"x86_64-windows-gnu"
|
||||
]
|
||||
|
||||
task release, "build release assets":
|
||||
mkdir "dist"
|
||||
for target in targets:
|
||||
let ext = if target == "x86_64-windows-gnu": ".cmd" else: ""
|
||||
for app in @["ccnz", "ccnzcc"]:
|
||||
let outdir = &"dist/{target}/"
|
||||
exec &"ccnz cc --target {target} --nimble -- --out:{outdir}{app}{ext} -d:release src/{app}"
|
||||
|
||||
task bundle, "package build assets":
|
||||
cd "dist"
|
||||
for target in targets:
|
||||
let
|
||||
app = projectName()
|
||||
cmd =
|
||||
if target == "x86_64-windows-gnu":
|
||||
&"7z a {app}_{target}.zip {target}"
|
||||
else:
|
||||
&"tar czf {app}_{target}.tar.gz {target}"
|
||||
|
||||
cpFile("../README.md", &"{target}/README.md")
|
||||
exec cmd
|
||||
|
||||
|
||||
|
30
forge.nimble
Normal file
30
forge.nimble
Normal file
|
@ -0,0 +1,30 @@
|
|||
version = "2023.1001"
|
||||
author = "Daylin Morgan"
|
||||
description = "build nim binaries for all the platforms"
|
||||
license = "MIT"
|
||||
srcDir = "src"
|
||||
bin = @["forge", "forgecc"]
|
||||
binDir = "bin"
|
||||
|
||||
|
||||
requires "nim >= 2.0.0",
|
||||
"cligen"
|
||||
|
||||
import strformat
|
||||
|
||||
task release, "build release assets":
|
||||
version = (gorgeEx "git describe --tags --always").output
|
||||
exec &"forge release -v {version} -V"
|
||||
|
||||
task bundle, "package build assets":
|
||||
withDir "dist":
|
||||
for dir in listDirs("."):
|
||||
let cmd = if "windows" in dir:
|
||||
&"7z a {dir}.zip {dir}"
|
||||
else:
|
||||
&"tar czf {dir}.tar.gz {dir}"
|
||||
cpFile("../README.md", &"{dir}/README.md")
|
||||
exec cmd
|
||||
|
||||
|
||||
|
72
src/ccnz.nim
72
src/ccnz.nim
|
@ -1,72 +0,0 @@
|
|||
import std/[osproc, strformat, strutils, tables, terminal]
|
||||
import ccnz/utils
|
||||
|
||||
proc genFlags(target: string, args: seq[string]): seq[string] =
|
||||
let targetList = zigTargets()
|
||||
if target notin targetList:
|
||||
errQuit &"unknown target: {target}", "", "must be one of:",
|
||||
targetList.columns
|
||||
|
||||
addFlag "cpu"
|
||||
addFlag "os"
|
||||
|
||||
result &= @[
|
||||
"--cc:clang",
|
||||
&"--clang.exe='ccnzcc'",
|
||||
&"--clang.linkerexe='ccnzcc'",
|
||||
# &"--passC:\"-target {target} -fno-sanitize=undefined\"",
|
||||
&"--passC:'-target {target}'",
|
||||
# &"--passL:\"-target {target} -fno-sanitize=undefined\"",
|
||||
&"--passL:'-target {target}'",
|
||||
]
|
||||
|
||||
proc targets() =
|
||||
## show available targets
|
||||
let targetList = zigTargets()
|
||||
styledEcho styleBright, fgGreen, "available targets:"
|
||||
echo targetList.columns
|
||||
|
||||
proc cc(target: string, dryrun: bool = false, nimble: bool = false, args: seq[string]) =
|
||||
## compile with zig cc
|
||||
let ccArgs = genFlags(target, args)
|
||||
if args.len == 0:
|
||||
errQuit "expected additional arguments i.e. -- -d:release src/main.nim\n"
|
||||
|
||||
let rest =
|
||||
if args[0] == "c":
|
||||
args[1..^1]
|
||||
else:
|
||||
args
|
||||
|
||||
let baseCmd = if nimble: "nimble" else: "nim"
|
||||
let cmd = (@[baseCmd] & @["c"] & ccArgs & rest).join(" ")
|
||||
if dryrun:
|
||||
stderr.write cmd, "\n"
|
||||
else:
|
||||
quit(execCmd cmd)
|
||||
|
||||
when isMainModule:
|
||||
import cligen
|
||||
zigExists()
|
||||
|
||||
const
|
||||
customMulti = "${doc}Usage:\n $command {SUBCMD} [sub-command options & parameters]\n\nsubcommands:\n$subcmds"
|
||||
vsn = staticExec "git describe --tags --always HEAD"
|
||||
|
||||
|
||||
if clCfg.useMulti == "": clCfg.useMulti = customMulti
|
||||
if clCfg.helpAttr.len == 0:
|
||||
clCfg.helpAttr = {"cmd": "\e[1;36m", "clDescrip": "", "clDflVal": "\e[33m",
|
||||
"clOptKeys": "\e[32m", "clValType": "\e[31m", "args": "\e[3m"}.toTable
|
||||
clCfg.helpAttrOff = {"cmd": "\e[m", "clDescrip": "\e[m", "clDflVal": "\e[m",
|
||||
"clOptKeys": "\e[m", "clValType": "\e[m", "args": "\e[m"}.toTable
|
||||
|
||||
var vsnCfg = clCfg
|
||||
vsnCfg.version = vsn
|
||||
|
||||
|
||||
dispatchMulti(["multi", cf = vsnCfg], [cc, help = {
|
||||
"dryrun": "show command instead of executing",
|
||||
"nimble": "use nimble as base command for compiling"
|
||||
}, short = {"dryrun": 'n'}],
|
||||
[targets])
|
|
@ -1,3 +0,0 @@
|
|||
import ccnz/utils
|
||||
|
||||
callZig("cc")
|
155
src/forge.nim
Normal file
155
src/forge.nim
Normal file
|
@ -0,0 +1,155 @@
|
|||
import std/[os, osproc, strformat, strutils, tables, terminal]
|
||||
|
||||
import forge/[config, utils, term]
|
||||
|
||||
proc genFlags(triplet: Triplet, args: seq[string] = @[]): seq[string] =
|
||||
addFlag "cpu"
|
||||
addFlag "os"
|
||||
|
||||
result &= @[
|
||||
"--cc:clang",
|
||||
&"--clang.exe='forgecc'",
|
||||
&"--clang.linkerexe='forgecc'",
|
||||
# &"--passC:\"-target {target} -fno-sanitize=undefined\"",
|
||||
&"--passC:'-target {triplet}'",
|
||||
# &"--passL:\"-target {target} -fno-sanitize=undefined\"",
|
||||
&"--passL:'-target {triplet}'",
|
||||
]
|
||||
|
||||
proc targets() =
|
||||
## show available targets
|
||||
let targetList = zigTargets()
|
||||
termEcho styleBright, fgGreen, "available targets:"
|
||||
stderr.writeLine targetList.columns
|
||||
|
||||
proc cc(target: string, dryrun: bool = false, nimble: bool = false, args: seq[string]) =
|
||||
## compile with zig cc
|
||||
if args.len == 0:
|
||||
termErrQuit "expected additional arguments i.e. -- -d:release src/main.nim"
|
||||
|
||||
let
|
||||
targets = zigTargets()
|
||||
ccArgs = genFlags(parseTriplet(target, targets), args)
|
||||
rest = parseArgs(args)
|
||||
baseCmd = if nimble: "nimble" else: "nim"
|
||||
cmd = (@[baseCmd] & @["c"] & ccArgs & rest).join(" ")
|
||||
|
||||
if dryrun:
|
||||
stderr.writeLine cmd
|
||||
else:
|
||||
quit(execCmd cmd)
|
||||
|
||||
proc release(
|
||||
target: seq[string] = @[],
|
||||
bin: seq[string] = @[],
|
||||
args: seq[string],
|
||||
outdir: string = "dist",
|
||||
format: string = "",
|
||||
name: string = "",
|
||||
version: string = "",
|
||||
dryrun: bool = false,
|
||||
nimble: bool = false,
|
||||
configFile: string = ".forge.cfg",
|
||||
verbose: bool = false,
|
||||
) =
|
||||
## generate release assets for n>=1 targets
|
||||
##
|
||||
## format argument:
|
||||
## format is a template string used for each target directory
|
||||
## available fields are name, version, target
|
||||
## default: ${name}-v${verison}-${target}
|
||||
##
|
||||
## if name or version are not specified they will be inferred from the local .nimble file
|
||||
|
||||
var cfg = newConfig(
|
||||
target,
|
||||
bin,
|
||||
outdir,
|
||||
format,
|
||||
name,
|
||||
version,
|
||||
nimble,
|
||||
configFile
|
||||
)
|
||||
if cfg.targets.len == 0:
|
||||
termErrQuit "expected at least 1 target"
|
||||
if cfg.bins.len == 0:
|
||||
termErrQuit "expected at least 1 bin"
|
||||
|
||||
if verbose:
|
||||
termEcho $cfg
|
||||
|
||||
if dryrun:
|
||||
termEcho styleBright, fgBlue, "dry run...see below for commands"
|
||||
|
||||
let
|
||||
targets = zigTargets()
|
||||
baseCmd = if nimble or cfg.nimble: "nimble" else: "nim"
|
||||
rest = parseArgs(args)
|
||||
|
||||
termEcho styleBright, fgYellow,
|
||||
&"compiling {cfg.bins.len} binaries for {cfg.targets.len} targets"
|
||||
|
||||
for t, tArgs in cfg.targets:
|
||||
for b, bArgs in cfg.bins:
|
||||
var cmdParts: seq[string] = @[]
|
||||
let outFlag = &"--outdir:'" & (
|
||||
outdir / formatDirName(cfg.format, cfg.name, cfg.version, t)
|
||||
) & "'"
|
||||
|
||||
cmdParts &= @[baseCmd, "c"]
|
||||
cmdParts.add genFlags(parseTriplet(t, targets), rest)
|
||||
cmdParts.add "-d:release"
|
||||
cmdParts.add rest
|
||||
cmdParts.add outFlag
|
||||
for a in @[targs, bargs]:
|
||||
if a != "": cmdParts.add a
|
||||
cmdParts.add b
|
||||
|
||||
let cmd = cmdParts.join(" ")
|
||||
if dryrun:
|
||||
stderr.writeLine cmd
|
||||
else:
|
||||
if verbose:
|
||||
termEcho styleBright, "cmd: ", ansiResetCode, cmd
|
||||
let errCode = execCmd cmd
|
||||
if errCode != 0:
|
||||
termErrQuit "problems executing cmd " & cmd
|
||||
|
||||
when isMainModule:
|
||||
import cligen
|
||||
zigExists()
|
||||
|
||||
const
|
||||
customMulti = "${doc}Usage:\n $command {SUBCMD} [sub-command options & parameters]\n\nsubcommands:\n$subcmds"
|
||||
vsn = staticExec "git describe --tags --always HEAD"
|
||||
|
||||
|
||||
if clCfg.useMulti == "": clCfg.useMulti = customMulti
|
||||
if clCfg.helpAttr.len == 0:
|
||||
clCfg.helpAttr = {"cmd": "\e[1;36m", "clDescrip": "", "clDflVal": "\e[33m",
|
||||
"clOptKeys": "\e[32m", "clValType": "\e[31m", "args": "\e[3m"}.toTable
|
||||
clCfg.helpAttrOff = {"cmd": "\e[m", "clDescrip": "\e[m", "clDflVal": "\e[m",
|
||||
"clOptKeys": "\e[m", "clValType": "\e[m", "args": "\e[m"}.toTable
|
||||
|
||||
var vsnCfg = clCfg
|
||||
vsnCfg.version = vsn
|
||||
|
||||
|
||||
dispatchMulti(["multi", cf = vsnCfg], [cc, help = {
|
||||
"dryrun": "show command instead of executing",
|
||||
"nimble": "use nimble as base command for compiling"
|
||||
}],
|
||||
[targets],
|
||||
[release,
|
||||
help = {
|
||||
"target": "set target, may be repeated",
|
||||
"bin": "set bin, may be repeated",
|
||||
"dryrun": "show command instead of executing",
|
||||
"format": "set format, see help above",
|
||||
"nimble": "use nimble as base command for compiling",
|
||||
"config-file": "path to config"
|
||||
},
|
||||
short = {"verbose": 'V'}
|
||||
]
|
||||
)
|
128
src/forge/config.nim
Normal file
128
src/forge/config.nim
Normal file
|
@ -0,0 +1,128 @@
|
|||
import std/[parsecfg, tables, os, strutils, strformat]
|
||||
|
||||
type
|
||||
Config* = object
|
||||
targets*: OrderedTableRef[string, string]
|
||||
bins*: OrderedTableRef[string, string]
|
||||
outdir*: string
|
||||
format*: string
|
||||
name*: string
|
||||
version*: string
|
||||
nimble*: bool
|
||||
|
||||
proc `$`*(c: Config): string =
|
||||
var lines: seq[string] = @[]
|
||||
lines.add "config ="
|
||||
lines.add "| nimble " & $c.nimble
|
||||
lines.add "| outdir " & c.outdir
|
||||
lines.add "| format " & c.format
|
||||
lines.add "| version " & c.version
|
||||
lines.add "| targets:"
|
||||
for target, args in c.targets:
|
||||
lines.add "| " & target & (if args != "": "|" & args else: "")
|
||||
lines.add "| bins:"
|
||||
for bin, args in c.bins:
|
||||
lines.add "| " & bin & (if args != "": "|" & args else: "")
|
||||
|
||||
lines.join("\n")
|
||||
|
||||
proc loadConfigFile*(f: string): Config =
|
||||
let
|
||||
dict = loadConfig(f)
|
||||
base = dict.getOrDefault("")
|
||||
|
||||
result.targets = newOrderedTable[string, string]()
|
||||
result.bins = newOrderedTable[string, string]()
|
||||
|
||||
result.nimble = base.hasKey("nimble")
|
||||
result.outdir = base.getOrDefault("outdir")
|
||||
result.name = base.getOrDefault("name")
|
||||
result.version = base.getOrDefault("version")
|
||||
result.format = base.getOrDefault("format")
|
||||
if dict.hasKey("target"):
|
||||
result.targets = dict.getOrDefault("target")
|
||||
if dict.hasKey("bin"):
|
||||
result.bins = dict.getOrDefault("bin")
|
||||
|
||||
proc inferName(s: string, nimbleFile: string): string =
|
||||
if s != "":
|
||||
return s
|
||||
elif nimbleFile != "":
|
||||
return nimbleFile.rsplit(".", maxsplit = 1)[0]
|
||||
|
||||
proc findNimbleFile(): string =
|
||||
var candidates: seq[string]
|
||||
for kind, path in walkDir(getCurrentDir(), relative = true):
|
||||
case kind:
|
||||
of pcFile, pcLinkToFile:
|
||||
if path.endsWith(".nimble"):
|
||||
candidates.add path
|
||||
else: discard
|
||||
|
||||
# nimble will probably prevent this,
|
||||
# but not sure about atlas or bespoke builds
|
||||
if candidates.len > 1:
|
||||
echo "found multiple nimble files: " & candidates.join(", ")
|
||||
echo "cannot infer name or version"
|
||||
elif candidates.len == 1:
|
||||
return candidates[0]
|
||||
|
||||
proc inferVersion(s: string, nimbleFile: string): string =
|
||||
if s != "": return s
|
||||
|
||||
# TODO: catch io errors?
|
||||
let nimbleCfg = loadConfig(nimbleFile)
|
||||
return nimbleCfg.getSectionValue("", "version")
|
||||
|
||||
proc inferBin(nimbleFile: string): string =
|
||||
let
|
||||
pkgName = nimbleFile.split(".")[0]
|
||||
default = "src" / &"{pkgName}.nim"
|
||||
backup = &"{pkgName}.nim"
|
||||
|
||||
if default.fileExists(): return default
|
||||
if backup.fileExists(): return backup
|
||||
|
||||
|
||||
proc newConfig*(
|
||||
targets: seq[string],
|
||||
bins: seq[string],
|
||||
outdir: string,
|
||||
format: string,
|
||||
name: string,
|
||||
version: string,
|
||||
nimble: bool,
|
||||
configFile: string
|
||||
): Config =
|
||||
|
||||
let nimbleFile = findNimbleFile()
|
||||
|
||||
if configFile.fileExists:
|
||||
result = loadConfigFile(configFile)
|
||||
else:
|
||||
# no seg faults here...
|
||||
result.targets = newOrderedTable[string, string]()
|
||||
result.bins = newOrderedTable[string, string]()
|
||||
|
||||
result.nimble = result.nimble or nimble
|
||||
|
||||
if result.outdir == "" or (result.outdir != "dist" and outdir != "dist"):
|
||||
result.outdir = outdir
|
||||
|
||||
if result.name == "":
|
||||
result.name = inferName(name, nimbleFile)
|
||||
if result.version == "":
|
||||
result.version = inferVersion(version, nimbleFile)
|
||||
if result.format == "":
|
||||
if format != "": result.format = format
|
||||
else: result.format = "${name}-v${version}-${target}"
|
||||
|
||||
for t in targets:
|
||||
result.targets[t] = ""
|
||||
for b in bins:
|
||||
result.bins[b] = ""
|
||||
|
||||
if result.bins.len == 0 and nimbleFile != "":
|
||||
let bin = inferBin(nimbleFile)
|
||||
if bin != "":
|
||||
result.bins[bin] = ""
|
17
src/forge/term.nim
Normal file
17
src/forge/term.nim
Normal file
|
@ -0,0 +1,17 @@
|
|||
import std/terminal
|
||||
|
||||
# TODO support NO_COLOR for these
|
||||
let prefix = ansiForegroundColorCode(fgMagenta, bright = true) & "forge" &
|
||||
ansiResetCode & ansiForegroundColorCode(fgYellow) & " || " & ansiResetCode
|
||||
|
||||
template termEcho*(args: varargs[untyped]) =
|
||||
stderr.styledWriteLine(prefix, args)
|
||||
|
||||
template termErr*(args: varargs[untyped]) =
|
||||
stderr.styledWriteLine(prefix, fgRed, "error ", fgDefault, args)
|
||||
|
||||
template termErrQuit*(args: varargs[untyped]) =
|
||||
termErr(args)
|
||||
quit 1
|
||||
|
||||
|
|
@ -1,8 +1,25 @@
|
|||
import std/[json, macros, math, os, osproc, strutils, terminal, sequtils]
|
||||
import std/[json, macros, math, os, osproc, sequtils, strutils, strformat, terminal]
|
||||
|
||||
proc errQuit*(msg: varargs[string]) =
|
||||
stderr.write msg.join("\n") & "\n"
|
||||
quit 1
|
||||
import term
|
||||
|
||||
proc columns*(items: seq[string]): string =
|
||||
## return a list of items as equally spaced columns
|
||||
let
|
||||
maxWidth = max(items.mapIt(it.len))
|
||||
nColumns = floor((terminalWidth() + 1) / (maxWidth + 1)).int
|
||||
result = (
|
||||
items.mapIt(it.alignLeft(maxWidth + 1))
|
||||
).distribute(
|
||||
(items.len / nColumns).int + 1
|
||||
).mapIt(it.join("")).join("\n")
|
||||
|
||||
template parseArgs*(args: seq[string]): seq[string] =
|
||||
if args.len == 0:
|
||||
args
|
||||
elif args[0] == "c":
|
||||
args[1..^1]
|
||||
else:
|
||||
args
|
||||
|
||||
# based on https://github.com/enthus1ast/zigcc
|
||||
template callZig*(zigCmd: string) =
|
||||
|
@ -21,11 +38,33 @@ template callZig*(zigCmd: string) =
|
|||
close process
|
||||
quit exitCode
|
||||
|
||||
|
||||
type
|
||||
Triplet* = object
|
||||
cpu: string
|
||||
os: string
|
||||
libc: string
|
||||
|
||||
proc `$`*(t: Triplet): string = &"{t.cpu}-{t.os}-{t.libc}"
|
||||
|
||||
proc parseTriplet*(s: string, targets: seq[string]): Triplet =
|
||||
if s notin targets:
|
||||
termErr &"unknown target: {s}", "", "must be one of:"
|
||||
stderr.writeLine targets.columns
|
||||
quit 1
|
||||
|
||||
|
||||
let parts = s.split("-")
|
||||
result.cpu = parts[0]
|
||||
result.os = parts[1]
|
||||
result.libc = parts[2]
|
||||
|
||||
proc zigExists*() =
|
||||
if (findExe "zig") == "":
|
||||
errQuit "zig not found",
|
||||
"ccnz requires a working installation of zig",
|
||||
"see: https://ziglang.org/download/"
|
||||
termErr "zig not found"
|
||||
termErr " forge requires a working installation of zig"
|
||||
termErr " see: https://ziglang.org/download/"
|
||||
quit 1
|
||||
|
||||
proc zigTargets*(): seq[string] =
|
||||
let (output, _) = execCmdEx "zig targets"
|
||||
|
@ -34,7 +73,7 @@ proc zigTargets*(): seq[string] =
|
|||
macro addFlag*(arg: untyped): untyped =
|
||||
let
|
||||
flag = "--" & arg.strVal & ":"
|
||||
inferProc = newCall("infer" & arg.strVal, newIdentNode("target"))
|
||||
inferProc = newCall("infer" & arg.strVal, newIdentNode("triplet"))
|
||||
|
||||
quote do:
|
||||
if `flag` notin args:
|
||||
|
@ -43,30 +82,24 @@ macro addFlag*(arg: untyped): untyped =
|
|||
result.add `flag` & selected
|
||||
|
||||
|
||||
proc inferOs*(target: string): string =
|
||||
if "windows" in target:
|
||||
"Windows"
|
||||
elif "macos" in target:
|
||||
"MacOSX"
|
||||
elif "linux" in target:
|
||||
"Linux"
|
||||
elif "wasm" in target:
|
||||
"Linux"
|
||||
else:
|
||||
""
|
||||
proc inferOs*(t: Triplet): string =
|
||||
case t.os:
|
||||
of "windows", "linux": t.os.capitalizeAscii()
|
||||
of "macos": "MacOSX"
|
||||
of "wasm": "Linux"
|
||||
else: ""
|
||||
|
||||
proc inferCpu*(target: string): string =
|
||||
proc inferCpu*(t: Triplet): string =
|
||||
# Available options are:
|
||||
# i386, m68k, alpha, powerpc, powerpc64, powerpc64el, sparc,
|
||||
# vm, hppa, ia64, amd64, mips, mipsel, arm, arm64, js,
|
||||
# nimvm, avr, msp430, sparc64, mips64, mips64el, riscv32,
|
||||
# riscv64, esp, wasm32, e2k, loongarch64
|
||||
#
|
||||
let candidate = target.split("-")[0]
|
||||
|
||||
# NOTE: I don't know what the _be eb means but if nim
|
||||
# can't handle them then maybe an error would be better
|
||||
result =
|
||||
case candidate:
|
||||
case t.cpu:
|
||||
of "x86_64":
|
||||
"amd64"
|
||||
of "aarch64", "aarch64_be":
|
||||
|
@ -79,35 +112,21 @@ proc inferCpu*(target: string): string =
|
|||
"powerpc64le"
|
||||
# remain the same
|
||||
of "m68k", "mips64el", "mipsel", "mips", "powerpc", "powerpc64", "riscv64",
|
||||
"sparc", "sparc64", "wasm32":
|
||||
candidate
|
||||
"sparc", "sparc64", "wasm32": t.cpu
|
||||
else:
|
||||
""
|
||||
|
||||
# s390x-linux-gnu
|
||||
# s390x-linux-musl
|
||||
# sparc-linux-gnu
|
||||
# sparc64-linux-gnu
|
||||
# wasm32-freestanding-musl
|
||||
# wasm32-wasi-musl
|
||||
# x86_64-linux-gnu
|
||||
# x86_64-linux-gnux32
|
||||
# x86_64-linux-musl
|
||||
# x86_64-windows-gnu
|
||||
# x86_64-macos-none
|
||||
# x86_64-macos-none
|
||||
# x86_64-macos-none
|
||||
#
|
||||
proc columns*(items: seq[string]): string =
|
||||
## return a list of items as equally spaced columns
|
||||
let
|
||||
maxWidth = max(items.mapIt(it.len))
|
||||
nColumns = floor((terminalWidth() + 1) / (maxWidth + 1)).int
|
||||
result = (
|
||||
items.mapIt(it.alignLeft(maxWidth + 1))
|
||||
).distribute(
|
||||
(items.len / nColumns).int + 1
|
||||
).mapIt(it.join("")).join("\n")
|
||||
|
||||
proc formatDirName*(formatstr: string, name: string, version: string,
|
||||
target: string): string =
|
||||
var vsn = version
|
||||
if ("v$version" in formatstr or "v${version}" in formatstr) and
|
||||
vsn.startsWith("v"):
|
||||
vsn = vsn[1..^1]
|
||||
try:
|
||||
result = formatstr % ["name", name, "version", vsn, "target", target]
|
||||
except ValueError as e:
|
||||
termErrQuit e.msg
|
||||
|
||||
if result == "":
|
||||
termErrQuit &"error processing formatstr: {formatstr}"
|
||||
|
3
src/forgecc.nim
Normal file
3
src/forgecc.nim
Normal file
|
@ -0,0 +1,3 @@
|
|||
import forge/utils
|
||||
|
||||
callZig("cc")
|
Loading…
Reference in a new issue