mirror of
https://github.com/daylinmorgan/forge.git
synced 2024-11-27 18:00:43 -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