Commit Graph

142 Commits

Author SHA1 Message Date
Darryl L. Miles 5719a536e8 build: autodetect ccache (configure --disable-ccache to opt out)
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>
2026-07-26 14:54:11 -04:00
Darryl L. Miles a9edf1a97d build: add --disable-magic-builddate (reproducible, ccache-stable builds)
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>
2026-07-26 14:54:11 -04:00
Darryl L. Miles 20911acc49 build: honor SOURCE_DATE_EPOCH for the build date; graceful git fallback
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>
2026-07-26 14:54:11 -04:00
Darryl L. Miles b3d6540f13 build: isolate build-info defines into utils/buildinfo.c (ccache-friendly)
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>
2026-07-26 14:54:11 -04:00
Darryl L. Miles 2b4fcf5968 build: include rules.mak from source, drop the build-top copy
rules.mak has no @...@ substitutions, so there is no reason to copy it into
the build top.  Point all 38 subdir Makefile.in includes at the source copy
directly -- ${MAGICSRC}/rules.mak instead of ${MAGICDIR}/rules.mak -- and
remove AC_CONFIG_FILES([rules.mak:rules.mak]) from configure.  defs.mak (the
one make fragment with substitutions) remains the only generated file in the
build top.  readline/ and the top Makefile never included rules.mak, so they
are unaffected; AC_CONFIG_SRCDIR(rules.mak) (the srcdir sentinel) is kept.

Now editing rules.mak in the source tree takes effect without reconfiguring.

Verified rc=0, 375 files, both in-tree and out-of-tree; out-of-tree build
top has no rules.mak; distclean rc=0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-26 14:54:11 -04:00
Darryl L. Miles 69dff2aaa8 build: reduce the srcdir derivation to a minimal fallback
Every converted module sets srcdir=@srcdir@ and VPATH=@srcdir@
before including defs.mak, so the full srcdir derivation is now reached
only by readline/ (never converted) and the top-level Makefile.  Neither
compiles magic sources through the pattern rules, so neither needs VPATH.

Drop the MODULE_SUBPATH variable and the VPATH derivation; keep just a
one-line srcdir fallback so CPPFLAGS (-I${srcdir}) stays well-formed for
those two.  BUILD_TOP is retained (GENINC still needs it).

Verified rc=0: out-of-tree Tcl (375) + in-tree Tcl (375, header present) +
out-of-tree --without-tcl (readline/libreadline.a + magic/magic built
through the fallback).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-26 14:54:11 -04:00
Darryl L. Miles d2650e4833 build: convert nested children + rewire parent recursion to native
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>
2026-07-26 14:54:11 -04:00
Darryl L. Miles 887eca61fe build: generate magic/tcltk/scmos/doc/lisp Makefiles from Makefile.in (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>
2026-07-26 14:54:11 -04:00
Darryl L. Miles fe70666b0c build: generate near-standard + outlier Makefiles from Makefile.in (rename 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>
2026-07-26 14:54:11 -04:00
Darryl L. Miles 02d2147753 build: generate 21 standard-module Makefiles from Makefile.in (rename 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>
2026-07-26 14:54:11 -04:00
Darryl L. Miles 214cc43f4a build: generate tiles/Makefile from tiles/Makefile.in (rename unit)
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>
2026-07-26 14:54:11 -04:00
Darryl L. Miles 242d415788 build: accept @srcdir@-substituted subdir Makefiles
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>
2026-07-26 14:54:11 -04:00
Darryl L. Miles 64d2ad8df7 build: generate <magic/autoconf/config.h> from configure
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>
2026-07-26 14:54:11 -04:00
Darryl L. Miles 1bdc3fa12a build: put the generated header under include/ for relocated builds
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>
2026-07-26 14:54:11 -04:00
Darryl L. Miles 0a3b61dbdd build: fix bundled-readline out-of-tree (unblocks the non-Tcl build)
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>
2026-07-26 14:54:11 -04:00
Darryl L. Miles 3f4a9633d6 build: auto-detect latex/dvips and regenerate docs in default make
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>
2026-07-26 14:54:11 -04:00
Darryl L. Miles 4e967a4766 build: out-of-tree outlier Makefiles — full make + install
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>
2026-07-26 14:54:11 -04:00
Darryl L. Miles 67df47ffb3 build: top Makefile.in + build-dir orchestration (out-of-tree)
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>
2026-07-26 14:54:11 -04:00
Darryl L. Miles b522f31d87 build: VPATH-enable shared make machinery (out-of-tree)
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>
2026-07-26 14:54:11 -04:00
Darryl L. Miles a4e6289035 build: make configure relocatable (out-of-tree)
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>
2026-07-26 14:54:11 -04:00
Darryl L. Miles 665f65d61f configure: autoconf regen (2.69) LDFLAGS/CXXFLAGS/CXX/CC propagation fix 2026-07-23 16:09:35 -04:00
Darryl L. Miles dc31c1f6f6 Makefile: LDFLAGS autoconf propagation
Also fixed up CC/CXX/CXXFLAGS in the same way.

Main notable concern the tclmagic.so now has reordered position of
$LDFLAGS (was start AND end of list, now start of list only),
$LDDL_FLAGS would have already provided it start of list, so it
would be duplicated set of options.

@LDDL_FLAGS@ no longer prepend $LDFLAGS which is now explicit in the
Makefile to allow specific target control.

The purpose of all this is the toplevel ./configure now has LDFLAGS
control passed down to linker command lines as configure --help
indicates.
2026-07-23 16:09:35 -04:00
Darryl L. Miles b6429a3b0b configure: autoconf regen (2.69) ld_first_libs 2026-07-23 16:09:35 -04:00
Darryl L. Miles 12c7927e88 Makefile: LD_FIRST_LIBS high-priority lib order conf control point 2026-07-23 16:09:35 -04:00
Enno Schnackenberg e45db485d8 Add TCL-embedded WASM build variant alongside the existing non-TCL build
Bump VERSION to 8.3.645.

magic.wasm can now be built as two variants packaged in the same npm
release: notcl/ (legacy, magic's own parser) and tcl/ (intubun/tcl 9.x
statically linked, commands evaluated by Tcl_EvalEx). The TCL fork is
pinned via npm/tcl.ref and cloned/built by magic itself — the tcl/
checkout is treated as read-only and built out-of-source into
magic/build-tcl-wasm/.

Configure layer:
- New usingTk variable decoupled from usingTcl in scripts/configure.in
  + scripts/configure, so --with-tcl --without-tk is finally a valid
  combination. Native Linux Tcl+Tk builds keep their previous behaviour
  (both flags default to enabled).
- When usingTk is empty, configure passes -DMAGIC_NO_TK so the small
  number of remaining Tk callsites in tcltk/tclmagic.{h,c} compile out,
  and TKCOMMON_SRCS / USE_TK_STUBS are omitted from the link.

WASM build orchestration:
- toolchains/emscripten/build-tcl-wasm.sh builds libtcl9.x.a + libtclstub.a
  + tclConfig.sh out-of-source from a pristine intubun/tcl checkout.
- npm/build.sh grew a --variant=<tcl|notcl|both> flag and writes its
  outputs into npm/tcl/ and npm/notcl/. It also clones intubun/tcl with
  autocrlf=false at the SHA pinned by npm/tcl.ref.
- magic/Makefile (WASM block only): magicWasm.o is now compiled with
  DFLAGS_NOSTUB so Tcl_CreateInterp resolves to libtcl9.x directly
  before tclStubsPtr is set. magic.js link pulls in LIB_SPECS_NOSTUB
  and -ltclstub. After rules.mak include, magic: is a phony alias for
  magic.js so the generic ${MODULE} recipe doesn't fight it.
- toolchains/emscripten/defs.mak: add -sUSE_ZLIB=1 (libtcl9 references
  zlib), replace -sSTACK_SIZE=N with -Wl,-z,stack-size=N (emcc >=5
  rejects the setting form).
- magic/magicWasm.c bootstraps the embedded interp under MAGIC_WRAPPER
  (Tcl_CreateInterp -> Tcl_Init -> Tclmagic_Init) and routes
  run_command through Tcl_EvalEx.
- magic/magicTop.c: gate MagicVersion/Revision/CompileTime on
  !MAGIC_WRAPPER so they don't collide with the copies in
  tcltk/tclmagic.c when both objects land in the same wasm binary.

npm package:
- Subpath exports: ".", "./tcl", "./notcl". Default import keeps the
  pre-existing non-TCL behaviour for backward compatibility.
- examples/smoke-tcl.mjs exercises the TCL variant.

CI:
- main-wasm.yml clones intubun/tcl at the pinned ref, builds both
  variants via npm/build.sh --variant=both, runs the existing notcl
  test suite and the new TCL smoke test, and publishes only on a
  v<x.y.z>... git tag. Tag name (minus the leading v) becomes the
  npm version.
2026-06-09 16:07:53 -04:00
Darryl L. Miles c74215ad55 scripts/defs.mak.in: FEATURE_FLAGS -DSUPPORT_DIRECT_MALLOC -DSUPPORT_REMOVE_MALLOC_LEGACY
./configure
 # If you are brave, enable with your favourite editor after ./configure
 sed -e 's/^#FEATURE_FLAGS /FEATURE_FLAGS /' -i defs.mak
 make
 make install
2025-12-19 09:31:58 -05:00
Darryl L. Miles 15faa19346 configure: autoconf regen (2.69) --enable-readline-bundled GR_SRCS 2025-10-04 20:50:31 -04:00
Darryl L. Miles af7b6bf119 graphics: minor change to Makefile and configure
This splits and groups DEPSRCS better so errors are not seen trying to
include files that are not present with no intention to build that
source file.
2025-10-04 20:50:31 -04:00
Darryl L. Miles 8b0616eaf5 readline: add configure --enable-readline-bundled option
Cleanup autoconf handling, should always work as expected.
Use of --enable-readline-bundled when readline is needed will use
copy in subdir.
2025-10-04 20:50:31 -04:00
Darryl L. Miles 92b4d6a1f7 configure: autoconf regen (2.69) AC_CHECK_HEADERS sys/ioctl_compat.h sgtty.h 2025-07-29 10:50:32 -04:00
Darryl L. Miles 730d327702 configure.in: AC_CHECK_HEADERS sys/ioctl_compat.h sgtty.h 2025-07-29 10:50:32 -04:00
Darryl L. Miles c3054f265b configure: autoconf regen (2.69) LIBS 2025-07-29 10:50:32 -04:00
Darryl L. Miles a8f5291bd7 defs.mak.in: restore autoconf LIBS functionality
This is a standard autoconf variable, it was probably disabled due to
how the graphics/Makefile works and the more complex detection taking
place there.

Needed to use it to add -lpthread to some platforms (freebsd/openbsd)
to make it build out the box.
2025-07-29 10:50:32 -04:00
Darryl L. Miles aaa477e44a configure: autoconf regen (2.69) AC_STRUCT_DIRENT_D_TYPE 2025-07-29 10:50:32 -04:00
Darryl L. Miles f45aeb6cee configure.in: AC_STRUCT_DIRENT_D_TYPE 2025-07-29 10:50:32 -04:00
Darryl L. Miles 9f0f5f5b4e configure: autoconf regen (2.69) AC_PATH_PROG(PERL,) AC_SUBST(PERL) 2025-07-29 10:50:32 -04:00
Darryl L. Miles ec7d0fc79a configure.in: AC_PROG_PERL 2025-07-29 10:50:32 -04:00
Darryl L. Miles d2449dc971 configure: autoconf regen (2.69) AC_PROG_SED 2025-07-29 10:50:32 -04:00
Darryl L. Miles e51189911b configure.in: AC_PROG_SED (looking for GNU sed) 2025-07-29 10:50:32 -04:00
Darryl L. Miles 412d0570e2 configure: autoconf regen (2.69) ALLOCA NDEBUG DEBUG
also --enable-assertions --enable-debug
also termio.h termios.h sys/ioctl.h
2025-07-29 10:50:32 -04:00
Darryl L. Miles 9f1398dfcb utils/magsgtty.h: detect termio/ioctl headers
Linux is not based on BSD and this file appears to exist to manage
historic BSD conventions concerning termios.
2025-07-29 10:50:32 -04:00
Darryl L. Miles c5ebd7d3c0 makedbh.in _DATABASE_H => _MAGIC__DATABASE__DATABASE_H 2025-07-29 10:50:32 -04:00
Darryl L. Miles b6e70f9632 utils/magic_alloca.h: with autoconf AC_FUNC_ALLOCA
Unclear what the correct Copyright header should be on this one,
given most of the lines in the file are from the autoconf
documentation.
2025-07-29 10:50:32 -04:00
Darryl L. Miles 4d2def46f4 configure.in: whitespace cleanup align --help columns 2025-07-29 10:50:32 -04:00
Darryl L. Miles 49caa3267b configure: --enable-debug make this a user accessible config
This should help with automated CI testing as well, where a suite
can be run and debug enabled and checked, just via a specific
CI setup.
2025-07-29 10:50:32 -04:00
Darryl L. Miles dd49ca21d2 configure: --enable-assertions make this a user accessible config
This should help with automated CI testing as well, where a suite
can be run and assertions enabled and checked, just via a specific
CI setup.
2025-07-29 10:50:32 -04:00
Darryl L. Miles 2a78de8cb9 magic/Makefile: MAGIC_BUILDDATE and inherit values when possible
Went the whole way and make it inherit from toplevel Makefile.
2025-07-29 10:50:32 -04:00
Darryl L. Miles 4e7396162d scripts/configure: autoconf regen (2.69) MAKE_xxxxx generation 2025-07-29 10:50:32 -04:00
Darryl L. Miles d13fa6872e MAKE_xxxxx: to skip building OBJs part of configure 2025-07-29 10:50:32 -04:00
Darryl L. Miles ebf2db91b1 defs.mak.in: DFLAGS_MAGICVERSION
This seems needed in multiple places so made a variable on its own.
2025-07-29 10:50:31 -04:00