chore: mvp

This commit is contained in:
Daylin Morgan 2023-09-04 23:24:13 -05:00
parent af54a4cfc4
commit 9dc6353e8b
Signed by: daylin
GPG key ID: C1E52E7DD81DF79F
10 changed files with 385 additions and 0 deletions

39
.github/workflows/build.yml vendored Normal file
View 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
View 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
View 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
View file

@ -0,0 +1,2 @@
/bin
/dist

3
README.md Normal file
View file

@ -0,0 +1,3 @@
# ccnz compiles nim w/zig

46
ccnz.nimble Normal file
View 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
View 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
View 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
View 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
View file

@ -0,0 +1,3 @@
import ccnz/utils
callZig("cc")