diff --git a/parser/Makefile.toml b/parser/Makefile.toml index 09d1a3b..403e892 100644 --- a/parser/Makefile.toml +++ b/parser/Makefile.toml @@ -39,12 +39,11 @@ "cargo build -Z unstable-options --target ${TARGET} ${CARGO_OPTIONS} --artifact-dir target/cpp/${CONFIGURATION}", "cp target/cpp/${CONFIGURATION}/libmilo_parser.a ../dist/cpp/${CONFIGURATION}/libmilo.a", "cp target/headers/milo.h ../dist/cpp/${CONFIGURATION}", - "node ../scripts/postbuild-cpp.js ${CONFIGURATION}", ] [tasks."cpp:headers"] - command = "cbindgen" - args = ["--quiet", "--output", "target/headers/milo.h"] + command = "bash" + args = ["../scripts/postbuild-cpp.sh", "target/headers/milo.h"] [tasks."wasm:release"] env = { CONFIGURATION = "release", CARGO_BUILD_OPTIONS = "-Z unstable-options -Z build-std=std,panic_abort", CARGO_OPTIONS = "--release", RUSTFLAGS_BASE = "-Z unstable-options -C panic=immediate-abort", WASMPACK_OPTIONS = "--release" } diff --git a/scripts/postbuild-cpp.js b/scripts/postbuild-cpp.js deleted file mode 100644 index 5e62d66..0000000 --- a/scripts/postbuild-cpp.js +++ /dev/null @@ -1,44 +0,0 @@ -import { readFile, writeFile } from 'node:fs/promises' -import { getBuildInfo } from './buildinfo.js' - -async function prependVersionAndMethodMap () { - const headerMatcher = 'namespace milo_parser {' - - const { - version: { raw, major, minor, patch, prerelease }, - constants - } = await getBuildInfo() - - // Create the method map, required by Node.js - const methods = Object.entries(constants) - .filter(p => p[0].startsWith('METHOD_')) - .map(([k, v]) => [k.replace('METHOD_', ''), v]) - - const updatedHeader = ` -#define MILO_VERSION "${raw}" -#define MILO_VERSION_MAJOR ${major} -#define MILO_VERSION_MINOR ${minor} -#define MILO_VERSION_PATCH ${patch} -#define MILO_VERSION_PRERELEASE "${prerelease}" - -#define MILO_METHODS_MAP(EACH) \\ -${methods.map(([v, i]) => ` EACH(${i}, ${v}, ${v}) \\`).join('\n')} - -namespace milo_parser { - -struct Parser; -`.trim() - - // Replace the header with the new code - return header.replace(/\n{3,}/g, '\n\n').replace(headerMatcher, updatedHeader) -} - -// Read the file -const headerPath = new URL(`../dist/cpp/${process.argv[2]}/milo.h`, import.meta.url) -let header = await readFile(headerPath, 'utf-8') - -// Apply modifications -header = await prependVersionAndMethodMap(header) - -// Write the updated file -await writeFile(headerPath, header, 'utf-8') diff --git a/scripts/postbuild-cpp.sh b/scripts/postbuild-cpp.sh new file mode 100755 index 0000000..7d213a3 --- /dev/null +++ b/scripts/postbuild-cpp.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash +set -euo pipefail + +if [ $# -lt 1 ]; then + echo "Usage: postbuild-cpp.sh " >&2 + exit 1 +fi + +OUTPUT_FILE="$1" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" + +mkdir -p "$(dirname "$OUTPUT_FILE")" +TMPFILE=$(mktemp) +trap 'rm -f "$TMPFILE"' EXIT + +# Run cbindgen from the parser directory so cargo finds its vendored config. +# RUSTC_BOOTSTRAP=1 allows stable rustc to accept -Zunpretty=expanded, which +# cbindgen needs for [parse.expand] to resolve proc-macro-generated types. +(cd "$ROOT_DIR/parser" && RUSTC_BOOTSTRAP=1 cbindgen --quiet --output "$TMPFILE") + +# Extract version from parser/Cargo.toml +VERSION=$(grep -m1 '^\s*version\s*=' "$ROOT_DIR/parser/Cargo.toml" | sed 's/.*"\([^"]*\)".*/\1/') +if [ -z "$VERSION" ]; then + echo "Error: Cannot find parser version in parser/Cargo.toml" >&2 + exit 1 +fi + +# Parse semver components +MAJOR="${VERSION%%.*}" +REST="${VERSION#*.}" +MINOR="${REST%%.*}" +REST="${REST#*.}" +if [[ "$REST" == *-* ]]; then + PATCH="${REST%%-*}" + PRERELEASE="${REST#*-}" +else + PATCH="$REST" + PRERELEASE="" +fi + +# Read methods from YAML (skip comments, blank lines, and document start marker) +mapfile -t METHODS < <(grep '^- ' "$ROOT_DIR/macros/constants/methods.yml" | sed 's/^- //' | tr '-' '_') + +# Build the replacement block +REPLACEMENT=$( + printf '#define MILO_VERSION "%s"\n' "$VERSION" + printf '#define MILO_VERSION_MAJOR %s\n' "$MAJOR" + printf '#define MILO_VERSION_MINOR %s\n' "$MINOR" + printf '#define MILO_VERSION_PATCH %s\n' "$PATCH" + printf '#define MILO_VERSION_PRERELEASE "%s"\n' "$PRERELEASE" + printf '\n' + printf '#define MILO_METHODS_MAP(EACH) \\\\\n' + for i in "${!METHODS[@]}"; do + printf ' EACH(%d, %s, %s) \\\\\n' "$i" "${METHODS[$i]}" "${METHODS[$i]}" + done + printf '\n' + printf 'namespace milo_parser {\n' + printf '\n' + printf 'struct Parser;' +) + +# Replace "namespace milo_parser {" with the preamble, then collapse 3+ blank lines to 1 +awk -v replacement="$REPLACEMENT" ' + /^namespace milo_parser \{$/ && !replaced { + print replacement + replaced = 1 + next + } + { print } +' "$TMPFILE" \ +| awk '/^$/ { blank++; if (blank <= 1) print; next } { blank = 0; print }' \ +> "$OUTPUT_FILE"