Added release building script
This commit is contained in:
parent
f056377977
commit
7d967073f3
7 changed files with 350 additions and 5 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -41,3 +41,4 @@ opencode-config/package-lock.json
|
||||||
internal/preproc/lib/
|
internal/preproc/lib/
|
||||||
.bun/
|
.bun/
|
||||||
*.asm
|
*.asm
|
||||||
|
.config/
|
||||||
|
|
|
||||||
1
BUILDNUM
Normal file
1
BUILDNUM
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
1
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
FROM ghcr.io/anomalyco/opencode:1.14.48
|
FROM ghcr.io/anomalyco/opencode:1.14.48
|
||||||
|
#FROM ghcr.io/anomalyco/opencode:latest
|
||||||
|
|
||||||
RUN apk add --no-cache go gcc musl-dev
|
RUN apk add --no-cache go gcc musl-dev
|
||||||
|
|
||||||
|
|
|
||||||
91
README.md
91
README.md
|
|
@ -2,6 +2,35 @@
|
||||||
|
|
||||||
A high-level 6502 cross-compiler targeting the ACME Cross-Assembler. c65gm provides a more expressive language for writing 6502 assembly programs, with features like functions, type-checked variables, control flow structures, and compile-time optimizations.
|
A high-level 6502 cross-compiler targeting the ACME Cross-Assembler. c65gm provides a more expressive language for writing 6502 assembly programs, with features like functions, type-checked variables, control flow structures, and compile-time optimizations.
|
||||||
|
|
||||||
|
## Download
|
||||||
|
|
||||||
|
Pre-built binaries are available from the [Releases page](https://github.com/YOUR_USERNAME/c65gm/releases). Each release follows the naming pattern `c65gm_v{MAJOR}.{BUILD}_os_arch`:
|
||||||
|
|
||||||
|
| File | Platform |
|
||||||
|
|------|----------|
|
||||||
|
| `c65gm_v1.1_linux_amd64.tar.gz` | Linux (x86_64) |
|
||||||
|
| `c65gm_v1.1_linux_arm64.tar.gz` | Linux (ARM64) |
|
||||||
|
| `c65gm_v1.1_darwin_amd64.tar.gz` | macOS (Intel) |
|
||||||
|
| `c65gm_v1.1_darwin_arm64.tar.gz` | macOS (Apple Silicon) |
|
||||||
|
| `c65gm_v1.1_windows_amd64.zip` | Windows (x86_64) |
|
||||||
|
|
||||||
|
Each release includes a `checksums.txt` file for verifying download integrity:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sha256sum -c checksums.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
### Verify with the annotated tag
|
||||||
|
|
||||||
|
Every release is created from an annotated git tag containing the Go compiler version and SHA256 checksums. To inspect:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git fetch --tags
|
||||||
|
git tag -l v1.1
|
||||||
|
```
|
||||||
|
|
||||||
|
The tag message shows the exact checksums. You can reproduce the build from the tag and verify your binary matches:
|
||||||
|
|
||||||
## What It Does
|
## What It Does
|
||||||
|
|
||||||
c65gm compiles high-level source code into ACME assembler syntax for the 6502 processor (Commodore 64 and similar platforms). It provides:
|
c65gm compiles high-level source code into ACME assembler syntax for the 6502 processor (Commodore 64 and similar platforms). It provides:
|
||||||
|
|
@ -248,6 +277,68 @@ The example directories also contain `cm.sh` scripts showing the old build metho
|
||||||
- Kate: copy XML to ~/.local/share/org.kde.syntax-highlighting/syntax/
|
- Kate: copy XML to ~/.local/share/org.kde.syntax-highlighting/syntax/
|
||||||
- Sublime: copy .sublime-syntax to Packages/User/
|
- Sublime: copy .sublime-syntax to Packages/User/
|
||||||
|
|
||||||
|
## Release Process
|
||||||
|
|
||||||
|
This section documents how to create a new release for maintainers.
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- Go 1.25.1+ installed
|
||||||
|
- `sha256sum` (Linux) or `shasum` (macOS)
|
||||||
|
- Git with write access to the repository
|
||||||
|
|
||||||
|
### Steps
|
||||||
|
|
||||||
|
The release script does everything automatically. Just run it:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bash scripts/release.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
This performs the following sequence:
|
||||||
|
|
||||||
|
1. **Verify git clean** — fails if uncommitted changes exist
|
||||||
|
2. **Read BUILDNUM** — e.g., `42` → version `1.42`
|
||||||
|
3. **Verify tag available** — fails if tag `v1.42` already exists
|
||||||
|
4. **Bump BUILDNUM** — writes `43` to `BUILDNUM`
|
||||||
|
5. **Build all targets** — 5 platform binaries with version injected via ldflags
|
||||||
|
6. **Generate SHA256 checksums** — written to `dist/checksums.txt`
|
||||||
|
7. **Commit BUILDNUM** — `git commit` with checksums in the commit body
|
||||||
|
8. **Create annotated tag** — `git tag -a v1.42` pointing at the pre-bump commit, with checksums and Go version in the tag message
|
||||||
|
|
||||||
|
### Publish
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git push --follow-tags origin
|
||||||
|
```
|
||||||
|
|
||||||
|
This pushes both the new commit and the annotated tag. The tag is the source of truth for verification.
|
||||||
|
|
||||||
|
### Verify a release
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git checkout v1.42
|
||||||
|
# You now have the exact source (BUILDNUM=42)
|
||||||
|
go build -trimpath -ldflags="-s -w -X main.version=1.42"
|
||||||
|
sha256sum c65gm
|
||||||
|
# Compare with the checksum in: git tag -l v1.42
|
||||||
|
```
|
||||||
|
|
||||||
|
### Reproducible builds
|
||||||
|
|
||||||
|
The release script uses these flags for deterministic builds:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
go build -trimpath -ldflags="-s -w -X main.version=${VERSION}"
|
||||||
|
```
|
||||||
|
|
||||||
|
- `-trimpath` strips local filesystem paths
|
||||||
|
- `-s -w` strips symbol table and DWARF debug info
|
||||||
|
- `-X main.version` injects the version
|
||||||
|
- `CGO_ENABLED=0` ensures fully static binaries
|
||||||
|
|
||||||
|
Binaries built from the same source with the same Go version produce identical hashes. The tag message captures the Go version and expected checksums for verification.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
Copyright (C) 1999, 2025 Mattias Hansson
|
Copyright (C) 1999, 2025 Mattias Hansson
|
||||||
|
|
|
||||||
11
main.go
11
main.go
|
|
@ -20,6 +20,8 @@ import (
|
||||||
// Copyright (C) 1999, 2025 Mattias Hansson
|
// Copyright (C) 1999, 2025 Mattias Hansson
|
||||||
// Distributed under GPL.
|
// Distributed under GPL.
|
||||||
|
|
||||||
|
var version = "dev"
|
||||||
|
|
||||||
// ANSI color codes for error messages
|
// ANSI color codes for error messages
|
||||||
const (
|
const (
|
||||||
colorRed = "\033[31m"
|
colorRed = "\033[31m"
|
||||||
|
|
@ -28,8 +30,14 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
// Check for version flag before banner
|
||||||
|
if len(os.Args) == 2 && (os.Args[1] == "--version" || os.Args[1] == "-V") {
|
||||||
|
fmt.Printf("c65gm v%s\n", version)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Println("c65gm - A 6502 Cross-Compiler for the ACME Cross-Assembler.")
|
fmt.Println("c65gm - A 6502 Cross-Compiler for the ACME Cross-Assembler.")
|
||||||
fmt.Println("Copyright (C) 1999, 2025 Mattias Hansson. v1.0.0")
|
fmt.Printf("Copyright (C) 1999, 2025 Mattias Hansson. v%s\n", version)
|
||||||
fmt.Println("Distributed under GPL.")
|
fmt.Println("Distributed under GPL.")
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
|
|
||||||
|
|
@ -222,6 +230,7 @@ func printUsage() {
|
||||||
fmt.Println(" -o, --output Output file (default: <input>.prg for build, <input>.asm for compile)")
|
fmt.Println(" -o, --output Output file (default: <input>.prg for build, <input>.asm for compile)")
|
||||||
fmt.Println(" --keep-asm Keep intermediate assembly file (build command only)")
|
fmt.Println(" --keep-asm Keep intermediate assembly file (build command only)")
|
||||||
fmt.Println(" --no-cbm Don't add -f cbm flag to ACME (build command only)")
|
fmt.Println(" --no-cbm Don't add -f cbm flag to ACME (build command only)")
|
||||||
|
fmt.Println(" -V, --version Show version")
|
||||||
}
|
}
|
||||||
|
|
||||||
func runBuildCommand(args []string) {
|
func runBuildCommand(args []string) {
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,16 @@
|
||||||
"$schema": "https://opencode.ai/config.json",
|
"$schema": "https://opencode.ai/config.json",
|
||||||
"agent": {
|
"agent": {
|
||||||
"plan": {
|
"plan": {
|
||||||
"model": "deepseek/deepseek-reasoner",
|
"model": "deepseek/deepseek-v4-pro",
|
||||||
"description": "Planning and architecture analysis using DeepSeek Reasoner"
|
"options": {
|
||||||
|
"thinking": { "type": "enabled" },
|
||||||
|
"reasoningEffort": "high"
|
||||||
|
},
|
||||||
|
"description": "Planning and architecture analysis using DeepSeek V4 Pro"
|
||||||
},
|
},
|
||||||
"build": {
|
"build": {
|
||||||
"model": "deepseek/deepseek-chat",
|
"model": "deepseek/deepseek-v4-flash",
|
||||||
"description": "Implementation and coding using DeepSeek Chat"
|
"description": "Implementation and coding using DeepSeek V4 Flash"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
238
scripts/release.sh
Executable file
238
scripts/release.sh
Executable file
|
|
@ -0,0 +1,238 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# c65gm Release Builder
|
||||||
|
#
|
||||||
|
# Fully automated release process:
|
||||||
|
# 1. Verifies git working tree is clean
|
||||||
|
# 2. Reads BUILDNUM, derives version (MAJOR.BUILDNUM)
|
||||||
|
# 3. Verifies the tag doesn't already exist
|
||||||
|
# 4. Bumps BUILDNUM
|
||||||
|
# 5. Builds all target binaries (embedded lib, version injected)
|
||||||
|
# 6. Generates SHA256 checksums
|
||||||
|
# 7. Commits the BUILDNUM bump (with checksums in commit body)
|
||||||
|
# 8. Creates an annotated tag pointing at PRE-bump commit
|
||||||
|
# (tag message contains checksums + build info for verification)
|
||||||
|
#
|
||||||
|
# To publish the release:
|
||||||
|
# git push --follow-tags origin
|
||||||
|
|
||||||
|
MAJOR=1
|
||||||
|
|
||||||
|
print_ok() { echo " [OK] $1"; }
|
||||||
|
print_err() { echo " [ERROR] $1" >&2; }
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== c65gm Release Builder ==="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 1. Verify git working tree is clean
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
if [ -n "$(git status --porcelain 2>/dev/null)" ]; then
|
||||||
|
echo ""
|
||||||
|
git status --short
|
||||||
|
echo ""
|
||||||
|
print_err "working tree is not clean — commit or stash changes first"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
print_ok "Working tree is clean"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 2. Read BUILDNUM
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
if [ ! -f BUILDNUM ]; then
|
||||||
|
echo "1" > BUILDNUM
|
||||||
|
fi
|
||||||
|
|
||||||
|
BUILDNUM=$(cat BUILDNUM)
|
||||||
|
VERSION="${MAJOR}.${BUILDNUM}"
|
||||||
|
TAG="v${VERSION}"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 3. Verify tag doesn't already exist
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
if git rev-parse --quiet --verify "refs/tags/${TAG}" >/dev/null 2>&1; then
|
||||||
|
print_err "tag ${TAG} already exists — bump BUILDNUM manually if needed"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
print_ok "Tag ${TAG} is available"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 4. Save source commit (before any changes)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
SOURCE_COMMIT=$(git rev-parse HEAD)
|
||||||
|
if [ -z "$SOURCE_COMMIT" ]; then
|
||||||
|
print_err "could not determine HEAD commit"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo " Version: ${TAG}"
|
||||||
|
echo " Source: ${SOURCE_COMMIT}"
|
||||||
|
echo " BUILDNUM: ${BUILDNUM} (bumps to $((BUILDNUM + 1)))"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 5. Bump BUILDNUM
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
NEXT_BUILDNUM=$((BUILDNUM + 1))
|
||||||
|
echo "${NEXT_BUILDNUM}" > BUILDNUM
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 6. Copy lib for embedding
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo " Preparing embedded library..."
|
||||||
|
rm -rf internal/preproc/lib
|
||||||
|
cp -r lib internal/preproc/
|
||||||
|
print_ok "Library copied for embedding"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Build metadata
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
GO_VERSION="$(go version 2>/dev/null || echo 'unknown')"
|
||||||
|
BUILD_DATE="$(date -u +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u +%Y-%m-%d)"
|
||||||
|
|
||||||
|
LDFLAGS="-s -w -X main.version=${VERSION}"
|
||||||
|
DIST="dist"
|
||||||
|
mkdir -p "$DIST"
|
||||||
|
|
||||||
|
# SHA256 command detection (Linux vs macOS)
|
||||||
|
SHA_CMD=""
|
||||||
|
if command -v sha256sum &>/dev/null; then
|
||||||
|
SHA_CMD="sha256sum"
|
||||||
|
elif command -v shasum &>/dev/null; then
|
||||||
|
SHA_CMD="shasum -a 256"
|
||||||
|
else
|
||||||
|
print_err "no sha256sum or shasum command found"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Targets
|
||||||
|
TARGETS=(
|
||||||
|
"linux/amd64"
|
||||||
|
"linux/arm64"
|
||||||
|
"darwin/amd64"
|
||||||
|
"darwin/arm64"
|
||||||
|
"windows/amd64"
|
||||||
|
)
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo " Building targets: ${TARGETS[*]}"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 7. Build all targets
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
BUILD_DIR="$(mktemp -d)"
|
||||||
|
trap 'rm -rf "$BUILD_DIR"' EXIT
|
||||||
|
|
||||||
|
for target in "${TARGETS[@]}"; do
|
||||||
|
GOOS="${target%%/*}"
|
||||||
|
GOARCH="${target##*/}"
|
||||||
|
|
||||||
|
bin_name="c65gm"
|
||||||
|
[ "$GOOS" = "windows" ] && bin_name="c65gm.exe"
|
||||||
|
|
||||||
|
echo " ${target}..."
|
||||||
|
|
||||||
|
GOOS=$GOOS GOARCH=$GOARCH CGO_ENABLED=0 \
|
||||||
|
go build -trimpath -ldflags="$LDFLAGS" -o "${BUILD_DIR}/${bin_name}"
|
||||||
|
|
||||||
|
archive_name="c65gm_v${VERSION}_${GOOS}_${GOARCH}"
|
||||||
|
if [ "$GOOS" = "windows" ]; then
|
||||||
|
(cd "$BUILD_DIR" && zip -q "${OLDPWD}/${DIST}/${archive_name}.zip" "$bin_name")
|
||||||
|
echo " => ${DIST}/${archive_name}.zip"
|
||||||
|
else
|
||||||
|
tar -czf "${DIST}/${archive_name}.tar.gz" -C "$BUILD_DIR" "$bin_name"
|
||||||
|
echo " => ${DIST}/${archive_name}.tar.gz"
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f "${BUILD_DIR}/${bin_name}"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
print_ok "All targets built"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 8. Generate checksums
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo ""
|
||||||
|
echo "=== SHA256 checksums ==="
|
||||||
|
echo ""
|
||||||
|
(
|
||||||
|
cd "$DIST"
|
||||||
|
$SHA_CMD * > checksums.txt
|
||||||
|
cat checksums.txt
|
||||||
|
)
|
||||||
|
|
||||||
|
CHECKSUMS_TEXT="$(cat "${DIST}/checksums.txt")"
|
||||||
|
print_ok "Checksums generated"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 9. Commit BUILDNUM bump
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo ""
|
||||||
|
echo "=== Creating commit ==="
|
||||||
|
|
||||||
|
COMMIT_MSG=$(cat << COMMIT_EOF
|
||||||
|
${TAG}
|
||||||
|
|
||||||
|
Built with: ${GO_VERSION}
|
||||||
|
Build date: ${BUILD_DATE}
|
||||||
|
|
||||||
|
SHA256 checksums:
|
||||||
|
${CHECKSUMS_TEXT}
|
||||||
|
COMMIT_EOF
|
||||||
|
)
|
||||||
|
|
||||||
|
git add BUILDNUM
|
||||||
|
git commit -m "$COMMIT_MSG"
|
||||||
|
print_ok "Commit created (BUILDNUM bumped to ${NEXT_BUILDNUM})"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 10. Create annotated tag pointing at source commit
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo ""
|
||||||
|
echo "=== Creating tag ==="
|
||||||
|
|
||||||
|
TAG_MSG=$(cat << TAG_EOF
|
||||||
|
c65gm ${TAG}
|
||||||
|
|
||||||
|
Built with: ${GO_VERSION}
|
||||||
|
Build date: ${BUILD_DATE}
|
||||||
|
|
||||||
|
SHA256 checksums:
|
||||||
|
${CHECKSUMS_TEXT}
|
||||||
|
|
||||||
|
To reproduce this build:
|
||||||
|
git checkout ${TAG}
|
||||||
|
go build -trimpath -ldflags="${LDFLAGS}"
|
||||||
|
|
||||||
|
Then verify:
|
||||||
|
sha256sum c65gm
|
||||||
|
TAG_EOF
|
||||||
|
)
|
||||||
|
|
||||||
|
git tag -a "$TAG" "$SOURCE_COMMIT" -m "$TAG_MSG"
|
||||||
|
print_ok "Tag ${TAG} created (pointing at ${SOURCE_COMMIT})"
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# 11. Summary
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
echo ""
|
||||||
|
echo "============================================"
|
||||||
|
echo " c65gm ${TAG} released!"
|
||||||
|
echo ""
|
||||||
|
echo " Source commit: ${SOURCE_COMMIT}"
|
||||||
|
echo " BUILDNUM: ${BUILDNUM} → ${NEXT_BUILDNUM}"
|
||||||
|
echo " Artifacts in: ${DIST}/"
|
||||||
|
echo " Go version: ${GO_VERSION}"
|
||||||
|
echo ""
|
||||||
|
echo " To publish:"
|
||||||
|
echo " git push --follow-tags origin"
|
||||||
|
echo ""
|
||||||
|
echo " Artifacts:"
|
||||||
|
ls -lh "${DIST}/" | sed 's/^/ /'
|
||||||
|
echo "============================================"
|
||||||
|
echo ""
|
||||||
Loading…
Reference in a new issue