new "plane" property type (which apparently was not previously
documented when implemented, an oversight), and also (added by
request) to add a reminder that the "MASKHINTS" property only works
in conjunction with corresponding "mask-hints" records in the tech
file.
list in "extresist". This was previously done when a device
terminal could not be found and defaults to its original node
name, but apparently the port itself can get disconnected from
the rest of the net, which needs to be thoroughly investigated.
See the issue that was posted in the netgen issue tracker
(issue #108) by Simon Dorrer.
tech file setup results in a residue mask for a contact that includes
the contact type itself. Therefore in ResMain.c, FindStartTile()
ends up calling itself with the same arguments, ensuring an infinite
loop. It is easy enough to reject the recursive call if the residue
type equals the original type. The question of how a contact residue
mask ended up with the contact type as part of it is not addressed by
this fix, and may not have any other consequences.
coefficient from the calculation to the tech file parser (done once
instead of done many times), and corrected the included (old) SCMOS
tech files to use the new "standard" coefficient values.
(1) Corrections to the R-C extraction code to better handle nodes
which have the recorded position at the corner of a split tile.
(2) Corrected "select area label" to prevent accidentally selecting
unexpanded instances in the area. Also corrects an issue with
not being able to select labels that are attached to "space".
(3) Changed the way that magic interprets the "sidewall" coefficient
so that it is entered into the tech file as the actual sidewall
coefficient instead of being half the value to correct for
magic's double counting of edges. The correction is instead
done when parsing the tech file. This measure was taken because
the open PDK values generated by "capiche" were not halving the
value, so I either change magic or I change all the tech files.
committed by Darryl Miles in PR #546 and #547 (changes to enable
in-tree building, although there are numerous other changes here,
including removing the clunky Depend method and removing the copy
of readline source in the code base).
The gdb and valgrind launchers previously passed every argument straight to
magic, leaving no way to give the tool its own options. Add a "--" split
(shared magic_split_args helper): arguments before "--" go to gdb/valgrind,
arguments after go to magic; with no "--", all arguments go to magic (the
common case). Examples:
./run_magic_gdb.sh -tui -ex run -- -dnull foo.mag
./run_magic_valgrind.sh --tool=callgrind -- foo.mag
Also make the tool binary and its default options overridable from the
environment: GDB/GDB_OPTS and VALGRIND/VALGRIND_OPTS (valgrind defaults to
--leak-check=full --error-exitcode=0), and warn if the tool is not on PATH.
Smoke-tested against a live X display: gdb runs magic to a clean exit and
valgrind produces a Memcheck report; option routing verified (a bogus flag
after "--" is rejected by magic, not gdb), both headless (-dnull) and GUI.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Expand each run_magic*.sh header to state its purpose, usage, and the full set
of environment overrides. Initialize every knob with ${VAR:-default} so a value
inherited from the environment always wins:
- CAD_ROOT is now overridable (was hardwired to $builddir/CAD_DIR); point it at
a shared/installed tree to skip staging.
- WISH/TCLSH default to the wish/tclsh configure detected for this build's
Tcl/Tk (@WISH_EXE@/@TCLSH_EXE@, matching --with-tk/--with-tcl), so a build
against a non-standard Tcl/Tk automatically uses the correct absolute paths.
MAGIC_WISH (what tkcon.tcl uses for the Tk console) defaults from WISH.
Add magic_check_env(): on source, sanity-check each value (directory / regular
file / executable, as appropriate) and print a non-fatal stderr warning naming
the offending variable and whether it came from the environment or the baked
default -- to make a bad override easy to diagnose. Empty optional values
(e.g. no tclsh configured) and a not-yet-created CAD_ROOT are not flagged.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>
magicexec.c, magicdnull.c and tclmagic.c hardwired the compile-time TCL_DIR
(the install location) when locating magic.tcl (tcl_rcFileName) and the Tcl
auto_path. So even with CAD_ROOT set -- the documented relocation knob, already
honored by the sys-file search and by tcltk/magic.sh's
TCL_MAG_DIR=${CAD_ROOT}/magic/tcl -- the C launchers still looked in the baked
install path, which is why magic could not source its startup from a relocated
install or a build tree.
Add tcltk/tcldir.h with a MagicTclDir() helper: $CAD_ROOT/magic/tcl when CAD_ROOT
is set and non-empty, else the compile-time TCL_DIR. Use it in all three sites.
This makes the C side consistent with the shell wrappers and with how magic.tcl
itself already derives its own directory (from `info script`).
Verified: default (no CAD_ROOT) resolves to TCL_DIR as before (build rc=0); with
CAD_ROOT pointed at a staged build tree, `magicdnull -dnull` sources magic.tcl
from there and runs (tech load scmos -> 13 planes).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Delete readline/ (the vendored GNU readline 4.3, ~104 files / 2 MB) now that
configure requires the system readline (Patch 1) and the Makefiles no longer
wire the bundled build (Patch 2). Sweep the remaining references:
* commands/Makefile.in: drop the `module: ${MAGICDIR}/readline/readline` rule
and the readline-create-symlinks delegation (bundled-only; commands now uses
the default `module: libcommands.o`).
* commands/CmdFI.c, textio/txMain.c, textio/txInput.c: the readline includes
had a `#ifdef HAVE_READLINE <system> #else "readline/readline/*.h" (bundled)`
split. HAVE_READLINE/NEED_READLINE are used nowhere else and USE_READLINE now
always implies the system library, so collapse to the plain
`#include <readline/readline.h>` / `<history.h>`.
* CI: main.yml's non-Tcl job installs libreadline-dev (was relying on bundled);
canary-matrix drops the now-invalid no_tk_tcl_brl / --enable-readline-bundled
variant.
* .gitignore: drop the "readline/ intentionally not converted" note.
Verified: Tcl -j12 builds+installs 375 files (commands builds, no readline-dir
references); --without-tcl --disable-readline -j12 builds (x2); --without-tcl with
no readline dev package still errors with the guidance message.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
With the bundled fallback gone (Patch 1) the readline/ special-casing is dead
machinery. Remove it:
* Makefile.in: $(submake) drops the `= readline` `-f`/mkdir branch and is now
plain `$(MAKE) -C <dir> <goal>`; the clean loop drops its matching branch;
`readline` is removed from BUNDLED_MODULES.
* scripts/defs.mak.in: remove the `ifeq (@MAKE_READLINE@,1) -I${MAGICSRC}/
readline` block (system readline headers are on the standard search path) and
the MAKE_READLINE variable; tidy the srcdir-fallback comment (only the
top-level Makefile uses it now).
* scripts/configure.in: drop AC_SUBST(MAKE_READLINE); regenerate configure.
The system readline link flags (rl_libs = -lreadline via READLINE_LIBS) are
unchanged. readline/ itself is deleted in the next patch.
Verified: no unsubstituted @MAKE_READLINE@; Tcl -j12 builds+installs 375 files
with readline/ not built; --without-tcl --disable-readline -j12 builds (x2).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
main@ depends on both `modules` and `libs`, so `module@X` (`make -C X module`)
and `lib@X` (`make -C X lib`) could run in the same directory concurrently under
-j and race on X's shared objects -- each %.o recipe does `rm $*.o; cc -c`, so
one make would delete/rebuild an object while the other was linking it, e.g.
`ld: cannot find touchtypes.o` while linking libutils.o. It was rare (timing
dependent) but real; it surfaced on a --without-tcl --disable-readline -j12 build.
Make `lib@%` depend on its own `module@%`: module@X builds the objects, lib@X
then only archives them, so the two never touch X's *.o at the same time.
Cross-directory parallelism is unchanged (lib@X waits only on module@X, not the
whole modules phase).
Verified: 4/4 clean --without-tcl -j12 builds pass (previously intermittently
failed); Tcl -j12 still builds 375 files.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
configure already preferred the system readline (AC_CHECK_LIB → -lreadline) and
only fell back to the bundled readline/ copy. Remove that fallback: a non-Tcl
interactive build now requires the *system* GNU readline -- both its header
(AC_CHECK_HEADER readline/readline.h, so configure fails cleanly instead of deep
in compilation) and the library -- and if neither Tcl nor readline is available
configure errors with a clear explanation of the three ways forward (build with
Tcl, install libreadline-dev, or --disable-readline).
Also drop the now-meaningless --enable-readline-bundled, and substitute
MAKE_READLINE=0 unconditionally so the Makefiles' bundled-readline path goes
inert. readline/ and all Makefiles are left untouched here (cleaned up and
removed in the following patches).
--disable-readline stays as the escape hatch: it just tells configure to ignore
the system readline and build the existing no-line-editing variant.
Verified: Tcl build rc=0 (readline off, 375 files, readline/ not built); non-Tcl
--disable-readline builds (serial); non-Tcl default with no readline dev package
now errors with the guidance message.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The build's SOURCE_DATE_EPOCH date handling auto-detects gdate/GNU date and
falls back to native BSD `date -r`, so coreutils is not a prerequisite (unlike
gnu-sed). Add an optional note so the reproducible-build audience knows it is
available but not needed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
MAGIC_VERSION/REVISION/COMMIT/BUILDDATE used `?=` with `$(shell ...)`, which
makes them recursively-expanded. Because they are exported, make re-evaluated
(re-spawned git/date/cat) every time it built a child's environment -- so a
no-op recursive `make` spawned git and date ~624 times each.
Guard each with `ifndef` and assign with `:=` (simply-expanded) so the value is
computed once at the top and exported as a plain string; sub-makes inherit it
and the ifndef skips recomputation. This was the last "fold in" item from the
buildinfo/ccache plan.
Verified: a no-op `make` now spawns git and date once each (was 624); a full
clean build spawns 1 git / 2 date / 10 cat; the commit is still embedded
correctly and builds are reproducible.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
npm/build.sh stripped CRs from configure and every scripts/ file before each
WASM build. Its purpose was purely to survive a Windows checkout with
core.autocrlf=true (which rewrites LF->CRLF, and bash/make then reject CRLF) --
not reproducible packaging. No tracked build input is CRLF today
(`git ls-files --eol` shows only the incidental appimage/rsc/magic.svg), so it
never fired on a normal checkout, and it mutated the source tree to do it.
Add .gitattributes `eol=lf` for configure, scripts/**, *.sh, *.mak, *.mak.in
and Makefile.in. Attributes override core.autocrlf, so git always checks these
out as LF regardless of platform -- the authoritative fix -- and the source tree
is never rewritten by the build. Remove sed_strip_cr and its call sites.
Verified: git check-attr reports eol=lf for configure/scripts/*/*.sh/rules.mak/
Makefile.in; build.sh parses cleanly.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The SOURCE_DATE_EPOCH -> date conversion previously relied on a runtime
`date -u -d @EPOCH 2>/dev/null || date -u -r EPOCH` fallback. That is
unreliable on macOS/*BSD: BSD `date -d` reads -d as a DST flag and silently
prints the wrong time (exit 0), so the `-r` fallback is never reached.
Decide at configure time instead: prefer coreutils `gdate` (GNU date, e.g.
installed on macOS), else a native `date` that really is GNU (verified by the
epoch-0 output containing 1970), else BSD `date -r`. configure substitutes the
chosen invocation as @SOURCE_DATE_CMD@ and defs.mak appends the epoch.
Verified on Linux (no gdate -> GNU `date -u -d @`): a fixed SOURCE_DATE_EPOCH
yields a byte-identical buildinfo.o across builds; the no-epoch path still
stamps the current local time.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
From an independent review of the branch:
* Makefile.in: `tcltk` is in both INSTALL_CAD_DIRS and PROGRAMS (Tcl build),
so install@tcltk / install-tcl@tcltk were defined twice -> "given more than
once" warnings on every command. Wrap both install lists in $(sort ...) to
dedup (as CLEAN_TARGETS already does). Also fix a stale comment (module@ now
waits for ${DATABASE_H}, not a `depend` phase).
* toolchains/emscripten/defs.mak: the scmos display-file embed globbed
`mos.*.dstyle`, which misses mos.7bit.mraster_dstyle (an underscore, not a
dot) -- so the mono-raster style was not embedded in WASM, and the comment
wrongly called that file non-existent. Glob `mos.*dstyle` to cover both.
* npm/build.sh: sed_strip_cr wrote the file back unconditionally, bumping the
mtimes of configure and every scripts/ file on each WASM build (contradicting
the "source never mutated" guarantee and able to force a coexisting native
rebuild). Only write back when a CR was actually stripped.
* graphics/Makefile.in: remove the dead DEPSRCS block left behind by retiring
the Depend machinery (it also referenced an undefined ${THREE_D_SRCS}).
* scripts/defs.mak.in: clarify that only the SOURCE_DATE_EPOCH branch is UTC.
Verified: 0 duplicate-target warnings, wildcard now lists mos.7bit.mraster_dstyle,
full Tcl build+install rc=0 (375 files), graphics lib builds, build.sh syntax OK.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
With per-file dependencies now generated during compilation (previous commit),
the serial `depend` phase and its barrier are obsolete. Drop SUBDIRS_DEPEND and
the `<dir>/Depend: ${DATABASE_H}` rule, and replace the `module@/lib@/tech@ %:
depend` prerequisite with `: ${DATABASE_H}` -- the only real ordering constraint
is the generated header, not a whole dependency-scanning pass. Modules therefore
start compiling in parallel immediately instead of waiting for every subdir's
deps to be scanned first.
`make depend` is kept as a top-level no-op (the WASM build script still calls
`emmake make depend`).
Verified out-of-tree serial and -j12 and in-tree -j12: rc=0, 375 files, serial
and -j installs byte-identical, zero Depend files, source tree clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the monolithic per-directory `Depend` file -- generated by a separate,
serial `make depend` pass (one `gcc -MM` over all sources) and post-processed by
sed -- with automake-style per-file dependency fragments produced as a side
effect of each compile.
rules.mak's %.o rule now adds, when the compiler supports it,
-MMD -MP -MF .deps/<stem>.d
so every object records the (non-system) headers it used. Those fragments are
`-include`d best-effort: absent on a first build, present and correct after.
Benefits:
* self-maintaining -- no explicit depend step; deps refresh on every compile;
* parallel -- generated during the (already parallel) compile, no barrier;
* -MMD already drops system headers (what the sed did) and -MP tolerates a
removed/renamed header, so the sed post-processing is gone;
* fixes out-of-tree incremental header tracking: with an absolute srcdir the
old sed stripped the now-absolute *local* header paths too, silently losing
them; the .d files keep them.
configure probes `-MMD -MP` (AUTODEP_FLAGS; empty and best-effort-skipped if the
compiler cannot). clean/distclean remove .deps (rm -r); .gitignore replaces the
obsolete */Depend with .deps/. `make depend` is kept as a no-op for callers that
still invoke it (e.g. the WASM build script).
Verified out-of-tree (--disable-ccache): 324 .d files, 0 Depend files, a header
touch recompiles its dependents, no-op rebuild is idle, clean clears .deps. (The
top-level depend phase still runs here as a no-op; removed next.)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Add three configure options to the INSTALL option list:
* --disable-magic-builddate -- omit the build date for reproducible builds
(byte-identical objects for a given commit) and full ccache effectiveness.
* --disable-ccache -- opt out of the auto-detected ccache.
* --enable-ccache-prefix-map -- relativize embedded source paths for
cross-tree ccache sharing (off by default; note the debugger and
CCACHE_BASEDIR implications).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The out-of-tree build puts absolute source-root paths on the command line
(-I${MAGICSRC}, -I${srcdir}, the source file itself), which are part of
ccache's key -- so same-tree rebuilds hit (proven) but different checkouts /
build dirs do not share cache.
New opt-in configure --enable-ccache-prefix-map adds
-ffile-prefix-map=${MAGICSRC}=.
to CFLAGS (requires ccache; the flag is probed for GCC-8+/clang support and
skipped with a warning otherwise). This relativizes the source paths embedded
in the compiled output (__FILE__, debug info) so a cached object is valid
regardless of which tree produced it.
Off by default: it makes debug paths relative, so gdb then needs
`set substitute-path . <srcdir>`. It is only for cross-tree *correctness* and
must be paired with CCACHE_BASEDIR=<build top> in the environment for cross-tree
*hits* (that half normalizes the command-line paths in the hash; this half keeps
the cached output tree-neutral). Same-tree caching needs neither.
Verified: default/--disable-ccache carry no -ffile-prefix-map;
--enable-ccache-prefix-map (probe "yes") adds it, and with --disable-ccache it
warns and is ignored. Full build rc=0 (375 files); the installed tclmagic.so
contains zero absolute /work/magic paths.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When ccache is on PATH, prefix CC/CXX with it so every compile goes through
ccache -- no Makefile change, since rules.mak already runs `${CC} ... -c` and
defs.mak substitutes @CC@/@CXX@. Autodetected on by default; --disable-ccache
opts out.
Placed after the AC_PROG_C* checks so configure's own feature tests use the
plain compiler and only the build picks up the prefix. Pairs with the
build-info isolation (utils/buildinfo.c): with the volatile MAGIC_BUILDDATE on
only that one unit, a full rebuild hits the cache for every other unit.
Measured (default Tcl build, all objects deleted then rebuilt): 323/324 hits
with the date enabled (only buildinfo.o misses), 324/324 with
--disable-magic-builddate.
Verified: default configure -> CC="ccache gcc", CXX="ccache g++";
--disable-ccache -> CC="gcc".
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New configure option --disable-magic-builddate omits the build date from the
binary. It is wired via an AC_SUBST'd MAGIC_BUILDDATE_DEFS (not AC_DEFINE), so
it reaches only buildinfo.o rather than @DEFS@ / every command line:
* enabled (default): buildinfo.o gets -DMAGIC_BUILDDATE="<date>" and defs.mak
computes the date (SOURCE_DATE_EPOCH-aware);
* disabled: buildinfo.o gets -DMAGIC_NO_BUILDDATE instead, defs.mak skips the
date computation entirely (no parse-time `date` spawn), and buildinfo.c
reports an empty MagicCompileTime.
This gives a fully reproducible build whose one volatile input (the date) is
gone; what remains in buildinfo.o is commit/version/revision, which do not
change second-to-second -- the intended pairing with ccache for day-to-day
development.
Verified both configs: default bakes the date + commit; --disable-magic-builddate
compiles buildinfo.o with -DMAGIC_NO_BUILDDATE (no date), commit still present.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
MAGIC_BUILDDATE now derives from SOURCE_DATE_EPOCH (UTC) when it is set,
falling back to the current local time otherwise. This makes the date baked
into buildinfo.o reproducible for the appimage/npm tarballs (cf. npm/pack.sh,
which already normalizes mtimes).
Also add `2>/dev/null` to the MAGIC_COMMIT git call so a source tarball or a
non-work-tree ${MAGICSRC} yields an empty commit rather than a git error.
Only buildinfo.o consumes these (see the prior commit), so the shell still
runs at defs.mak parse time but affects just that one unit's define.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
MAGIC_VERSION / MAGIC_REVISION / MAGIC_COMMIT / MAGIC_BUILDDATE were on the
global DFLAGS, so every object's compile command line carried them. Because
the command line is part of ccache/sccache's hash key and MAGIC_BUILDDATE
changes every second, that meant a cache miss on every unit on every build;
it also smeared the baked-in date/commit across "whenever each file last
recompiled".
Move the four values into a single translation unit:
* utils/magic_buildinfo.h -- extern MagicVersion/MagicRevision/MagicCommit/
MagicCompileTime (MagicCommit is new; the other three moved here from
utils/magic.h, which now includes this header).
* utils/buildinfo.c -- the ONLY unit compiled with the version defines
(target-specific `buildinfo.o: DFLAGS += ${DFLAGS_MAGICVERSION}` in
utils/Makefile.in); it defines the four globals. ${DFLAGS_MAGICVERSION}
is removed from the global DFLAGS/DFLAGS_NOSTUB.
Consumers updated to read the runtime symbol instead of the compile-time
macro:
* magicTop.c / tclmagic.c no longer define the globals (the MAGIC_WRAPPER
duplicate-symbol guard is gone -- buildinfo.o owns them for every variant,
including WASM, which links both mains).
* Tcl_PkgProvide/PkgRequire in router/ext2spice/lef/ext2sim/plot/tclmagic
now pass MagicVersion.
* extflat: EFVersion (a static-initialized copy of MAGIC_VERSION) is dropped;
EFread.c compares the .ext version against MagicVersion directly -- the same
value ExtCell.c already *writes* into .ext files, so read and write are now
consistent.
Verified: only buildinfo.o carries -DMAGIC_* (hash/DBio/windCmdSZ carry none);
Tcl (375 files) and --without-tcl builds rc=0, version/commit/date embedded in
tclmagic.so, magicTop.o no longer defines MagicVersion; in-tree source clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The tcl smoke test writes generated artifacts to npm/examples/output-tcl/,
mirroring the already-ignored notcl npm/examples/output/. Ignore it too.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The WASM link embeds ${MAGICDIR}/scmos (the build tree) at the VFS sys dir,
which out of source holds only the *generated* tech files. A technology's
"styles" section (styletype mos) also needs the display styles and colour
maps -- scmos ${FILES}: mos.*.dstyle / mos.*.cmap -- which are *source*
files absent from the build tree. So magic_wasm_init failed:
Couldn't open color map file "mos.7bit.std.cmap"
... minimum.tech ... [styles] ... Cannot load technology "minimum"
(In-tree this never showed because build == source. It was also masked
until now behind the wasmBinary/INCOMING_MODULE_JS_API abort.)
Embed each display file from the source tree into the same VFS dir via
$(wildcard), which matches only files that exist -- so a stale/typo'd name
in ${FILES} (e.g. the non-existent mos.7bit.mraster_dstyle) can't break the
link.
Verified on emsdk 6.0.3, both variants: smoke tests now pass 4/4 (notcl)
and 5/5 (tcl).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Emscripten's default INCOMING_MODULE_JS_API list dropped `wasmBinary`
(present through ~4.x, gone by 6.0.x). With -sASSERTIONS=1 a caller that
sets Module.wasmBinary — as the npm harness and the documented API do —
then aborts at instantiation:
Aborted(`Module.wasmBinary` was supplied but `wasmBinary` not included
in INCOMING_MODULE_JS_API)
Set the list explicitly so the build no longer depends on Emscripten's
default (which drifts between emsdk versions). Allow the properties that
matter for embedding/consuming the .wasm across node/web/worker:
print, printErr stdout/stderr callbacks
wasmBinary, wasm supply the module as bytes / a compiled Module
instantiateWasm, locateFile custom instantiation (streaming/caching/
bundlers) and .wasm URL resolution
`arguments` is intentionally omitted: main() is defined but never run
(magic is driven through the magic_wasm_* exports), so argv is inert here.
Verified on emsdk 6.0.2 and 6.0.3: the wasmBinary abort is gone and the
module instantiates (0 INCOMING aborts in the smoke run on either).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Out-of-tree, doc/latexfiles points a build-tree ../psfigures at the source
copy so latex/dvips resolve ../psfigures/*.ps. The old
`test -e ../psfigures || ln -s ... ../psfigures` had two defects:
* Under a parallel docs build two .ps jobs could both see ../psfigures
absent and both run `ln -s`. The second `ln -s DIR symlink-to-dir`
nests the link *inside* the target, writing a stray
doc/psfigures/psfigures INTO THE SOURCE TREE -- an out-of-tree build
must never modify source.
* (An order-only make prerequisite is not a fix here: VPATH makes make
"find" ../psfigures in the source tree and skip creating the build link
latex actually needs.)
Use a shell test (VPATH-immune) that is both idempotent and race/nest safe:
`test -d ../psfigures || ln -sfn ${MAGICSRC}/doc/psfigures ../psfigures`.
`test -d` is true in-tree (real source dir) and once the build symlink
exists; `ln -sfn` (force + no-dereference) replaces an existing symlink in
place instead of nesting inside it.
Verified in/out of tree under -j12: 28/28 docs, correct single-level build
symlink, source tree never touched (in-tree psfigures stays a real dir).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
maint1.tex failed to build -- it was the one document that never
regenerated -- because of three source-level LaTeX errors, each masked by
the one before it:
* `gdb program $pid`: a bare `$` opens math mode (meant literally), which
was never closed, so `\endi` hit "Missing $ inserted" / Emergency stop.
Escaped to `\$pid`.
* `{\itshape process_ID}` (x2): a bare `_` is a math-mode subscript in
text. Escaped to `process\_ID`.
* a tabbing block (`\ii ps -C wish` before `\ii gdb ...`, and the
`gdb wish / run / set argc / set argv / source` block) was missing its
`\\` row separators, so multiple `\ii` (= \>\>\>) accumulated in one row
and overran the 4 tab stops -> "Undefined tab position". Added the
missing `\\`.
maint1 now compiles cleanly (two-pass, 0 errors) and `make all` in
doc/latexfiles produces 28/28 PostScript files instead of 27/28.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two fixes make a parallel `make -jN` deterministic:
1. lib@database: module@tiles module@utils. libdatabase.a physically
archives tiles/libtiles.o and utils/libutils.o (database/Makefile.in
LIB_OBJS +=), so lib@database must wait for those module objects. A
serial build got this from prerequisite order; under -j it was a latent
race (it happened to win most of the time because tiles/utils are quick).
Audited all Makefile.in: no other default-built module archives another
module's objects (magic's EXTRA_LIBS is covered by main@: modules libs;
the ext2*/router tools are not in the default build).
2. docs runs the doc/latexfiles sub-make with -j1. Those rules share
per-run .aux/.log files in one directory and are not parallel-safe;
under an inherited jobserver they raced and dropped documents (5-9 of 28
failed under -j vs 1 serial). Doc regeneration is best-effort (pre-built
PostScript is the install fallback), so forcing it serial costs nothing.
Verified: 5x clean out-of-tree `make -j12` all rc=0 with zero core-build
errors and a stable 27/28 docs; in-tree -j12 installs 375 files;
--without-tcl -j12 builds readline + magic. Serial behaviour unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the shell `for dir` loops and the FORCE pattern-rule hack with a
uniform per-directory PHONY target scheme: each (phase, dir) is a target
"<phase>@<dir>" that recurses into <dir> with that phase's goal via
$(submake), and each phase aggregate (depend, modules, libs, techs,
install, install-tcl, clean, mains, tcllibrary) is just the list of its
per-dir targets as prerequisites.
Inter-phase ordering moves from the aggregate onto the per-dir targets
(module@/lib@/tech@ each require `depend`; main@ requires modules+libs),
so the dependency graph is correct under `make -jN`, not only in a
left-to-right serial build. '@' is a safe namespace char (never in a real
target name). readline/ still takes the -f path inside $(submake).
The `depend` rule is left as real file targets (<dir>/Depend) so Depend is
still regenerated incrementally, not on every build. clean-mains loses its
one-iteration shell loop too.
The one cross-module edge (libdatabase.a needs tiles/utils modules first)
is preserved by prerequisite order for serial builds here; its explicit
-j edge is fixed in the following commit.
Verified serial rc=0, 375 files, identical installs in-tree and
out-of-tree; --without-tcl builds readline + magic.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
rules.mak has no @...@ substitutions, so there is no reason to copy it into
the build top. Point all 38 subdir Makefile.in includes at the source copy
directly -- ${MAGICSRC}/rules.mak instead of ${MAGICDIR}/rules.mak -- and
remove AC_CONFIG_FILES([rules.mak:rules.mak]) from configure. defs.mak (the
one make fragment with substitutions) remains the only generated file in the
build top. readline/ and the top Makefile never included rules.mak, so they
are unaffected; AC_CONFIG_SRCDIR(rules.mak) (the srcdir sentinel) is kept.
Now editing rules.mak in the source tree takes effect without reconfiguring.
Verified rc=0, 375 files, both in-tree and out-of-tree; out-of-tree build
top has no rules.mak; distclean rc=0.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Every converted module sets srcdir=@srcdir@ and VPATH=@srcdir@
before including defs.mak, so the full srcdir derivation is now reached
only by readline/ (never converted) and the top-level Makefile. Neither
compiles magic sources through the pattern rules, so neither needs VPATH.
Drop the MODULE_SUBPATH variable and the VPATH derivation; keep just a
one-line srcdir fallback so CPPFLAGS (-I${srcdir}) stays well-formed for
those two. BUILD_TOP is retained (GENINC still needs it).
Verified rc=0: out-of-tree Tcl (375) + in-tree Tcl (375, header present) +
out-of-tree --without-tcl (readline/libreadline.a + magic/magic built
through the fallback).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Every module is now a configure-generated Makefile, so the
generic "use -f if there is no build Makefile" fallback in $(submake) and
in the clean loop is only ever reached by readline/ (the one module that
is intentionally never converted).
Replace the generic `test -f $dir/Makefile` probe with an explicit
`$dir = readline` check: recurse natively everywhere, take the -f path
(against the source Makefile, creating the build subdir on demand) only
for readline. A converted module whose build Makefile is somehow missing
now fails loudly instead of silently falling back to -f.
Verified out-of-tree: default (Tcl) make+install+clean rc=0 (375 files);
--without-tcl make+clean rc=0 with readline/libreadline.a + magic/magic
built through the readline -f path.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The doc/html install tar'd the whole $(srcdir), so it shipped Makefile.in
(always) and, for an in-tree build, the config.status-generated Makefile,
into $CAD_ROOT/magic/doc/html/. That also made the install differ
in-tree (377 files) vs out-of-tree (376).
Exclude ./Makefile and ./Makefile.in from the tar. The install now
contains only the 148 HTML files (+ subdirs) and is identical in-tree and
out-of-tree (375 files).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Switch the 5 nested children (scmos/cif_template, doc/man, doc/tutcells,
doc/html, doc/latexfiles) to configure-provided substitution:
srcdir = @srcdir@
VPATH = @srcdir@
MAGICDIR = @top_builddir@ (resolves to ../.. for these nested dirs)
Verified out-of-tree: full `make` rc=0; cif_template gets
srcdir=<src>/scmos/cif_template, doc/latexfiles MAGICDIR=../..; scmos
techs + 27/28 docs build.
With this, every module except readline/ is a configure-generated
Makefile.in using @srcdir@ substitution.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Convert the last nested children to Makefile.in and switch their parents
from the -f fallback to native recursion (they now have generated build
Makefiles). Rename and rewire are one unit: a pure rename would break the
parent's -f path to the (now-.in) child.
Converted (5): scmos/cif_template, doc/man, doc/tutcells, doc/html,
doc/latexfiles. Pure renames -- still build via the srcdir derivation;
@srcdir@ substitution follows.
Rewired to native `make -C <child>` (config.status now creates the child
build dirs + Makefiles):
* scmos/Makefile.in: cif_template build + clean.
* doc/Makefile.in: install/install-tcl over man/tutcells/html/latexfiles.
* Makefile.in: the docs: target -> `make -k -C doc/latexfiles all`.
The `mkdir -p` and `-f ${MAGICSRC}/.../Makefile` are dropped in each.
* configure.in: AC_CONFIG_FILES for the 5 children; regenerated configure.
* .gitignore: ignore each generated child Makefile, same commit.
Verified out-of-tree: full `make && make install` rc=0, 376 files --
scmos recurses natively into cif_template (8 objs), docs regenerate via
native doc/latexfiles (27/28), man pages install via native doc/man.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Switch the 5 top-level outlier modules to configure-provided substitution
(same template as the rest):
srcdir = @srcdir@
VPATH = @srcdir@
MAGICDIR = @top_builddir@
Their custom rules and ${MAGICDIR}/${MAGICSRC} references keep working:
${MAGICDIR} = @top_builddir@ (build top), $(srcdir) now from @srcdir@.
scmos/doc still recurse into their (static) children via -f.
Verified out-of-tree: full `make` rc=0 -- magic gets srcdir=<src>/magic,
tclmagic.so + scmos techs + 27/28 docs build.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fourth batch of the Makefile.in migration: the top-level complex outliers
magic tcltk scmos doc lisp
Pure renames -- content unchanged, so each still builds via the defs.mak
srcdir derivation; the @srcdir@ substitution follows.
Their nested children (scmos/cif_template and doc/{man,tutcells,html,
latexfiles}) are intentionally NOT converted here: scmos and doc recurse
into them with `-f ${MAGICSRC}/.../Makefile`, which keeps working only
while those children remain static Makefiles. They convert in a later
step together with the parent-recursion updates.
* git mv <dir>/Makefile -> <dir>/Makefile.in (5 modules)
* configure.in: AC_CONFIG_FILES for each; regenerated configure.
* .gitignore: ignore each generated <dir>/Makefile, same commit.
Verified out-of-tree: full `make` rc=0 -- tclmagic.so, scmos techs (scmos
recurses into the static cif_template via -f, 8 objs), 27/28 docs.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Switch the 13 near-standard/outlier modules to configure-provided
substitution (same template as the standard modules):
srcdir = @srcdir@
VPATH = @srcdir@
MAGICDIR = @top_builddir@
Their sibling-object refs (${MAGICDIR}/<mod>/lib*.o) and custom rules are
unchanged: ${MAGICDIR} = @top_builddir@ (the build top) so the sibling
objects resolve into the build tree, and $(srcdir) now comes from
@srcdir@ instead of the derivation.
Verified out-of-tree: `make modules libs` builds all 33 module libraries;
the five Tcl auto-load libraries (magiclef.so, tclplot.so, tclroute.so,
exttospice.so, exttosim.so) link (sibling refs resolve to the build top).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Third batch of the Makefile.in migration: near-standard modules
(utils windows commands database) and the program/.so outliers
(lef plot router ext2spice ext2sim extcheck net2ir graphics oa).
Pure renames -- content unchanged, so each still builds via the defs.mak
srcdir derivation; the @srcdir@ substitution follows.
* git mv <dir>/Makefile -> <dir>/Makefile.in (13 modules)
* configure.in: AC_CONFIG_FILES for each; regenerated configure.
* .gitignore: ignore each generated <dir>/Makefile, same commit.
These modules carry sibling-object refs (${MAGICDIR}/<mod>/lib*.o) and
custom rules; those keep working unchanged (${MAGICDIR} = the build top,
$(srcdir) from the derivation). readline/ remains on the -f path.
Verified out-of-tree: config.status writes 35 module Makefiles (22 + 13);
`make modules libs` builds all 33 module libraries (rc=0).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Switch the 21 standard modules from the defs.mak srcdir derivation to
configure-provided substitution (same template as tiles):
srcdir = @srcdir@
VPATH = @srcdir@
MAGICDIR = @top_builddir@
defs.mak's dual-mode guard sees `srcdir` already set (origin=file) and
skips the srcdir derivation for these modules.
Verified out-of-tree: config.status writes srcdir=<src>/<mod> into each
build/<mod>/Makefile; `make modules libs` builds all 33 module libraries
(lib*.o + lib*.a, rc=0).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Second batch of the Makefile.in migration: the remaining standard modules
bplane calma cif cmwind dbwind debug drc extflat extract garouter gcr
grouter irouter mzrouter netmenu plow resis select sim textio wiring
Pure renames -- content unchanged, so each still builds via the defs.mak
srcdir derivation (dual mode); the @srcdir@ substitution follows.
* git mv <dir>/Makefile -> <dir>/Makefile.in (21 modules)
* configure.in: AC_CONFIG_FILES for each; regenerated configure. Their
build subdirs + Makefiles are now created by config.status, so
$(submake) recurses natively (make -C <dir>), no -f.
* .gitignore: ignore each generated <dir>/Makefile, in this same commit.
Verified out-of-tree: config.status writes 22 module Makefiles (these 21 +
tiles); `make modules` builds all 33 module libraries (rc=0).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Switch tiles from the defs.mak srcdir *derivation* to configure-provided
substitution:
srcdir = @srcdir@
VPATH = @srcdir@
MAGICDIR = @top_builddir@
defs.mak's dual-mode guard now sees `srcdir` already set (origin=file) and
skips the $(abspath)/$(patsubst) srcdir computation for this module.
Verified: config.status writes srcdir=<src>/tiles into build/tiles/Makefile;
make -C tiles module compiles from that srcdir (libtiles.o, rc=0) with the
derivation bypassed. This is the template the remaining modules follow.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
First module of the Makefile.in migration (proof). Pure rename: the
Makefile content is unchanged, so config.status just copies it and the
module still builds via the defs.mak srcdir *derivation* (dual mode from
phase 1) -- the @srcdir@ substitution is a separate follow-up.
* git mv tiles/Makefile -> tiles/Makefile.in
* configure.in: AC_CONFIG_FILES([tiles/Makefile:tiles/Makefile.in]);
regenerated configure. config.status now creates build/tiles/Makefile,
so $(submake) recurses into tiles natively (make -C tiles), no -f.
* .gitignore: ignore the generated tiles/Makefile (in-tree it lands in the
source tree) -- added in this same commit so it can never be committed.
Verified out-of-tree: config.status writes build/tiles/Makefile,
make -C tiles module builds libtiles.o (rc=0).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Enabler for the Makefile -> Makefile.in migration. No module is
converted yet; behaviour is identical.
* scripts/defs.mak.in: dual-mode. A module converted to Makefile.in will
set `srcdir` (and VPATH) from @srcdir@ before including defs.mak; only
derive them (the $(abspath)/$(patsubst) srcdir computation) when it
did not -- `ifeq ($(origin srcdir),undefined)`. BUILD_TOP (needed by
GENINC) is computed either way.
* Makefile.in: route every subdir recursion through a single helper,
$(call submake,<dir>,<goal>)
which uses the generated build Makefile if config.status made one there
(a converted Makefile.in) and otherwise falls back to the source
Makefile with -f. Today nothing is converted, so out-of-tree always
takes the -f path and in-tree uses the (identical) static Makefile
natively. clean/ keeps its own no-mkdir variant. readline/ is
intentionally never converted and always takes -f.
* .gitignore: document the migration policy -- each converted module adds
its generated "<dir>/Makefile" here in the same commit so an in-tree
build can never commit a generated Makefile. (None converted yet.)
Verified in-tree and out-of-tree: `configure && make && make install`
each produce 376 files with the header in the right place (database/
database.h in-tree, include/database/database.h relocated), 27/28 docs,
source tree clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>