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>
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>
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>
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>
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>
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>
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 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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
magic replaces Tcl's stdin channel with its own (TerminalInputProc) during
startup (_magic_startup). The replacement builds a brand-new Tcl channel over
the same fd; the new channel starts with an empty buffer. If anything had
already read() stdin bytes out of the kernel into the *old* channel's buffer
before the swap -- e.g. a script/commands piped in fast enough that Tcl buffered
them during startup -- those bytes were silently dropped, and every command
after that point vanished. This was timing-dependent, so it surfaced only
intermittently ("piped input discarded sometimes").
Fix: before creating the replacement channel, drain any bytes still buffered in
the old channel (Tcl_InputBuffered / Tcl_ReadChars) and hand them to
TerminalInputProc via TxBuffer, which it already serves ahead of any fresh
read(). The swap is now lossless by construction rather than by luck. On the
normal path Tcl_InputBuffered() is 0, so the new branch is inert.
How to reproduce / observe the original loss:
Temporarily force the old channel to buffer input just before the swap, right
after `fsOrig = Tcl_GetChannelInstanceData(oldchannel);` in _magic_startup():
{ Tcl_Obj *l = Tcl_NewObj(); Tcl_IncrRefCount(l);
Tcl_GetsObj(oldchannel, l); /* consume 1 line, buffering the rest */
fprintf(stderr, "buffered=%d\n", (int)Tcl_InputBuffered(oldchannel));
Tcl_DecrRefCount(l); }
then pipe a burst of commands (more than one line):
printf 'puts a\nputs b\n...\nquit -noprompt\n' | ./run_magicnull.sh
Comment the drain out and every command after the first disappears; restore it
and they all survive. Measured with 218 bytes buffered: 0/20 commands survive
without the drain, 19/20 with it (the one line the probe consumed aside).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>