Merge pull request #305 from jolt-lang/fix-jolt-trace-aot-binary

JOLT_TRACE: honor the env at runtime in a built joltc
This commit is contained in:
Dmitri Sotnikov 2026-07-04 20:51:03 +00:00 committed by GitHub
commit e297a74501
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 31 additions and 10 deletions

View file

@ -145,11 +145,10 @@
(scheme-start (scheme-start
(lambda args (lambda args
(set-source-roots! (list \"jolt-core\" \"stdlib\")) (set-source-roots! (list \"jolt-core\" \"stdlib\"))
(guard (v (#t (jolt-report-throwable v (current-error-port)) ;; JOLT_TRACE at RUNTIME (the env is unset at heap-build), before any app ns
(let ((bt (jolt-backtrace-string v))) ;; compiles, so a `-M:run` traces the app's own code.
(when bt (display \" trace:\\n\" (current-error-port)) (jolt-trace-init-from-env!)
(display bt (current-error-port)))) (guard (v (#t (jolt-report-throwable v (current-error-port)) (exit 1)))
(exit 1)))
(cond (cond
((and (= (length args) 2) (string=? (car args) \"-e\")) ((and (= (length args) 2) (string=? (car args) \"-e\"))
(let ((result (jolt-final-str (let ((result (jolt-final-str

View file

@ -66,6 +66,9 @@
(when bt (display " trace:\n" port) (display bt port))) (when bt (display " trace:\n" port) (display bt port)))
(exit 1))) (exit 1)))
;; JOLT_TRACE opt-in, at runtime (before any app ns compiles) so the app is traced.
(jolt-trace-init-from-env!)
(guard (v (#t (jolt-report-uncaught v))) (guard (v (#t (jolt-report-uncaught v)))
(cond (cond
;; -e EXPR — evaluate one expression and print it (blank for nil). Wrapped in ;; -e EXPR — evaluate one expression and print it (blank for nil). Wrapped in

View file

@ -132,11 +132,16 @@
;; push is baked in at compile time, only code compiled after this call is traced — ;; push is baked in at compile time, only code compiled after this call is traced —
;; which is exactly the code you eval / reload in a live session. ;; which is exactly the code you eval / reload in a live session.
(def-var! "jolt.host" "enable-trace!" jolt-enable-trace!) (def-var! "jolt.host" "enable-trace!" jolt-enable-trace!)
;; Explicit opt-in for a whole run (JOLT_TRACE=1): enable at load, BEFORE any app ;; Explicit opt-in for a whole run (JOLT_TRACE=1): turn tracing on BEFORE any app
;; namespace is compiled, so a plain `-M:run` traces the app's own code too. Only an ;; namespace is compiled, so a plain `-M:run` traces the app's own code too. Called
;; affirmative value (set, non-empty, not falsey) forces it on here. ;; from the runtime entrypoints (cli.ss, and the built joltc launcher) — NOT at load
(let ((e (getenv "JOLT_TRACE"))) ;; time: a built joltc runs top-level forms at heap-build time, where JOLT_TRACE is
(when (and e (fx>? (string-length e) 0) (not (jolt-trace-env-off? e))) (jolt-enable-trace!))) ;; always unset, so a load-time check would never see the user's runtime env. Only an
;; affirmative value (set, non-empty, not falsey) forces it on.
(define (jolt-trace-init-from-env!)
(let ((e (getenv "JOLT_TRACE")))
(when (and e (fx>? (string-length e) 0) (not (jolt-trace-env-off? e)))
(jolt-enable-trace!))))
;; (with-meta sym m) -> sym, else x — an (ns ^:no-doc name …) yields the name with ;; (with-meta sym m) -> sym, else x — an (ns ^:no-doc name …) yields the name with
;; reader metadata as a with-meta form; strip it to read the bare ns symbol. ;; reader metadata as a with-meta form; strip it to read the bare ns symbol.

View file

@ -42,6 +42,20 @@ if [ "$got_e" != "45" ]; then
exit 1 exit 1
fi fi
# 2b. JOLT_TRACE must take effect in the BUILT binary. The env check runs at
# runtime (the launcher), NOT at heap-build where JOLT_TRACE is always unset — so
# an uncaught error shows a tail-frame trace recovering the TCO-elided chain, and
# exactly ONE trace block (the launcher must not double-print it).
got_tr="$(env -i HOME="$HOME" JOLT_TRACE=1 "$joltc" -e '(defn a [x] (+ x 1)) (defn b [x] (a x)) (b :x)' 2>&1)"
if ! printf '%s' "$got_tr" | grep -q ' trace:' || ! printf '%s' "$got_tr" | grep -q 'b'; then
echo " FAIL: JOLT_TRACE=1 in the built joltc produced no tail-frame trace"
echo "--- got ---"; echo "$got_tr"; exit 1
fi
if [ "$(printf '%s' "$got_tr" | grep -c ' trace:')" != "1" ]; then
echo " FAIL: built joltc double-printed the trace block"
echo "--- got ---"; echo "$got_tr"; exit 1
fi
# 3. Build an app through the distributed joltc with an EMPTY environment — no # 3. Build an app through the distributed joltc with an EMPTY environment — no
# PATH at all, so no chez, no cc, no shell tools are reachable. This is the core # PATH at all, so no chez, no cc, no shell tools are reachable. This is the core
# guarantee: joltc compiles apps entirely on its own. # guarantee: joltc compiles apps entirely on its own.