magic/scripts/magic_run_common.sh.in

172 lines
8.9 KiB
Bash
Raw Normal View History

build: add run_magic*.sh launchers to run magic from the build tree Four configure-generated launch scripts let you run magic straight from the build directory without `make install`: * run_magic.sh -- GUI magic (Cairo/X11) * run_magicnull.sh -- batch / no-GUI (-dnull) * run_magic_gdb.sh -- magic under gdb * run_magic_valgrind.sh -- magic under valgrind magic resolves its runtime files through a single $CAD_ROOT root ($CAD_ROOT/magic/{sys,tcl}), but in the build tree they are scattered across build/ (generated tech, .magicrc, magic.tcl, tclmagic, execs) and source/ (colormaps, dstyles, glyphs, fonts, tcl scripts). On first run each launcher self-stages ${builddir}/CAD_DIR as a symlink tree in that layout (no copies, always current) via the shared scripts/magic_run_common.sh, exports CAD_ROOT=${builddir}/CAD_DIR, and execs the right binary. This pairs with the preceding commit that made the C launchers honor CAD_ROOT. magic_stage() is idempotent and re-runs on every launch. Most staged entries are files, but the bitmaps entry links a *directory*, so it uses `ln -sfn` (--no-dereference; also accepted by BSD ln): a plain `ln -sf` would, on a second run, dereference the existing symlink-to-directory and drop the new link *inside* the target -- a magic/bitmaps/bitmaps self-loop in the source tree that trips up find/tar/cp -r. Verified: ./run_magicnull.sh self-stages (30 sys + 24 tcl symlinks) and runs -- `tech load scmos` reports 13 planes -- straight from the build dir. gitignore covers the generated scripts and the CAD_DIR tree. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-24 00:06:28 +02:00
# Shared setup for the run_magic* launchers -- sourced, not run directly.
#
# Generated by configure from scripts/magic_run_common.sh.in. It stages a
# CAD_ROOT directory of *symlinks* into the build (generated) and source trees --
# the same layout `make install` copies, but instantly and always reflecting the
# latest build -- and exports the environment magic needs to start straight from
# the build tree without `make install`.
#
# See magic's runtime file discovery: MAGIC_SYS_PATH = ". $CAD_ROOT/magic/sys
# $CAD_ROOT/magic/sys/current" (utils/paths.h) for tech/glyphs/fonts/styles, the
# system .magicrc at $CAD_ROOT/magic/sys/.magicrc, and (since tcltk/tcldir.h)
# magic.tcl / tclmagic / auto_path at $CAD_ROOT/magic/tcl.
#
# ---------------------------------------------------------------------------
# Environment overrides (every value below can be pre-set in the environment;
# each is initialized with ${VAR:-<default>} so the caller's value wins):
#
# CAD_ROOT Root of the staged runtime tree. Default: the build tree's
# own $builddir/CAD_DIR (a directory of symlinks, created on
# first run). Point it elsewhere to reuse a shared/installed
# tree instead of staging one.
# MAGIC_WISH The "wish" binary magic uses for the Tk console. Default:
# WISH, i.e. the wish detected by configure to match the Tcl/Tk
# this build linked against (--with-tk / --with-wish). A build
# against a non-standard Tk therefore uses the correct absolute
# wish automatically; override to force a different one.
# WISH Same as above; MAGIC_WISH defaults from it. Baked default is
# the configure-detected wish (may be empty on a --disable-tcl
# build -- the launchers use the self-contained magicexec and do
# not require an external wish).
# TCLSH tclsh matching this build's Tcl (--with-tcl). Provided for
# convenience/diagnostics; may be empty if configure found none.
# MAGIC_BUILDDIR Absolute build-tree top. Default: baked @abs_top_builddir@.
# MAGIC_SRCDIR Absolute source-tree top. Default: baked @abs_top_srcdir@.
#
# Any value that is inherited from the environment (or a baked default that no
# longer resolves) is sanity-checked below; problems are reported on stderr as
# non-fatal warnings to aid diagnosis -- see magic_check_env().
# ---------------------------------------------------------------------------
build: add run_magic*.sh launchers to run magic from the build tree Four configure-generated launch scripts let you run magic straight from the build directory without `make install`: * run_magic.sh -- GUI magic (Cairo/X11) * run_magicnull.sh -- batch / no-GUI (-dnull) * run_magic_gdb.sh -- magic under gdb * run_magic_valgrind.sh -- magic under valgrind magic resolves its runtime files through a single $CAD_ROOT root ($CAD_ROOT/magic/{sys,tcl}), but in the build tree they are scattered across build/ (generated tech, .magicrc, magic.tcl, tclmagic, execs) and source/ (colormaps, dstyles, glyphs, fonts, tcl scripts). On first run each launcher self-stages ${builddir}/CAD_DIR as a symlink tree in that layout (no copies, always current) via the shared scripts/magic_run_common.sh, exports CAD_ROOT=${builddir}/CAD_DIR, and execs the right binary. This pairs with the preceding commit that made the C launchers honor CAD_ROOT. magic_stage() is idempotent and re-runs on every launch. Most staged entries are files, but the bitmaps entry links a *directory*, so it uses `ln -sfn` (--no-dereference; also accepted by BSD ln): a plain `ln -sf` would, on a second run, dereference the existing symlink-to-directory and drop the new link *inside* the target -- a magic/bitmaps/bitmaps self-loop in the source tree that trips up find/tar/cp -r. Verified: ./run_magicnull.sh self-stages (30 sys + 24 tcl symlinks) and runs -- `tech load scmos` reports 13 planes -- straight from the build dir. gitignore covers the generated scripts and the CAD_DIR tree. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-24 00:06:28 +02:00
# Record which values the caller supplied (vs. the configure-baked default) so
# diagnostics can name the origin, then fall back to the baked-in defaults.
# ${VAR+x} is "x" only when VAR is already set -- safe under `set -u`.
_origin_MAGIC_BUILDDIR="build default"; [ -n "${MAGIC_BUILDDIR+x}" ] && _origin_MAGIC_BUILDDIR=environment
_origin_MAGIC_SRCDIR="build default"; [ -n "${MAGIC_SRCDIR+x}" ] && _origin_MAGIC_SRCDIR=environment
_origin_CAD_ROOT="build default"; [ -n "${CAD_ROOT+x}" ] && _origin_CAD_ROOT=environment
_origin_WISH="build default"; [ -n "${WISH+x}" ] && _origin_WISH=environment
_origin_MAGIC_WISH="build default"; [ -n "${MAGIC_WISH+x}" ] && _origin_MAGIC_WISH=environment
_origin_TCLSH="build default"; [ -n "${TCLSH+x}" ] && _origin_TCLSH=environment
build: add run_magic*.sh launchers to run magic from the build tree Four configure-generated launch scripts let you run magic straight from the build directory without `make install`: * run_magic.sh -- GUI magic (Cairo/X11) * run_magicnull.sh -- batch / no-GUI (-dnull) * run_magic_gdb.sh -- magic under gdb * run_magic_valgrind.sh -- magic under valgrind magic resolves its runtime files through a single $CAD_ROOT root ($CAD_ROOT/magic/{sys,tcl}), but in the build tree they are scattered across build/ (generated tech, .magicrc, magic.tcl, tclmagic, execs) and source/ (colormaps, dstyles, glyphs, fonts, tcl scripts). On first run each launcher self-stages ${builddir}/CAD_DIR as a symlink tree in that layout (no copies, always current) via the shared scripts/magic_run_common.sh, exports CAD_ROOT=${builddir}/CAD_DIR, and execs the right binary. This pairs with the preceding commit that made the C launchers honor CAD_ROOT. magic_stage() is idempotent and re-runs on every launch. Most staged entries are files, but the bitmaps entry links a *directory*, so it uses `ln -sfn` (--no-dereference; also accepted by BSD ln): a plain `ln -sf` would, on a second run, dereference the existing symlink-to-directory and drop the new link *inside* the target -- a magic/bitmaps/bitmaps self-loop in the source tree that trips up find/tar/cp -r. Verified: ./run_magicnull.sh self-stages (30 sys + 24 tcl symlinks) and runs -- `tech load scmos` reports 13 planes -- straight from the build dir. gitignore covers the generated scripts and the CAD_DIR tree. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-24 00:06:28 +02:00
MAGIC_BUILDDIR="${MAGIC_BUILDDIR:-@abs_top_builddir@}"
MAGIC_SRCDIR="${MAGIC_SRCDIR:-@abs_top_srcdir@}"
SHDLIB_EXT="${SHDLIB_EXT:-@SHDLIB_EXT@}"
CAD_ROOT="${CAD_ROOT:-${MAGIC_BUILDDIR}/CAD_DIR}"
build: add run_magic*.sh launchers to run magic from the build tree Four configure-generated launch scripts let you run magic straight from the build directory without `make install`: * run_magic.sh -- GUI magic (Cairo/X11) * run_magicnull.sh -- batch / no-GUI (-dnull) * run_magic_gdb.sh -- magic under gdb * run_magic_valgrind.sh -- magic under valgrind magic resolves its runtime files through a single $CAD_ROOT root ($CAD_ROOT/magic/{sys,tcl}), but in the build tree they are scattered across build/ (generated tech, .magicrc, magic.tcl, tclmagic, execs) and source/ (colormaps, dstyles, glyphs, fonts, tcl scripts). On first run each launcher self-stages ${builddir}/CAD_DIR as a symlink tree in that layout (no copies, always current) via the shared scripts/magic_run_common.sh, exports CAD_ROOT=${builddir}/CAD_DIR, and execs the right binary. This pairs with the preceding commit that made the C launchers honor CAD_ROOT. magic_stage() is idempotent and re-runs on every launch. Most staged entries are files, but the bitmaps entry links a *directory*, so it uses `ln -sfn` (--no-dereference; also accepted by BSD ln): a plain `ln -sf` would, on a second run, dereference the existing symlink-to-directory and drop the new link *inside* the target -- a magic/bitmaps/bitmaps self-loop in the source tree that trips up find/tar/cp -r. Verified: ./run_magicnull.sh self-stages (30 sys + 24 tcl symlinks) and runs -- `tech load scmos` reports 13 planes -- straight from the build dir. gitignore covers the generated scripts and the CAD_DIR tree. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-24 00:06:28 +02:00
export CAD_ROOT
MAGIC_SYS="${CAD_ROOT}/magic/sys"
MAGIC_TCL="${CAD_ROOT}/magic/tcl"
# wish/tclsh that match the Tcl/Tk this tree was configured against.
WISH="${WISH:-@WISH_EXE@}"
TCLSH="${TCLSH:-@TCLSH_EXE@}"
# tkcon.tcl launches the console via ${MAGIC_WISH:=wish}; hand it the matching one.
MAGIC_WISH="${MAGIC_WISH:-$WISH}"
[ -n "$MAGIC_WISH" ] && export MAGIC_WISH
# One warning helper for all launchers.
magic_warn() { printf 'run_magic: warning: %s\n' "$*" >&2; }
# _magic_check NAME KIND ORIGIN VALUE
# KIND: mustdir -- must exist and be a directory
# newdir -- may be absent (created later); if present must be a directory
# exec -- must exist, be a regular file, and be executable
# optexec -- empty is fine (feature not configured); else same as exec
_magic_check() {
_n="$1"; _k="$2"; _o="$3"; _v="$4"
case "$_k" in
optexec) [ -n "$_v" ] || return 0; _k=exec ;;
esac
case "$_k" in
mustdir)
[ -d "$_v" ] || magic_warn "\$$_n ($_o) = '$_v' is not a directory (build tree moved or removed?)" ;;
newdir)
{ [ ! -e "$_v" ] || [ -d "$_v" ]; } || \
magic_warn "\$$_n ($_o) = '$_v' exists but is not a directory" ;;
exec)
if [ ! -e "$_v" ]; then
magic_warn "\$$_n ($_o) = '$_v' does not exist"
elif [ ! -f "$_v" ]; then
magic_warn "\$$_n ($_o) = '$_v' is not a regular file"
elif [ ! -x "$_v" ]; then
magic_warn "\$$_n ($_o) = '$_v' is not executable"
fi ;;
esac
}
# Validate the (possibly environment-inherited) configuration and warn -- never
# fail -- on anything that looks wrong, so a bad override is easy to spot.
magic_check_env() {
_magic_check MAGIC_BUILDDIR mustdir "$_origin_MAGIC_BUILDDIR" "$MAGIC_BUILDDIR"
_magic_check MAGIC_SRCDIR mustdir "$_origin_MAGIC_SRCDIR" "$MAGIC_SRCDIR"
_magic_check CAD_ROOT newdir "$_origin_CAD_ROOT" "$CAD_ROOT"
_magic_check WISH optexec "$_origin_WISH" "$WISH"
# MAGIC_WISH defaults from WISH; only check it separately when it diverges
# (an explicit MAGIC_WISH override) to avoid a duplicate warning.
[ "$MAGIC_WISH" = "$WISH" ] || \
_magic_check MAGIC_WISH optexec "$_origin_MAGIC_WISH" "$MAGIC_WISH"
_magic_check TCLSH optexec "$_origin_TCLSH" "$TCLSH"
}
build: add run_magic*.sh launchers to run magic from the build tree Four configure-generated launch scripts let you run magic straight from the build directory without `make install`: * run_magic.sh -- GUI magic (Cairo/X11) * run_magicnull.sh -- batch / no-GUI (-dnull) * run_magic_gdb.sh -- magic under gdb * run_magic_valgrind.sh -- magic under valgrind magic resolves its runtime files through a single $CAD_ROOT root ($CAD_ROOT/magic/{sys,tcl}), but in the build tree they are scattered across build/ (generated tech, .magicrc, magic.tcl, tclmagic, execs) and source/ (colormaps, dstyles, glyphs, fonts, tcl scripts). On first run each launcher self-stages ${builddir}/CAD_DIR as a symlink tree in that layout (no copies, always current) via the shared scripts/magic_run_common.sh, exports CAD_ROOT=${builddir}/CAD_DIR, and execs the right binary. This pairs with the preceding commit that made the C launchers honor CAD_ROOT. magic_stage() is idempotent and re-runs on every launch. Most staged entries are files, but the bitmaps entry links a *directory*, so it uses `ln -sfn` (--no-dereference; also accepted by BSD ln): a plain `ln -sf` would, on a second run, dereference the existing symlink-to-directory and drop the new link *inside* the target -- a magic/bitmaps/bitmaps self-loop in the source tree that trips up find/tar/cp -r. Verified: ./run_magicnull.sh self-stages (30 sys + 24 tcl symlinks) and runs -- `tech load scmos` reports 13 planes -- straight from the build dir. gitignore covers the generated scripts and the CAD_DIR tree. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-24 00:06:28 +02:00
# (Re)build the symlink layout. Idempotent; `ln -sf` relinks so a rebuilt target
# is always current. Missing globs (a partial build) are tolerated.
magic_stage() {
local b="$MAGIC_BUILDDIR" s="$MAGIC_SRCDIR"
mkdir -p "$MAGIC_SYS" "$MAGIC_TCL"
# --- sys/ : generated tech (build) + display files/glyphs/fonts (source) ---
ln -sf "$b"/scmos/*.tech "$MAGIC_SYS"/ 2>/dev/null || :
ln -sf "$s"/scmos/*.cmap "$s"/scmos/*dstyle "$MAGIC_SYS"/ 2>/dev/null || :
ln -sf "$s"/windows/*.glyphs "$s"/windows/vfont.* "$MAGIC_SYS"/ 2>/dev/null || :
ln -sf "$s"/graphics/*.glyphs "$s"/graphics/*.pt3 "$MAGIC_SYS"/ 2>/dev/null || :
ln -sf "$b"/magic/proto.magicrc "$MAGIC_SYS"/.magicrc 2>/dev/null || :
ln -sf "$b"/magic/proto.initrc "$MAGIC_SYS"/.initrc 2>/dev/null || :
if [ -f "$b"/magic/magicps.pro ]; then
ln -sf "$b"/magic/magicps.pro "$MAGIC_SYS"/ 2>/dev/null || :
else
ln -sf "$s"/magic/magicps.pro "$MAGIC_SYS"/ 2>/dev/null || :
fi
# --- tcl/ : source scripts + generated magic.tcl + .so + execs + bitmaps ---
ln -sf "$s"/tcltk/*.tcl "$MAGIC_TCL"/ 2>/dev/null || :
ln -sf "$b"/tcltk/magic.tcl "$MAGIC_TCL"/ 2>/dev/null || :
ln -sf "$b"/magic/tclmagic${SHDLIB_EXT} "$MAGIC_TCL"/ 2>/dev/null || :
ln -sf "$b"/tcltk/magicexec "$b"/tcltk/magicdnull "$MAGIC_TCL"/ 2>/dev/null || :
# bitmaps is a *directory*: use -n so a re-stage replaces the existing
# symlink instead of dereferencing it and dropping a self-link *inside* the
# source tree (magic/bitmaps/bitmaps -> .../magic/bitmaps).
ln -sfn "$s"/magic/bitmaps "$MAGIC_TCL"/bitmaps 2>/dev/null || :
}
# Split a launcher's argv on the first "--":
# <tool-opts...> -- <magic-args...>
# Everything before "--" is for the wrapper tool (gdb/valgrind); everything after
# is magic's. With no "--" present, ALL arguments are treated as magic's -- the
# common case where no tool options are needed. Results are returned in the
# arrays MAGIC_TOOL_OPTS and MAGIC_ARGS.
magic_split_args() {
MAGIC_TOOL_OPTS=()
MAGIC_ARGS=()
local seen=0 a
for a in "$@"; do
if [ "$seen" -eq 0 ] && [ "$a" = "--" ]; then seen=1; continue; fi
if [ "$seen" -eq 1 ]; then MAGIC_ARGS+=("$a"); else MAGIC_TOOL_OPTS+=("$a"); fi
done
if [ "$seen" -eq 0 ]; then
MAGIC_ARGS=(${MAGIC_TOOL_OPTS[@]+"${MAGIC_TOOL_OPTS[@]}"})
MAGIC_TOOL_OPTS=()
fi
}
build: add run_magic*.sh launchers to run magic from the build tree Four configure-generated launch scripts let you run magic straight from the build directory without `make install`: * run_magic.sh -- GUI magic (Cairo/X11) * run_magicnull.sh -- batch / no-GUI (-dnull) * run_magic_gdb.sh -- magic under gdb * run_magic_valgrind.sh -- magic under valgrind magic resolves its runtime files through a single $CAD_ROOT root ($CAD_ROOT/magic/{sys,tcl}), but in the build tree they are scattered across build/ (generated tech, .magicrc, magic.tcl, tclmagic, execs) and source/ (colormaps, dstyles, glyphs, fonts, tcl scripts). On first run each launcher self-stages ${builddir}/CAD_DIR as a symlink tree in that layout (no copies, always current) via the shared scripts/magic_run_common.sh, exports CAD_ROOT=${builddir}/CAD_DIR, and execs the right binary. This pairs with the preceding commit that made the C launchers honor CAD_ROOT. magic_stage() is idempotent and re-runs on every launch. Most staged entries are files, but the bitmaps entry links a *directory*, so it uses `ln -sfn` (--no-dereference; also accepted by BSD ln): a plain `ln -sf` would, on a second run, dereference the existing symlink-to-directory and drop the new link *inside* the target -- a magic/bitmaps/bitmaps self-loop in the source tree that trips up find/tar/cp -r. Verified: ./run_magicnull.sh self-stages (30 sys + 24 tcl symlinks) and runs -- `tech load scmos` reports 13 planes -- straight from the build dir. gitignore covers the generated scripts and the CAD_DIR tree. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-24 00:06:28 +02:00
# Fail early with a clear message if the build has not produced the binaries yet.
magic_require_built() {
if [ ! -x "$MAGIC_BUILDDIR/tcltk/magicexec" ] && \
[ ! -x "$MAGIC_BUILDDIR/tcltk/magicdnull" ]; then
echo "error: magic is not built yet -- run 'make' in ${MAGIC_BUILDDIR} first." >&2
exit 1
fi
}
# Validate the environment as soon as this file is sourced (warnings only).
magic_check_env