mirror of
https://github.com/daylinmorgan/forge.git
synced 2024-12-24 19:40:44 -06:00
chore: mvp
This commit is contained in:
parent
af54a4cfc4
commit
9dc6353e8b
10 changed files with 385 additions and 0 deletions
39
.github/workflows/build.yml
vendored
Normal file
39
.github/workflows/build.yml
vendored
Normal file
|
@ -0,0 +1,39 @@
|
|||
name: ⚙️ Build Binaries
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
|
||||
env:
|
||||
APP_NAME: ccnz
|
||||
NIM_VERSION: stable
|
||||
|
||||
jobs:
|
||||
build-artifact:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: jiro4989/setup-nim-action@v1
|
||||
with:
|
||||
nim-version: ${{ env.NIM_VERSION }}
|
||||
|
||||
# for cross compilation with ccnz
|
||||
- uses: goto-bus-stop/setup-zig@v2
|
||||
|
||||
- name: Bootstrap with installed version
|
||||
run: nimble install -Y
|
||||
|
||||
- name: Generate build artifacts
|
||||
run: nimble release
|
||||
|
||||
- name: Create artifact bundles
|
||||
run: nimble bundle
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: artifacts
|
||||
path: |
|
||||
dist/*.tar.gz
|
||||
dist/*.zip
|
||||
|
60
.github/workflows/nightly.yml
vendored
Normal file
60
.github/workflows/nightly.yml
vendored
Normal file
|
@ -0,0 +1,60 @@
|
|||
name: 🌙 Nightly Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '0 2 * * *'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
check-commits:
|
||||
runs-on: ubuntu-latest
|
||||
name: Check latest commit
|
||||
outputs:
|
||||
quit: ${{ steps.should_run.outputs.quit }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: print latest commit
|
||||
run: echo ${{ github.sha }}
|
||||
|
||||
- id: should_run
|
||||
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"
|
||||
|
||||
build-artifacts:
|
||||
needs: check-commits
|
||||
if: ${{ needs.check-commits.outputs.quit != 'true' }}
|
||||
uses: ./.github/workflows/build.yml
|
||||
|
||||
create-release:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
needs:
|
||||
- build-artifacts
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Download Build Artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
|
||||
- run: ls -R artifacts
|
||||
|
||||
- name: Remove Old Nightly Release
|
||||
run: |
|
||||
gh release delete nightly --yes || true
|
||||
git push origin :nightly || true
|
||||
|
||||
- name: Generate New Nightly Release
|
||||
run: |
|
||||
gh release create nightly \
|
||||
--title "Nightly Release (Pre-release)" \
|
||||
--prerelease \
|
||||
./artifacts/*
|
||||
|
31
.github/workflows/release.yml
vendored
Normal file
31
.github/workflows/release.yml
vendored
Normal file
|
@ -0,0 +1,31 @@
|
|||
name: 🚀 Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*.*'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build-artifacts:
|
||||
uses: ./.github/workflows/build.yml
|
||||
|
||||
create-release:
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- build-artifacts
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Download Build Artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
|
||||
- run: ls -R artifacts/
|
||||
|
||||
- name: Generate New Nightly Release
|
||||
run: |
|
||||
gh release create ${{ github.ref }} ./artifacts/*
|
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
/bin
|
||||
/dist
|
3
README.md
Normal file
3
README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# ccnz compiles nim w/zig
|
||||
|
||||
|
46
ccnz.nimble
Normal file
46
ccnz.nimble
Normal file
|
@ -0,0 +1,46 @@
|
|||
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
|
||||
|
||||
|
||||
|
16
nimble.lock
Normal file
16
nimble.lock
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"version": 2,
|
||||
"packages": {
|
||||
"cligen": {
|
||||
"version": "1.6.14",
|
||||
"vcsRevision": "bee21f2d0878d4eba4631fd8b67370e4778424de",
|
||||
"url": "https://github.com/c-blake/cligen.git",
|
||||
"downloadMethod": "git",
|
||||
"dependencies": [],
|
||||
"checksums": {
|
||||
"sha1": "195164d6a417c5393ee8aac1d1c2dfb0d45574b1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tasks": {}
|
||||
}
|
72
src/ccnz.nim
Normal file
72
src/ccnz.nim
Normal file
|
@ -0,0 +1,72 @@
|
|||
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])
|
113
src/ccnz/utils.nim
Normal file
113
src/ccnz/utils.nim
Normal file
|
@ -0,0 +1,113 @@
|
|||
import std/[json, macros, math, os, osproc, strutils, terminal, sequtils]
|
||||
|
||||
proc errQuit*(msg: varargs[string]) =
|
||||
stderr.write msg.join("\n") & "\n"
|
||||
quit 1
|
||||
|
||||
# based on https://github.com/enthus1ast/zigcc
|
||||
template callZig*(zigCmd: string) =
|
||||
# Set the zig compiler to call and append args
|
||||
var args = @[zigCmd]
|
||||
args &= commandLineParams()
|
||||
# Start process
|
||||
let process = startProcess(
|
||||
"zig",
|
||||
args = args,
|
||||
options = {poStdErrToStdOut, poUsePath, poParentStreams}
|
||||
)
|
||||
# Get the code so we can carry across the exit code
|
||||
let exitCode = process.waitForExit()
|
||||
# Clean up
|
||||
close process
|
||||
quit exitCode
|
||||
|
||||
proc zigExists*() =
|
||||
if (findExe "zig") == "":
|
||||
errQuit "zig not found",
|
||||
"ccnz requires a working installation of zig",
|
||||
"see: https://ziglang.org/download/"
|
||||
|
||||
proc zigTargets*(): seq[string] =
|
||||
let (output, _) = execCmdEx "zig targets"
|
||||
parseJson(output)["libc"].to(seq[string])
|
||||
|
||||
macro addFlag*(arg: untyped): untyped =
|
||||
let
|
||||
flag = "--" & arg.strVal & ":"
|
||||
inferProc = newCall("infer" & arg.strVal, newIdentNode("target"))
|
||||
|
||||
quote do:
|
||||
if `flag` notin args:
|
||||
let selected = `inferProc`
|
||||
if selected != "":
|
||||
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 inferCpu*(target: string): 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:
|
||||
of "x86_64":
|
||||
"amd64"
|
||||
of "aarch64", "aarch64_be":
|
||||
"arm64"
|
||||
of "arm", "armeb":
|
||||
"arm"
|
||||
of "x86":
|
||||
"i386"
|
||||
of "powerpc64el":
|
||||
"powerpc64le"
|
||||
# remain the same
|
||||
of "m68k", "mips64el", "mipsel", "mips", "powerpc", "powerpc64", "riscv64",
|
||||
"sparc", "sparc64", "wasm32":
|
||||
candidate
|
||||
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")
|
||||
|
||||
|
||||
|
3
src/ccnzcc.nim
Normal file
3
src/ccnzcc.nim
Normal file
|
@ -0,0 +1,3 @@
|
|||
import ccnz/utils
|
||||
|
||||
callZig("cc")
|
Loading…
Reference in a new issue