2025-08-31 06:22:48 +09:00
|
|
|
|
#!/usr/bin/env bash
|
|
|
|
|
|
set -euo pipefail
|
|
|
|
|
|
|
|
|
|
|
|
if [[ "${NYASH_CLI_VERBOSE:-0}" == "1" ]]; then
|
|
|
|
|
|
set -x
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
usage() {
|
|
|
|
|
|
cat << USAGE
|
2025-11-06 15:41:52 +09:00
|
|
|
|
Usage: tools/build_llvm.sh <input.hako> [-o <output>]
|
2025-08-31 06:22:48 +09:00
|
|
|
|
|
|
|
|
|
|
Compiles a Nyash program with the LLVM backend to an object (.o),
|
|
|
|
|
|
links it with the NyRT static runtime, and produces a native executable.
|
|
|
|
|
|
|
|
|
|
|
|
Options:
|
2025-09-20 09:11:52 +09:00
|
|
|
|
-o <output> Output executable path (default: tmp/app)
|
2025-08-31 06:22:48 +09:00
|
|
|
|
|
|
|
|
|
|
Requirements:
|
|
|
|
|
|
- LLVM 18 development (llvm-config-18)
|
2025-09-24 12:57:33 +09:00
|
|
|
|
- Nyash Kernel static runtime (crates/nyash_kernel)
|
2025-08-31 06:22:48 +09:00
|
|
|
|
USAGE
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if [[ $# -lt 1 ]]; then usage; exit 1; fi
|
|
|
|
|
|
|
|
|
|
|
|
INPUT=""
|
2025-09-20 09:11:52 +09:00
|
|
|
|
OUT="tmp/app"
|
2025-08-31 06:22:48 +09:00
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
|
|
|
|
case "$1" in
|
|
|
|
|
|
-h|--help) usage; exit 0 ;;
|
|
|
|
|
|
-o) OUT="$2"; shift 2 ;;
|
|
|
|
|
|
*) INPUT="$1"; shift ;;
|
|
|
|
|
|
esac
|
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
|
|
if [[ ! -f "$INPUT" ]]; then
|
|
|
|
|
|
echo "error: input file not found: $INPUT" >&2
|
|
|
|
|
|
exit 1
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
|
|
if ! command -v llvm-config-18 >/dev/null 2>&1; then
|
|
|
|
|
|
echo "error: llvm-config-18 not found (install LLVM 18 dev)." >&2
|
|
|
|
|
|
exit 2
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
2025-12-18 09:13:23 +09:00
|
|
|
|
# Use the cargo target dir when set (helps LLVM EXE smokes that build under /tmp).
|
|
|
|
|
|
CARGO_TARGET_DIR_EFFECTIVE="${CARGO_TARGET_DIR:-$PWD/target}"
|
|
|
|
|
|
|
2025-12-18 17:48:05 +09:00
|
|
|
|
# Rust builds (especially rmeta/rlib finalization) may fail with EXDEV when the temp dir
|
|
|
|
|
|
# is not compatible with the output directory. Prefer a temp dir under the final output
|
|
|
|
|
|
# folder so rustc can atomically persist artifacts without cross-device rename issues.
|
|
|
|
|
|
#
|
|
|
|
|
|
# NOTE: release/deps may not exist yet on first build, so create it eagerly.
|
docs: Phase 131 refactoring tasks 1-7 completion
Update documentation with refactoring results:
**phase-131/README.md**:
- Document all 7 refactoring tasks (1: MergeContracts, 2: instruction_rewriter boxification,
3-4: OutputContract + require_joinir_dev, 5: env.sh SSOT, 6: MergeConfig, 7: contract_checks tests)
- Add task descriptions and success criteria
- Document benefits and test results
- Reference implementation files and commits
**tools/build_llvm.sh**:
- Use TARGET_TMPDIR from env.sh for TMPDIR configuration
- Improve EXDEV mitigation for WSL compatibility
- Better artifact finalization handling
**Summary of Phase 131 Refactoring**:
7 refactoring tasks completed on schedule:
✅ Task 1 (MergeContracts): +30 lines, SSOT for merge contracts
✅ Task 2 (instruction_rewriter): +212 lines (policy box), -50 lines (rewriter)
✅ Task 3 (OutputContract): +90 lines, unified verification interface
✅ Task 4 (require_joinir_dev): +14 lines, dev-only helper
✅ Task 5 (env.sh SSOT): +1014 lines, centralized environment
✅ Task 6 (MergeConfig): +54 lines, unified configuration
✅ Task 7 (contract_checks tests): +116 lines, 4 new tests
Total: ~2500 new lines, 0 regressions, all tests PASS
Benefits:
- Code organization: Single responsibility principle
- Maintainability: SSOT reduces duplication
- Testability: Policy boxes and unit tests enable regression detection
- Developer experience: Clearer code, better documentation
Related: Phase 131 P1.5-P2 DirectValue exit reconnection + infrastructure improvement
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2025-12-18 18:29:02 +09:00
|
|
|
|
# TMPDIR configuration (SSOT: tools/smokes/v2/lib/env.sh sets TARGET_TMPDIR)
|
|
|
|
|
|
# Use TARGET_TMPDIR if set by smoke framework, otherwise fallback to cargo deps dir
|
|
|
|
|
|
TMPDIR_EFFECTIVE="${TMPDIR:-${TARGET_TMPDIR:-$CARGO_TARGET_DIR_EFFECTIVE/release/deps}}"
|
2025-12-18 17:48:05 +09:00
|
|
|
|
mkdir -p "$TMPDIR_EFFECTIVE"
|
|
|
|
|
|
export TMPDIR="$TMPDIR_EFFECTIVE"
|
|
|
|
|
|
|
2025-12-18 09:22:11 +09:00
|
|
|
|
BIN_DEFAULT="$CARGO_TARGET_DIR_EFFECTIVE/release/hakorune"
|
|
|
|
|
|
BIN="${NYASH_BIN:-$BIN_DEFAULT}"
|
|
|
|
|
|
|
2025-12-10 00:01:53 +09:00
|
|
|
|
echo "[1/4] Building hakorune (feature selectable) ..."
|
2025-09-14 04:51:33 +09:00
|
|
|
|
# Select LLVM feature: default harness (llvm), or legacy inkwell when NYASH_LLVM_FEATURE=llvm-inkwell-legacy
|
|
|
|
|
|
LLVM_FEATURE=${NYASH_LLVM_FEATURE:-llvm}
|
2025-12-18 09:13:23 +09:00
|
|
|
|
|
2025-09-14 17:09:16 +09:00
|
|
|
|
# Use 24 threads for parallel build
|
2025-09-24 03:28:24 +09:00
|
|
|
|
if [[ "$LLVM_FEATURE" == "llvm-inkwell-legacy" ]]; then
|
|
|
|
|
|
# Legacy inkwell需要LLVM_SYS_180_PREFIX
|
|
|
|
|
|
_LLVMPREFIX=$(llvm-config-18 --prefix)
|
|
|
|
|
|
LLVM_SYS_181_PREFIX="${_LLVMPREFIX}" LLVM_SYS_180_PREFIX="${_LLVMPREFIX}" \
|
2025-12-18 17:48:05 +09:00
|
|
|
|
CARGO_INCREMENTAL=0 cargo build --release -j 24 -p nyash-rust --features "$LLVM_FEATURE" >/dev/null
|
2025-09-24 03:28:24 +09:00
|
|
|
|
else
|
|
|
|
|
|
# llvm-harness(デフォルト)はLLVM_SYS_180_PREFIX不要
|
2025-12-18 17:48:05 +09:00
|
|
|
|
CARGO_INCREMENTAL=0 cargo build --release -j 24 -p nyash-rust --features "$LLVM_FEATURE" >/dev/null
|
2025-09-24 03:28:24 +09:00
|
|
|
|
fi
|
2025-08-31 06:22:48 +09:00
|
|
|
|
|
2025-12-18 09:22:11 +09:00
|
|
|
|
if [[ ! -x "$BIN" ]]; then
|
|
|
|
|
|
# Backward compatible fallback for older layouts.
|
|
|
|
|
|
if [[ -x "$CARGO_TARGET_DIR_EFFECTIVE/release/nyash" ]]; then
|
|
|
|
|
|
BIN="$CARGO_TARGET_DIR_EFFECTIVE/release/nyash"
|
|
|
|
|
|
else
|
|
|
|
|
|
echo "error: compiler binary not found/executable after build: $BIN" >&2
|
|
|
|
|
|
echo "hint: ensure NYASH_BIN points to an existing binary or set CARGO_TARGET_DIR correctly" >&2
|
|
|
|
|
|
exit 1
|
|
|
|
|
|
fi
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
2025-08-31 06:22:48 +09:00
|
|
|
|
echo "[2/4] Emitting object (.o) via LLVM backend ..."
|
2025-12-18 09:22:11 +09:00
|
|
|
|
# Default object output path under $CARGO_TARGET_DIR/aot_objects
|
|
|
|
|
|
mkdir -p "$CARGO_TARGET_DIR_EFFECTIVE/aot_objects"
|
2025-09-01 23:44:34 +09:00
|
|
|
|
stem=$(basename "$INPUT")
|
2025-11-06 15:41:52 +09:00
|
|
|
|
stem=${stem%.hako}
|
2025-12-18 09:22:11 +09:00
|
|
|
|
OBJ="${NYASH_LLVM_OBJ_OUT:-$CARGO_TARGET_DIR_EFFECTIVE/aot_objects/${stem}.o}"
|
2025-09-01 23:44:34 +09:00
|
|
|
|
if [[ "${NYASH_LLVM_SKIP_EMIT:-0}" != "1" ]]; then
|
|
|
|
|
|
rm -f "$OBJ"
|
2025-09-17 22:01:29 +09:00
|
|
|
|
COMPILER_MODE=${NYASH_LLVM_COMPILER:-harness}
|
|
|
|
|
|
case "$COMPILER_MODE" in
|
|
|
|
|
|
crate)
|
|
|
|
|
|
# Use crates/nyash-llvm-compiler (ny-llvmc): requires pre-generated MIR JSON path in NYASH_LLVM_MIR_JSON
|
|
|
|
|
|
if [[ -z "${NYASH_LLVM_MIR_JSON:-}" ]]; then
|
2025-09-17 22:11:59 +09:00
|
|
|
|
# Auto‑emit MIR JSON via nyash CLI flag
|
|
|
|
|
|
mkdir -p tmp
|
|
|
|
|
|
NYASH_LLVM_MIR_JSON="tmp/nyash_crate_mir.json"
|
|
|
|
|
|
echo " emitting MIR JSON: $NYASH_LLVM_MIR_JSON" >&2
|
2025-12-10 00:01:53 +09:00
|
|
|
|
"$BIN" --emit-mir-json "$NYASH_LLVM_MIR_JSON" --backend mir "$INPUT" >/dev/null
|
2025-09-17 22:11:59 +09:00
|
|
|
|
fi
|
|
|
|
|
|
echo " using ny-llvmc (crate) with JSON: $NYASH_LLVM_MIR_JSON" >&2
|
|
|
|
|
|
cargo build --release -p nyash-llvm-compiler >/dev/null
|
|
|
|
|
|
# Optional schema validation when explicitly requested
|
|
|
|
|
|
if [[ "${NYASH_LLVM_VALIDATE_JSON:-0}" == "1" ]]; then
|
2025-09-17 22:01:29 +09:00
|
|
|
|
if [[ -f tools/validate_mir_json.py ]]; then
|
|
|
|
|
|
if ! python3 -m jsonschema --version >/dev/null 2>&1; then
|
|
|
|
|
|
echo "[warn] jsonschema not available; skipping schema validation" >&2
|
|
|
|
|
|
else
|
|
|
|
|
|
echo " validating MIR JSON schema ..." >&2
|
|
|
|
|
|
python3 tools/validate_mir_json.py "$NYASH_LLVM_MIR_JSON" || {
|
|
|
|
|
|
echo "error: MIR JSON validation failed" >&2; exit 3; }
|
|
|
|
|
|
fi
|
|
|
|
|
|
fi
|
|
|
|
|
|
fi
|
2025-09-18 03:57:25 +09:00
|
|
|
|
if [[ "${NYASH_LLVM_EMIT:-obj}" == "exe" ]]; then
|
|
|
|
|
|
echo " emitting EXE via ny-llvmc (crate) ..." >&2
|
2025-09-24 12:57:33 +09:00
|
|
|
|
# Ensure Nyash Kernel is built (for libnyash_kernel.a)
|
|
|
|
|
|
if [[ ! -f crates/nyash_kernel/target/release/libnyash_kernel.a && "${NYASH_LLVM_SKIP_NYRT_BUILD:-0}" != "1" ]]; then
|
|
|
|
|
|
( cd crates/nyash_kernel && cargo build --release -j 24 >/dev/null )
|
2025-09-18 03:57:25 +09:00
|
|
|
|
fi
|
2025-09-24 12:57:33 +09:00
|
|
|
|
NYRT_DIR_HINT="${NYASH_LLVM_NYRT:-crates/nyash_kernel/target/release}"
|
2025-09-18 03:57:25 +09:00
|
|
|
|
./target/release/ny-llvmc --in "$NYASH_LLVM_MIR_JSON" --out "$OUT" --emit exe --nyrt "$NYRT_DIR_HINT" ${NYASH_LLVM_LIBS:+--libs "$NYASH_LLVM_LIBS"}
|
|
|
|
|
|
echo "✅ Done: $OUT"; echo " (runtime may require nyash.toml and plugins depending on app)"; exit 0
|
|
|
|
|
|
else
|
|
|
|
|
|
./target/release/ny-llvmc --in "$NYASH_LLVM_MIR_JSON" --out "$OBJ"
|
|
|
|
|
|
fi
|
2025-09-17 22:01:29 +09:00
|
|
|
|
;;
|
|
|
|
|
|
esac
|
|
|
|
|
|
if [[ "$COMPILER_MODE" == "harness" ]]; then
|
|
|
|
|
|
if [[ "${NYASH_LLVM_FEATURE:-llvm}" == "llvm-inkwell-legacy" ]]; then
|
2025-09-24 03:28:24 +09:00
|
|
|
|
# Legacy path: do not use harness (LLVM_SYS_180_PREFIX needed)
|
|
|
|
|
|
_LLVMPREFIX=$(llvm-config-18 --prefix)
|
2025-09-17 22:01:29 +09:00
|
|
|
|
NYASH_LLVM_OBJ_OUT="$OBJ" LLVM_SYS_181_PREFIX="${_LLVMPREFIX}" LLVM_SYS_180_PREFIX="${_LLVMPREFIX}" \
|
2025-12-10 00:01:53 +09:00
|
|
|
|
"$BIN" --backend llvm "$INPUT" >/dev/null || true
|
2025-09-17 22:01:29 +09:00
|
|
|
|
else
|
2025-09-24 03:28:24 +09:00
|
|
|
|
# Harness path (Python llvmlite - LLVM_SYS_180_PREFIX不要)
|
|
|
|
|
|
NYASH_LLVM_OBJ_OUT="$OBJ" NYASH_LLVM_USE_HARNESS=1 \
|
2025-12-10 00:01:53 +09:00
|
|
|
|
"$BIN" --backend llvm "$INPUT" >/dev/null || true
|
2025-09-17 22:01:29 +09:00
|
|
|
|
fi
|
2025-09-14 04:51:33 +09:00
|
|
|
|
fi
|
2025-09-01 23:44:34 +09:00
|
|
|
|
fi
|
2025-08-31 06:22:48 +09:00
|
|
|
|
if [[ ! -f "$OBJ" ]]; then
|
|
|
|
|
|
echo "error: object not generated: $OBJ" >&2
|
2025-09-01 23:44:34 +09:00
|
|
|
|
echo "hint: you can pre-generate it (e.g. via --run-task smoke_obj_*) and set NYASH_LLVM_SKIP_EMIT=1" >&2
|
2025-08-31 06:22:48 +09:00
|
|
|
|
exit 3
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
2025-09-17 22:11:59 +09:00
|
|
|
|
if [[ "${NYASH_LLVM_ONLY_OBJ:-0}" == "1" ]]; then
|
|
|
|
|
|
echo "[3/4] Skipping link: object generated at $OBJ (NYASH_LLVM_ONLY_OBJ=1)"
|
|
|
|
|
|
exit 0
|
|
|
|
|
|
fi
|
|
|
|
|
|
|
2025-09-24 12:57:33 +09:00
|
|
|
|
echo "[3/4] Building Nyash Kernel static runtime ..."
|
2025-09-01 23:44:34 +09:00
|
|
|
|
if [[ "${NYASH_LLVM_SKIP_NYRT_BUILD:-0}" == "1" ]]; then
|
2025-09-24 12:57:33 +09:00
|
|
|
|
echo " Skipping Nyash Kernel build (NYASH_LLVM_SKIP_NYRT_BUILD=1)"
|
2025-09-01 23:44:34 +09:00
|
|
|
|
else
|
2025-12-18 09:13:23 +09:00
|
|
|
|
NYRT_LIB_PRIMARY="$CARGO_TARGET_DIR_EFFECTIVE/release/libnyash_kernel.a"
|
2025-12-15 11:06:26 +09:00
|
|
|
|
NYRT_LIB_ALT="crates/nyash_kernel/target/release/libnyash_kernel.a"
|
|
|
|
|
|
if [[ ( -f "$NYRT_LIB_PRIMARY" || -f "$NYRT_LIB_ALT" ) && "${NYASH_LLVM_FORCE_NYRT_BUILD:-0}" != "1" ]]; then
|
|
|
|
|
|
echo " Using cached Nyash Kernel runtime (set NYASH_LLVM_FORCE_NYRT_BUILD=1 to rebuild)"
|
|
|
|
|
|
else
|
2025-09-14 17:09:16 +09:00
|
|
|
|
# Use 24 threads for parallel build
|
2025-09-24 12:57:33 +09:00
|
|
|
|
( cd crates/nyash_kernel && cargo build --release -j 24 >/dev/null )
|
2025-12-15 11:06:26 +09:00
|
|
|
|
fi
|
2025-09-01 23:44:34 +09:00
|
|
|
|
fi
|
2025-08-31 06:22:48 +09:00
|
|
|
|
|
2025-09-20 09:11:52 +09:00
|
|
|
|
# Ensure output directory exists
|
|
|
|
|
|
mkdir -p "$(dirname "$OUT")"
|
2025-08-31 06:22:48 +09:00
|
|
|
|
echo "[4/4] Linking $OUT ..."
|
|
|
|
|
|
cc "$OBJ" \
|
2025-12-18 09:13:23 +09:00
|
|
|
|
-L "$CARGO_TARGET_DIR_EFFECTIVE/release" \
|
2025-09-24 12:57:33 +09:00
|
|
|
|
-L crates/nyash_kernel/target/release \
|
|
|
|
|
|
-Wl,--whole-archive -lnyash_kernel -Wl,--no-whole-archive \
|
2025-08-31 06:22:48 +09:00
|
|
|
|
-lpthread -ldl -lm -o "$OUT"
|
|
|
|
|
|
|
|
|
|
|
|
echo "✅ Done: $OUT"
|
|
|
|
|
|
echo " (runtime requires nyash.toml and plugin .so per config)"
|