Conversation
The top-level ./configure wrapper did `cd scripts`, which is resolved
against the caller's current directory. Running it from anywhere other
than the source top (e.g. `mkdir build; cd build; ../configure`) failed
immediately with:
../configure: line 12: cd: scripts: No such file or directory
Derive the script's own location via `dirname "$0"` and cd into
"${basedir}/scripts" so the wrapper works regardless of CWD.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Enable `mkdir build; cd build; ../configure` to run entirely in the build
directory, with generated config landing there instead of in the source
tree. This is the autoconf-layer groundwork for a full VPATH build; the
make layer (defs.mak/rules.mak VPATH support, per-dir orchestration) is
still to come, so an out-of-tree `make` is not yet expected to work.
Changes:
* configure (wrapper): run the generated config.status in the *current*
directory with --srcdir pointing back at the source tree (instead of
`cd scripts`), so outputs land in the build dir. Uses an absolute
basedir so any build-dir location works, not just a subdir of srcdir.
* scripts/configure.in:
- AC_CONFIG_AUX_DIR(.) -> AC_CONFIG_AUX_DIR(scripts). Once srcdir
resolves to the true top (scripts' parent, where rules.mak lives),
autoconf searches for install-sh/config.sub/... relative to srcdir;
"." pointed at the wrong place and out-of-tree configure died with
"cannot find install-sh".
- Name the .in templates explicitly
(defs.mak:scripts/defs.mak.in, scripts/makedbh:scripts/makedbh.in)
so config.status finds them from a separate build dir. defs.mak is
written to the build top; makedbh under build/scripts/ to match
${SCRIPTS}/makedbh.
- Drop the trailing `cp defs.mak ..`; defs.mak is now generated in the
build top directly, and from a build dir the copy would clobber the
source tree's defs.mak.
* scripts/configure: regenerated with autoconf 2.69.
Verified: out-of-tree `../configure` completes rc=0, writes defs.mak /
scripts/makedbh / config.status into the build dir, records
srcdir=<source top>, and leaves the source tree's tracked files and
generated defs.mak/makedbh untouched.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
With the autoconf layer relocatable, teach the shared make
files to read sources from the source tree and write objects into the
build tree. The ~26 "standard" and "near-standard" module Makefiles now
build out-of-tree with no per-module edits.
scripts/defs.mak.in:
* Add MAGICSRC = @abs_top_srcdir@ (absolute source top) and derive each
module's srcdir/VPATH from CURDIR relative to the build top:
BUILD_TOP := $(abspath $(MAGICDIR))
MODULE_SUBPATH := $(subst $(BUILD_TOP),,$(CURDIR))
srcdir := $(MAGICSRC)$(MODULE_SUBPATH)
VPATH := $(srcdir)
(MAGICDIR keeps meaning the *build* top; in-tree the trees coincide.)
* CPPFLAGS: add -I${MAGICSRC} (source top, for "<module>/<hdr>.h") and
-I${srcdir} (same-dir headers), keeping -I${MAGICDIR} for the generated
database/database.h in the build top.
* MAGIC_VERSION/REVISION read ${MAGICSRC}/VERSION; MAGIC_COMMIT uses
`git -C ${MAGICSRC}` so it works from a build dir outside the work-tree.
rules.mak:
* Compile rule: `-c $*.c` -> `-c $< -o $@` so the source is found via
VPATH in srcdir and the object is written to the build cwd.
* Depend and tags rules: prefix sources with $(srcdir)/ (they are passed
to the compiler/ctags directly, which do not honor VPATH).
scripts/configure.in: AC_CONFIG_FILES([rules.mak:rules.mak]) copies the
VPATH-aware rules.mak into the build top, so a single ${MAGICDIR}
resolves both `include`s in every subdir Makefile. Regenerated configure.
Known limitation (v1): the Depend post-processing sed strips
absolute-path headers, so with an absolute srcdir most header deps are
dropped; out-of-tree incremental header-change rebuilds are weaker.
Depend is already "optimistic/optional"; relativizing is a follow-up.
Verified out-of-tree: `tiles` and `drc` (the latter #includes the
generated database/database.h) build to completion; all objects land in
the build tree; the source tree stays clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Make a plain `make` in a build directory build every module into the
build tree. The top Makefile becomes a configure-generated Makefile.in,
and each recursion drives a build subdirectory (created on demand) using
the module Makefile from the source tree.
Makefile -> Makefile.in (config.status generates Makefile in the build
top via AC_CONFIG_FILES([Makefile:Makefile.in])):
* Add MAGICSRC = @abs_top_srcdir@; read VERSION and re-run configure from
${MAGICSRC}.
* Every descent `(cd $$dir && ${MAKE} <goal>)` and `${MAKE} -C $(dir $@)
<goal>` becomes:
mkdir -p <builddir> && ${MAKE} -C <builddir> \
-f ${MAGICSRC}/<dir>/Makefile <goal>
so the build subdir need not pre-exist and the source Makefile is used.
Applied to modules/libs/depend pattern rules and the
tcllibrary/mains/techs/install/clean loops.
* database/database.h: generate from ${MAGICSRC}/.../database.h.in into
the build tree (mkdir -p database), via the generated build-tree
${MAGICDIR}/scripts/makedbh.
* install-dirs/install-tcl-dirs use ${SCRIPTS}/mkdirs (now source-tree);
clean skips absent build subdirs; distclean/dist/tags updated for the
split source/build layout.
scripts/defs.mak.in:
* SCRIPTS now points at the source tree (${MAGICSRC}/scripts) for the
static helpers (mkdirs, printmans, ...); the one generated helper,
makedbh, is referenced directly at ${MAGICDIR}/scripts (build tree).
* Guard VPATH so it is set only inside module subdirectories, never at
the build top -- a top-level VPATH into the source tree could let a
stale source database/database.h shadow the build-tree copy.
scripts/configure.in: AC_CONFIG_FILES([Makefile:Makefile.in]); regenerated
scripts/configure.
Verified out-of-tree: `../configure && make modules && make libs` builds
all 33 module libraries (lib*.o and lib*.a) plus the generated
database/database.h into the build tree, with no errors and the source
tree left clean. A full `make` (link the magic program, build techs)
still needs the later outlier fixes (magic/, scmos/, ...).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fix the remaining non-standard Makefiles so a full out-of-tree
`../configure && make && make install` builds and installs a complete
magic TCL tree, sources read from the source tree, all outputs in the
build tree.
Shared linker/preprocessor paths (scripts/configure.in, regenerated
scripts/configure):
* --version-script=${MAGICDIR}/magic/symbol.map -> ${MAGICSRC}/... so
every shared-library link (tclmagic.so, ...) finds the source map.
* MCPP preproc.py path ${MAGICDIR}/scripts -> ${MAGICSRC}/scripts.
Programs (built via tcllibrary, PROGRAMS = magic tcltk):
* magic/Makefile: proto.magicrc, magicWasm.o and the bitmaps/.initrc/
magicps.pro install copies use $< / $(srcdir) instead of bare names.
* tcltk/Makefile: magicexec/magicdnull compile $<; the sed'd launcher
scripts (magic.tcl/.sh, ext2spice.sh, ext2sim.sh) read $<; VERSION dep
-> ${MAGICSRC}; install-tcl copies each TCL file from the build dir if
present else $(srcdir) (magic.tcl is generated, the rest are source).
Techs (scmos):
* scmos/Makefile: SC_PP template include -> $(srcdir)/extract_template;
tech-file inputs (scmos.tech.in, *.tech.in) via $(srcdir)/$< ; recurse
into cif_template with mkdir + -f ${MAGICSRC}/scmos/cif_template/Makefile;
install copies from build-or-$(srcdir).
* scmos/cif_template/Makefile: MKDIR -> ${MAGICSRC}/scripts/mkdirs;
SC_CPP gains -I$(srcdir); cpp reads $(srcdir)/cif{in,out}.c so the .gen
includes resolve; objs/ generated in the build tree.
Data-file installs (source files copied from $(srcdir)):
* graphics/Makefile: glyphs, outline fonts, and the X11 helper build.
* windows/Makefile: glyphs and vector fonts.
* doc/Makefile: recurse into man/tutcells/html/latexfiles build-aware;
doc/man, doc/tutcells install with $< ; doc/html tars $(srcdir);
doc/latexfiles reads pre-built PostScript from ${MAGICSRC}/doc/psfiles.
Verified out-of-tree (mkdir _build; cd _build; ../configure): `make`
returns rc=0 (33 module libs, tclmagic.so, magicexec/magicdnull, scmos
tech files + cif_template objs, proto.magicrc), and
`make install DESTDIR=...` returns rc=0 installing 376 files
(bin/magic, tcl/tclmagic.so, sys/ glyphs+fonts+techs+dstyles), with the
source tree left completely clean.
Not exercised by the default TCL build/install and therefore not
converted here: the standalone .so/program variants of
lef/plot/router/ext2spice/ext2sim (their module libs do build), the
disabled oa module (-I. -> -I$(srcdir) still needed if enabled), the
WASM path, and doc/latexfiles PostScript *regeneration* (which still
writes into the source psfiles dir).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The out-of-tree conversion turned the top-level Makefile into a configure-generated file (from Makefile.in), and config.status now runs in the build directory (the source top for an in-tree build). Ignore both at the top level only (anchored) so the tracked per-module Makefiles are unaffected. config.log is already ignored. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extend the out-of-tree build to the outliers deferred earlier, and
audit install sourcing. All are read-source / write-build now.
Tcl auto-load shared libraries (built via each module's `tcl-main`;
not part of the default TCL build, but now correct when invoked):
* lef/plot/router/ext2spice/ext2sim: the hand-written object rules
(tcllef.o, tclplot.o, tclroute.o, spicewrap.o, spicehier.o, simwrap.o,
ext2sim_main.o) compiled a bare-name source from the cwd; switch to
`-c $< -o $@` so the source is found via VPATH and the object lands in
the build tree. ext2sim_main.o also swaps the hard-coded -I${MAGICDIR}
for ${CPPFLAGS} (build + source include paths). ext2spice spice2sim
install copies $< (source script). Sibling ${MAGICDIR}/<mod>/lib*.o
refs already resolve into the build tree (MAGICDIR = build top).
oa (disabled by default; OpenAccess):
* CXX_INCLUDES -I. -> -I$(srcdir) -I${MAGICDIR} -I${MAGICSRC} so the C++
sources, generated database/database.h, and cross-module headers all
resolve out-of-tree; .deps and objects were already build-local.
doc/latexfiles PostScript regeneration:
* Split PS_SRCDIR (pre-built PS shipped in the source tree, read-only)
from PS_GENDIR (= psfiles in the build tree). `all` / the .tex.ps
rule now regenerate into PS_GENDIR (mkdir -p; latex reads $(srcdir)
via TEXINPUTS; dvips writes the build tree) instead of writing back
into the source psfiles dir. install takes each .ps from PS_GENDIR if
regenerated there, else the pre-built PS_SRCDIR copy.
Verified out-of-tree (make modules; then per-module tcl-main):
* magiclef.so / tclplot.so / tclroute.so / exttospice.so / exttosim.so
all build into the build tree (rc=0); oa.o builds into the build tree;
source tree stays clean.
* install-tcl copies each .so from the build tree.
* Install-location audit on a full `make install DESTDIR=...`: generated
data (scmos.tech, .magicrc, magic.tcl, tclmagic.so) matches the build
tree; verbatim data (glyphs, fonts, magicps.pro, man pages, doc PS)
matches the source tree.
* DESTDIR: two distinct prefixes install 376 files each, independent and
fully contained (nothing written outside DESTDIR).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
magic/Makefile ran the WASM post-processor via ${MAGICDIR} (the build
top). Out-of-tree that resolves to build/toolchains/... which does not
exist — the script is a source file. Use ${MAGICSRC}. In-tree the two
are identical, so behaviour is unchanged there.
(Static edit; not runtime-verified — emscripten is not available here.)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Emscripten link embedded data files via magic-relative paths
(../scmos, ../windows/...), which only resolve when the build dir is the
source dir. Split them by which tree the data lives in:
* generated scmos tech files -> ${MAGICDIR}/scmos (the build tree, where
`make techs` writes them);
* verbatim window glyphs -> ${MAGICSRC}/windows/... (the source tree).
Out-of-tree, ../windows/windows7.glyphs pointed at build/windows/ (which
holds only objects) and the link would fail to embed it. In-tree the two
trees coincide, so the resulting .wasm is unchanged.
(Static edit; not runtime-verified — emscripten is not available here.)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
npm/build.sh built in-tree: it cd'd into the source root, ran `./configure` there, appended the WASM defs.mak to the source-tree defs.mak, and copied magic.js/.wasm out of the source magic/ dir. Run each variant in a dedicated out-of-source build dir instead (build-wasm-<variant>, overridable via WASM_BUILD_DIR): * configure is invoked as "$REPO_ROOT/configure" from $build_dir, so config.status and all generated files land under $build_dir; the source tree is only read (VPATH). * the WASM defs.mak is appended to $build_dir/defs.mak. * artifacts are copied from $build_dir/magic/. * a fresh `rm -rf $build_dir` per run replaces the old in-tree `make distclean` (which also removes the need to touch the source tree, and sidesteps the tracked-rules.mak distclean hazard entirely). CRLF stripping now targets the source-tree configure inputs explicitly. Note: build-wasm-<variant> dirs are not gitignored (left per task scope); they are disposable and recreated each run. (Static edit; not runtime-verified — emscripten is not available here.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
npm/build.sh now builds each WASM variant out-of-source in build-wasm-<variant> under the repo root (fixed names build-wasm-tcl / build-wasm-notcl). They are disposable (recreated each run) and must not be tracked. Confirmed the relocated build dirs receive all output while the source module dirs stay clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
TCL 9.1's configure defines NOTIFIER_EPOLL whenever <sys/epoll.h> is present (unix/configure.ac:342). Emscripten's sysroot ships that header and the epoll_* symbols, so TCL picked the epoll notifier — but epoll does not work under WASM at runtime and the event loop hangs. Hide the header/functions from TCL's configure via autoconf cache vars (ac_cv_header_sys_epoll_h=no + epoll_create/epoll_create1=no) so the select()-based notifier is selected instead. Verified with emsdk 6.0.3: NOTIFIER_EPOLL is absent from DEFS, the tclEpollNotfy.o/tclKqueueNotfy.o objects are empty stubs (333 B) and tclSelectNotfy.o is the live notifier (~9.9 KB); the tcl WASM variant links (magic.js + magic.wasm) via npm/build.sh out-of-source. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When latex and dvips are available, the default no-arg "make" now
regenerates the PostScript documentation from its .tex sources into the
build tree; otherwise the pre-built PostScript shipped in the source tree
is used as-is at install time. Documentation is always available either
way -- installing latex simply refreshes it from source.
configure (scripts/configure.in, regenerated scripts/configure):
* AC_PATH_PROG for latex + dvips; DOCS_TARGET = "docs" only when both are
found; AC_SUBST(LATEX/DVIPS/DOCS_TARGET).
* Configuration summary prints "LaTeX docs: yes/no".
scripts/defs.mak.in: export LATEX/DVIPS.
Makefile.in:
* all: ... $(DOCS_TARGET) -- pulls in "docs" only when latex was found.
* docs: best-effort -- `make -k` + a warning on failure so a document
that will not typeset (or a missing texlive package) never fails the
build; install falls back to the pre-built PostScript for those.
doc/latexfiles/Makefile:
* use ${LATEX}/${DVIPS} from defs.mak.
* the .tex include figures as ../psfigures/*.ps; point the build-tree
../psfigures at ${MAGICSRC}/doc/psfigures (no-op in-tree) so latex and
dvips find them while outputs stay in the build tree.
CI: main.yml and main-aarch64.yml install
texlive-latex-base/-recommended + texlive-fonts-recommended so the Linux
builds exercise doc regeneration (best-effort, never fatal).
README.Tcl: document latex/dvips as an optional prerequisite for docs.
.gitignore: ignore in-tree doc build artifacts (doc/latexfiles/psfiles/,
*.dvi/*.aux/*.log); the pre-built doc/psfiles/ stays tracked.
Verified out-of-tree with TeX Live 2024: configure reports "LaTeX docs:
yes"; `make` regenerates 27/28 documents into the build tree (maint1.tex
has a genuine LaTeX error and falls back), stays exit 0; `make install`
installs the 27 regenerated PostScript from the build tree and maint1
from the source pre-built copy; the source tree is not modified.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The AppImage builders already shipped the pre-built PostScript documentation (each Dockerfile runs "make install", and INSTALL_CAD_DIRS includes doc/), but they did not install latex/dvips, so the docs were never regenerated from source. Install texlive (latex + dvips + recommended fonts) before the magic build in all four EL variants (yum on EL7, dnf on EL8/9/10), so configure reports "LaTeX docs: yes" and the default "make" regenerates the docs into the build before "make install" ships them. The install is non-fatal (|| echo): if a texlive package is unavailable on a given EL release it falls back to the pre-built PostScript, so the release image build can never be broken by documentation, and docs are shipped either way. NOTE: not build-tested here (no Docker/EL toolchain available). The package names (texlive-latex, texlive-dvips, texlive-collection-fontsrecommended) should be validated on each EL image; the non-fatal guard protects the tag-triggered release builds in the meantime. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two long-standing breakages in `make -C ext2sim main`:
* finds.c included <string.h> *after* utils/magic.h. magic.h defines the
legacy SysV bcopy/bzero/bcmp compat macros in terms of memcpy/memset/
memcmp; with a modern glibc that then declares those functions, the
macro expansion collides ("conflicting types for 'memcpy'"). Include
the C library headers before magic.h so the real prototypes win.
* the `main` target listed `sim2simp`, which has no source file and no
rule (and `ext2sim_main` was already commented out as deprecated), so
the target always failed. Reduce `main` to the one real artifact,
`finds`.
Verified: `make -C ext2sim -f .../ext2sim/Makefile main` now builds
`finds` cleanly (rc=0).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The non-Tcl ("standard") configuration links the bundled GNU readline,
and that path was broken two ways:
* headers: readline's own headers use <readline/*.h> includes, so the
readline source's parent must be on the include path. Nothing added
it, so every module including readline (commands, textio, ...) failed
with "readline/rlstdc.h: No such file". Add -I${MAGICSRC}/readline to
CPPFLAGS for the bundled build only (@MAKE_READLINE@ = 1).
* library: readline/Makefile ran "../readline/configure" from the
build-readline dir -- a source-relative path that, out-of-tree, points
into the (empty) build tree. Use ${MAGICSRC}/readline/readline/
configure so the out-of-source readline build finds its sources.
Verified: `mkdir b; cd b; ../configure --without-tcl && make` now
completes (rc=0) and produces the native magic binary; previously it
died at commands/CmdFI.o (headers) then at the readline library build.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Extend the Linux CI so consumers exercise more of what is buildable: * In the Tcl job, after the default build, also build the per-module Tcl auto-load shared libraries (lef/plot/router/ext2spice/ext2sim tcl-main -> magiclef.so, tclplot.so, tclroute.so, exttospice.so, exttosim.so). These are real products the default target never builds, so building them in CI keeps them from bit-rotting. * Add a standard_build_linux job for the non-Tcl configuration (./configure --without-tcl): the native magic binary + bundled GNU readline -- code paths the Tcl build does not cover, and which only build now that the bundled-readline out-of-tree fixes landed. NB: the standard job's apt package set is not validated on the runner; adjust if a library is not found. Docs remain best-effort in both jobs. Not changed here: whether the five auto-load .so should also be shipped by the default "make install" (they currently are not) -- left as a separate decision. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Previously the generated database/database.h was written to the build
top and exposed with -I${MAGICDIR}. Out-of-tree that placed the raw
build directory on the compiler's include search path.
Introduce ${GENINC}, the single include dir for generated headers:
* in-tree (build top == source top): ${MAGICDIR}, so the header stays
at $(builddir)/database/database.h and -I${GENINC} is exactly the old
-I${MAGICDIR} -- behaviour is unchanged.
* relocated (out-of-tree): ${MAGICDIR}/include, so the header is written
to $(builddir)/include/database/database.h and only that clean
include/ dir is on the search path; the raw build top never is.
* scripts/defs.mak.in: derive GENINC from BUILD_TOP vs MAGICSRC; add
DATABASE_H = ${GENINC}/database/database.h; CPPFLAGS uses -I${GENINC}.
* Makefile.in: the makedbh rule targets ${DATABASE_H} (mkdir its dir);
every prereq and the distclean use ${DATABASE_H}.
* database/Makefile: the fallback delegate targets ${DATABASE_H}.
Verified: relocated `make modules` builds all 33 module libraries with
the header at build/include/database/database.h and no raw build-top on
any -I line; in-tree the header stays at database/database.h and the
-I set is unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… path
The generated header's path now depends on in-tree vs relocated builds
(database/database.h vs include/database/database.h), so instructions
that named it directly ("make database/database.h") are brittle.
Add a stable, path-independent top-level target:
.PHONY: prepare
prepare: ${DATABASE_H}
Being .PHONY the name is always valid, but its prerequisite is the real
file target ${DATABASE_H}, so the header is still regenerated only when
out of date -- same result, no exposed path.
Convert every "make database/database.h" in the docs, appimage
Dockerfiles, and CI workflows to "make prepare".
Verified: relocated `make prepare` generates include/database/database.h;
re-running is a no-op; touching database.h.in triggers regeneration.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Emit an autoconf config header carrying every autoconf define -- at least
all the -D options that appear on the compiler command lines, plus
anything else configure knows -- available to the tree as
#include <magic/autoconf/config.h>
It is built directly from confdefs.h just before AC_OUTPUT (which removes
that file), NOT via AC_CONFIG_HEADERS. This is deliberate:
* AC_CONFIG_HEADERS would rewrite @defs@ to -DHAVE_CONFIG_H and move the
defines into the header, changing every compiler command line and
breaking the build until sources #include it. Building from confdefs.h
leaves @defs@ (and the whole build) exactly as-is, so the header is a
pure additional artifact with no consumers yet.
* confdefs.h already holds every AC_DEFINE, including the many that have
no autoheader template (CALMA_MODULE, HAVE_READLINE, ...), which
AC_CONFIG_HEADERS/autoheader would have dropped.
Location mirrors the generated database.h (defs.mak GENINC): magic/autoconf/
config.h at the build top when in-tree (build dir == source dir), else
include/magic/autoconf/config.h so the clean -I include/ rule finds it and
the raw build dir stays off the search path. The directory is created on
demand and the header is rewritten on every ./configure. No defs.mak.in
change is needed -- the existing -I${GENINC} already resolves it.
.gitignore: ignore the in-tree magic/autoconf/config.h (out-of-tree it is
under the build dir and already ignored).
Verified: out-of-tree writes include/magic/autoconf/config.h, in-tree
writes magic/autoconf/config.h; both contain the command-line defines
(SIZEOF_VOID_P, CALMA_MODULE, HAVE_*, ...); #include <magic/autoconf/
config.h> resolves via -I${GENINC} from a subdir; @defs@ is unchanged
(-DHAVE_CONFIG_H absent) and modules still build.
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>
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>
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>
… unit) 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 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>
…ename unit)
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 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>
… (rename unit)
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 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>
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>
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>
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>
…ndly)
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>
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>
…lds) 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>
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>
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>
…TALL
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>
… machinery
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>
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>
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>
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>
…ipping 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>
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>
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>
…atch 1) 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>
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>
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>
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>
…_DIR
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>
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>
…he env
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>
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>
|
I would point out that the LaTeX documentation was more or less hidden away on purpose, because I migrated all the documentation to HTML and the original .tex sources are considerably out of date (another job for "the clankers"?). |
RTimothyEdwards
left a comment
There was a problem hiding this comment.
This is a very useful set of updates. My only concern is the mess of outdated information that is likely to end up in the compiled .tex documentation, which has not been kept up to date with the HTML documentation. However, making sure all forms of documentation (including the man pages) are all up to date and agreeing with each other can be done in a later commit.
I especially like having the "Depend" mechanism removed, as it was making the compile time slower than it used to be.
|
pulled and merged to opencircuitdesign.com |
|
@RTimothyEdwards So what is being said, the |
|
@dlmiles : Well, I did say that the files in A long time ago I took the |
committed by Darryl Miles in PR RTimothyEdwards#546 and RTimothyEdwards#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).
Makefile and build system overhaul - encore
The clankers have been busy. The clankers have turned my local attempts in these areas into a
more comprehensive solution in line with the original intention/goals they were moving towards.
CHANGE LOG NOTES:
Previously the documentation advised
make database/database.hto seed the main compile. Thishas not been technically required since the last build-system overhaul, and the label has changed
to
make prepareso as to remove the hard dependency on the location of a specific file and use amore generic target unrelated to file existence. This is still optional for most/all builds, and
for in-tree builds
make database/database.hcontinues to work, but downstream builders shouldupdate their scripts.
INSTALL_MacOS.md notes a new optional package 'coreutils' for 'gdate' (GNU date). Some effort is
made to be compatible with the Mac BSD-based 'date', but it is recommended to have 'gdate' on
$PATH if you are packaging for third parties.
CAD_ROOT / TCL_DIR change, see above - not really expecting this to affect anyone.
configure - is now relocatable (out-of-tree builds).
cd magic; mkdir build-tmp; cd build-tmp; ../configure; make; ./run_magic.sh; make install DESTDIR=/tmp/stageThis now all works, this is probably the biggest blocker to magic being easily adopted by a modern
distribution as a regular package as the magic project predates autoconf and didn't get all the new
autoconf features as they arrived and out-of-tree building is the default where the sources are
treated read-only and the outputs end up in a $builddir.
in-tree building still continues to work
building multiple trees from the same source in different builddir using different configure
options and such should all now work with incremental build benefits.
We are still on autoconf 2.69 that is expected to be reviewed next time to look towards 2.71 / 2.72
even if we do not make use of new features from these, because they have become the new Linux
distro baseline.
Per-module Makefile.in migration - this is the mechanism that makes the out-of-tree build work.
Each module's Makefile is now a template (Makefile.in) that configure turns into a generated
) and VPATH points back at the read-only source. In-tree theMakefile in the $builddir via @srcdir@ substitution, rather than every subdir sharing one Makefile
that computed paths at make-time. config.status creates the build subdir with its Makefile, so
recursion is native (make -C
build top and source top are the same directory, so nothing changes for that case.
A series of scripts run_*.sh are created in the $builddir and are designed to allow magic to be
run directly from the builddir without a
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
On first run each one self-stages a $builddir/CAD_DIR directory (a tree of symlinks into the build
and source trees, no copies) and exports CAD_ROOT so magic finds its runtime files there. The gdb
and valgrind wrappers accept a "--" separator so you can pass options to the tool on the left and to
magic on the right.
CAD_ROOT / TCL_DIR - Due to making the "run from $builddir" feature work (without needing to
install), the TCL_DIR hardwired default is now constructed from $CAD_ROOT/magic/tcl at run time
when the CAD_ROOT environment variable is set and non-empty; otherwise the fallback to the hardwired
compile-time default still occurs. (CAD_ROOT is the runtime environment variable magic already
uses to relocate its sys files; CAD_DIR is the compile-time default and the name of the staged
directory.) If there is a downstream issue maybe we can add a $TCL_DIR override, but it would be
interesting to understand better the non-standard install layouts being used there if so; plus you
can always drop a symlink under $CAD_ROOT/magic/tcl. In the future the TCL_DIR compile-time
constant could perhaps be removed entirely.
The old legacy Depend mechanism has been removed. The SED processing that went with it may have
been to address a legacy compiler/toolchain matter that no longer exists today.
A more modern .deps/.d fragment is built per source file and transparently maintained by the
toolchain (compiler -MMD).
The depend system is only advisory anyway - it is not required to function to build everything, it
is only useful for those developing magic and wanting incremental build speeds. As a result there
is no longer a serialization barrier forcing dependencies to be built before compilation can start.
Parallelism - some work was done on this in the past to remove the worst offenders from the
compile/link phases. Now the build should be entirely parallelized so your
make -j$(nproc)shouldsee full top-down rebuild benefits.
ccache is supported by default, if found at configure time; --disable-ccache exists to have
configure ignore it. configure --enable-ccache-prefix-map also exists to help scenarios where
independent build trees want to share compiler output. Since compile time is below 10s maybe this
is performance overkill at this time.
Reproducible build - the new configure option --disable-magic-builddate will remove the
MAGIC_BUILDDATE from the project, making the final executables/DSO more compatible with reproducible
build goals some package maintainers may be trying to achieve (due to recent supply-chain security
concerns). This means given the same environment/distro/toolchain and build options the output
executables/DSO can be compared against another system doing the same, to allow verification of
toolchain/supply-chain compromise. If there are other concerns found in this area please raise
issues.
If you are a developer maybe you also want to consider --disable-magic-builddate in your configure
since it removes the requirement to recompile buildinfo.o to update MAGIC_BUILDDATE every time you
re-link to test. (The build-info defines were isolated into a single small translation unit,
utils/buildinfo.c, which is what makes this - and ccache stability - possible.)
SOURCE_DATE_EPOCH is also honored (configure detects GNU vs BSD
date); not fully tested but shouldassist in the reproducible build space.
Bundled readline has been removed. The bundled copy was GNU readline 4.3 (over 23 years old;
doesn't really have any CVE security concern) but all platforms magic builds against can provide
their own more recent version, including SVR4/Solaris, the oldest tested against. This was done as
a deliberate three-patch series (require system readline, then remove the Makefile wiring, then
delete the readline/ subdirectory). When building non-Tcl/Tk the default now expects readline to be
present at configure time or it will fail with a clear message; --disable-readline still exists to
build without it, which is useful in slim/headless build modes.
WASM / Emscripten - the WebAssembly build was brought in line with the same out-of-tree principles
and unbroken against the current emsdk:
the source tree is read-only);
verbatim glyphs/colour maps from the source tree) so out-of-source init works;
a hard "wasmBinary not included" abort seen on emsdk 6.x;
stub;
LaTeX documentation - this was hidden away; it has now been made part of the default build output,
with configure auto-detecting the necessary programs and advising what you are missing. (The CI /
AppImage packaging was updated to install texlive so the documents actually regenerate and ship.)