diff --git a/goals/G-096-zig-buildsuite-piperepl.md b/goals/G-096-zig-buildsuite-piperepl.md index fa12e528..9b4b59dd 100644 --- a/goals/G-096-zig-buildsuite-piperepl.md +++ b/goals/G-096-zig-buildsuite-piperepl.md @@ -1,6 +1,6 @@ # G-096 Tracked zig tcl buildsuite (suite_tcl90) with recovered TCLSH_PIPEREPL kit-repl capability -Status: proposed +Status: active Scope: src/buildsuites/ (suite_tcl90 new; samplesuite1 sketch reconciliation; VCS ignore flip), src/buildsuites/_build/ (untracked build/source area via existing _build globs), .gitignore + .fossil-settings/ignore-glob, src/scriptapps/bin/ (getzig scriptset rename), bin/ (regenerated punk-getzig wrapper twins, old names retired, AGENTS.md naming policy), bin/tools/ (untracked zig toolchains, existing), TEMP_REFERENCE/2024zig (read-only recovery origin) Goal: src/buildsuites gains its first real, VCS-tracked suite (suite_tcl90) that reproducibly builds the Tcl 9.0 windows runtime from clean sources using only project-managed tooling - a punk-getzig wrapper fetching a pinned zig into untracked bin/tools, with all transient checkouts and outputs under untracked src/buildsuites/_build - and the 2024 TCLSH_PIPEREPL tclMain patch is recovered into the suite in tracked form and rebased onto current Tcl 9 sources, so a suite-built runtime can return to a standard interactive repl after a kit-style main.tcl completes with unconsumed piped input buffered rather than eval'd, while stock behaviour is preserved whenever the env gate is unset. Acceptance: from a clean checkout plus a punk-getzig-fetched pinned zig, the suite builds tclsh90s/tclsh90szip from a fresh core-9-0-branch checkout under src/buildsuites/_build with recipe-generated tclUuid.h and tclsh.exe.manifest (no hand-placed files) and the result reports the expected patchlevel; the recovered patch set (piperepl plus the companion tclZipfs/tclCmdIL patches and a notes doc) is tracked in the suite; a piperepl-patched build with TCLSH_PIPEREPL unset behaves identically to the unpatched build on a tty/piped/script-arg matrix, and with TCLSH_PIPEREPL=1 a script setting ::tclsh(dorepl) 1 lands in a live interactive console repl after piped-input eof with the unconsumed input available in ::tclsh(inputbuffer); src/buildsuites is tracked in both VCSes with only _build content ignored and the samplesuite1 vendorbuild-prefix residue reconciled (vendorbuild concept retired); bin/AGENTS.md documents the utility naming policy (punk- prefix for punkshell-own utilities; exceptions: external-tool wrappers such as dtplite/sdx/kettle, and getpunk as the intended future cross-platform entry point) and the getzig scriptset and its bin wrapper twins (getzig.cmd/getzig.ps1) are renamed to punk-getzig with the old names removed and references updated. @@ -100,3 +100,57 @@ Acceptance: from a clean checkout plus a punk-getzig-fetched pinned zig, the sui - The G-076 kill-procedure runtime (zig-out905 under c:/buildtcl/2024zig) predates this suite; once suite_tcl90 reproduces it, the ad-hoc c:/buildtcl/2024zig builds become historical reference only. + +## Progress + +### 2026-07-20 increment 1: activated; buildsuites tracked; suite_tcl90 builds 9.0.5 end-to-end + +- Goal set active (user 2026-07-20). VCS tracking flip: the blanket /src/buildsuites + ignores removed from .gitignore and .fossil-settings/ignore-glob; the retired + vendorbuilds ignores removed with them; src/buildsuites/_build confirmed ignored via + the existing **/_build/ (git) and */_build (fossil) globs. +- samplesuite1 sketch reconciled: marked SKETCH ONLY with the toolchain-policy note; + buildprefix moved from /vendorbuild to src/buildsuites/_build/samplesuite1. +- suite_tcl90 created (tracked): build905.zig verbatim from the G-076-validated recipe, + helper build modules, src/main.zig stub, tools (wrapfiletofile.zig, + zipfs_mkzip/mkimg.tcl), patches/ (piperepl pair + tclZipfs + tclCmdIL + README with + the piperepl semantics), suite README, and the suite.tcl driver. +- Driver design: the tracked recipe is STAGED into _build/suite_tcl90/build with + sibling sources arranged around it (tcl905 = fossil core-9-0-branch; tclthread and + tclvfs fossil trunk; zlib copied from the tcl checkout's own compat/zlib 1.3.2; + vqtcl from a local dir - no public upstream confirmed), so the recipe needs no path + surgery and cache/outputs land under _build naturally. Fossil checkouts open --nested + (the stage is inside the punkshell checkout) with FOSSIL_HOME= so the global + fossil config db records nothing; clones reuse ~/.fossils (tcl, tclthread, tclvfs + all already present). +- Fresh-checkout generation lives in the driver (G-076 findings productized): + win/tclUuid.h from manifest.uuid; win/tclsh.exe.manifest from its .in + (TCL_WIN_VERSION per the tree's own formula, parsed from tcl.h - note the defines + are indented '# define'); thread.rc gains the tcl.h include for its version + resource (scripted idempotent edit of the staged checkout, replacing the historical + uncommitted tweak in the 2024 tclthread checkout). +- Recipe fixes made in the suite copies: the four tcl-dependent helper modules' + hardcoded ../tcl90/generic include (author's "todo - fix") now use their tcldir + param; build_tclthread additionally puts the generated threadUuid.h's output dir on + the include path - current thread trunk #includes threadUuid.h (upstream makefiles + generate it into their build dir; the recipe's copy-to-source went to win/, which is + not an include dir). build_libtommath.zig keeps its hardcoded path but is not called + by the recipe. +- End-to-end run PASS (native tclsh 9.0.3 driving; zig 0.14.0-dev.2074 at C:/zig): + fetch -> stage -> generate -> build -> smoke. Static and zip shells both report + 9.0.5 (checkout 1a9c3b9d96 = core-9-0-branch tip carrying the f10d91c2 console + fix); zip shell tzdata working; tcl9thread301.dll builds from CURRENT thread trunk + (3.0.1) and loads. vfs/vlerq dlls also built. + +Remaining for acceptance: + +- punk-getzig rename (scriptset + both bin wrapper twins, old names removed, + references updated) and the naming-policy section in bin/AGENTS.md. +- Pin an exact zig version retrievable via punk-getzig and have the suite consume it + (driver currently takes -zig / PUNK_ZIG / PATH; validated with 0.14.0-dev.2074). +- Rebase the piperepl patch onto current core-9-0-branch sources; build a + piperepl-enabled variant; behaviour matrix (TCLSH_PIPEREPL unset == stock on + tty/piped/script-arg forms; =1 with a script setting ::tclsh(dorepl) 1 -> live + interactive console repl after piped eof with unconsumed input in + ::tclsh(inputbuffer)). +- Final clean-checkout re-verification of the whole flow once the above land. diff --git a/src/buildsuites/suite_tcl90/README.md b/src/buildsuites/suite_tcl90/README.md new file mode 100644 index 00000000..169dd4f9 --- /dev/null +++ b/src/buildsuites/suite_tcl90/README.md @@ -0,0 +1,77 @@ +# suite_tcl90 - zig build of the Tcl 9.0 windows runtime (G-096) + +The first real, tracked buildsuite: reproducibly builds `tclsh90s.exe` (static) and +`tclsh90szip.exe` (self-contained zipfs) plus the thread/vfs/vlerq extension dlls from +a fresh Tcl core-9-0-branch checkout, using zig only (no MS toolchain, per the project +toolchain policy). + +Everything transient lives under `src/buildsuites/_build/suite_tcl90/` (VCS-ignored via +the repo's existing `_build` globs): staged recipe, source checkouts, zig cache, and the +`out/` install prefix. The tracked content here is the recipe and its driver. + +## Usage + + tclsh suite.tcl build ?options? + tclsh suite.tcl clean + +See `suite.tcl`'s header for options (`-zig`, `-optimize`, `-tclbranch`, `-refresh`, +`-vqtcl-source`, `-steps`). The zig executable defaults to `$env(PUNK_ZIG)` or `zig` on +PATH; the recipe's known-good zig is 0.14.0-dev.2074 (see Lineage) - a punk-getzig +fetched pinned zig is the intended source (G-096 acceptance; wrapper rename pending). + +## Layout + +- `build905.zig` - the zig recipe (verbatim lineage copy - see Lineage). Expects its + build root's SIBLING dirs to hold sources (`../tcl905`, `../zlib`, `../tclthread`, + `../tclvfs`, `../vqtcl`), which is why `suite.tcl` stages it into + `_build/suite_tcl90/build/` rather than building in place. +- `build_libtommath/ build_zlib/ build_tclvfs/ build_vqtcl/ build_tclthread/` - helper + build modules. The four tcl-dependent helpers take the tcl source dir as their + `tcldir` param (a hardcoded `../tcl90/generic` include, marked "todo - fix" upstream, + was fixed when these copies were made). `build_libtommath.zig` still carries the + hardcoded path but is not called by the current recipe (tcl's in-tree tommath is + compiled into the core; the `libtommath.dll` seen in old output dirs was a stale + cache-install artifact). +- `src/main.zig` - stub root module that disables zig's own start symbols so the mingw + CRT provides the exe entry. +- `tools/` - `wrapfiletofile.zig` (uuid-header generation used by prepare-source), + `zipfs_mkzip.tcl` / `zipfs_mkimg.tcl` (make-zipfs drivers). +- `patches/` - recovered 2024 experiment patches, including TCLSH_PIPEREPL + (see `patches/README.md`). NOT applied by the default build - stock sources. +- `suite.tcl` - the driver: stage recipe -> arrange sources -> generate the + configure-produced files a fresh checkout lacks -> build -> smoke-test. + +## Sources + +| dir (sibling of build root) | origin | selection | +|---|---|---| +| `tcl905` | fossil `https://core.tcl-lang.org/tcl` (clone cached `~/.fossils/tcl.fossil`) | `-tclbranch`, default `core-9-0-branch` | +| `zlib` | the tcl checkout's own `compat/zlib` (version-matched, includes contrib/minizip) | copied by suite.tcl | +| `tclthread` | fossil `https://core.tcl-lang.org/thread` | trunk | +| `tclvfs` | fossil `https://core.tcl-lang.org/tclvfs` | trunk | +| `vqtcl` | local dir only (vlerq 4.1 by jcw; no public upstream confirmed) | `-vqtcl-source` | + +Checkouts under `_build` use `FOSSIL_HOME=` so the user's global fossil config +db records nothing (stage-local `_fossil` db, deleted with `clean`). + +## Fresh-checkout preparations the driver performs + +Normally products of `configure`/`nmake` that a bare checkout lacks (G-076 findings): + +- `win/tclUuid.h` - generated from `manifest.uuid`. +- `win/tclsh.exe.manifest` - generated from its `.in` (`TCL_WIN_VERSION` per the tree's + own formula: `TCL_VERSION . releaselevel . patchlevel-stripped-of-'ab.'`). +- `thread/win/thread.rc` - gains `#include "../../tcl905/generic/tcl.h"` (the zig rc + compile does not receive the makefile's include paths; historically an uncommitted + tweak in the 2024 checkout, now a scripted idempotent edit of the staged copy). + +## Lineage + +`build905.zig` descends from the validated ad-hoc builds in `c:/buildtcl/2024zig/build_tcl90` +(reference snapshot: `TEMP_REFERENCE/2024zig`): `build90.zig` (tcl 9.0.1 era, last +built 2024-11-27, zig 0.14.0-dev.2074) plus the 2026-07-20 G-076 deltas - source folder +`../tcl905`, tclUuid.h copy-to-source targets derived from `tcl_source_folder`, and +`mingw_unicode_entry_point = true` (9.0.5 sources dropped `TCL_BROKEN_MAINARGS`; +tclAppInit's `_tmain` is `wmain` under `-DUNICODE`). Full provenance: +`goals/archive/G-076-tcl9-deadconsole-fix-adoption.md` (2026-07-20 entries). Goal +contract for this suite: `goals/G-096-zig-buildsuite-piperepl.md`. diff --git a/src/buildsuites/suite_tcl90/build905.zig b/src/buildsuites/suite_tcl90/build905.zig new file mode 100644 index 00000000..903b4f88 --- /dev/null +++ b/src/buildsuites/suite_tcl90/build905.zig @@ -0,0 +1,2009 @@ +const std = @import("std"); +const fs = std.fs; +const builtin = @import("builtin"); +const build_tommath = @import("build_libtommath/build_libtommath.zig").build_libtommath; +const build_zlib = @import("build_zlib/build_zlib.zig").build_zlib; + +// ******************** +// tclvfs experiments +//const tclvfs_static = @import("build_tclvfs/build_tclvfs_static.zig"); +const tclvfs_shared = @import("build_tclvfs/build_tclvfs_shared.zig"); +// ******************** + +const vqtcl_shared = @import("build_vqtcl/build_vqtcl_shared.zig"); + +const build_tclthread = @import("build_tclthread/build_tclthread.zig").build_tclthread; + +const tcl_major_version = "9"; +const tcl_nodot_version = "90"; //VER in makefile +const tcl_dot_version = "9.0"; //VERSION in makefile +const tcl_patch_suffix = "0"; +const tcl_source_folder = "../tcl905"; +const tcl_patch_level = tcl_dot_version ++ tcl_patch_suffix; //e.g 9.0b2 - generic/tcl.h TCL_PATCH_LEVEL (note TCL_PATCH_LEVEL in configure may be different e.g just the suffix "b2") + +// e.g result: tclsh90.exe & tclsh90s.exe +const tclsh_shared = "tclsh" ++ tcl_nodot_version; //leave off exe suffix - zig adds .exe automatically for windows +const tclsh_static = "tclsh" ++ tcl_nodot_version ++ "s"; + +//jmn3 +var static_build: bool = true; + +//minimum zig version +//const req_zig_version = "0.13.0"; +//comptime { +// const req_zig = std.SemanticVersion.parse(req_zig_version) catch unreachable; +// if (builtin.zig_version.order(req_zig) == .lt) { +// @compileError(std.fmt.comptimePrint( +// "Your Zig version v{} does not meet the minimum build requirement of v{}", +// .{ builtin.zig_version, req_zig }, +// )); +// } +//} + +comptime { + //const required_zig = "0.14.0-dev.300"; + const required_zig = "0.13.0-dev.8"; + const current_zig = builtin.zig_version; + const min_zig = std.SemanticVersion.parse(required_zig) catch unreachable; + if (current_zig.order(min_zig) == .lt) { + const error_message = + \\Sorry, it looks like your version of zig is too old. :-( + \\ + \\punk tcl requires development build {} + \\ + \\Please download a development ("master") build from + \\ + \\https://ziglang.org/download/ + \\ + \\ + ; + @compileError(std.fmt.comptimePrint(error_message, .{min_zig})); + } +} +const targets: []const std.Target.Query = &.{ + //.{ .cpu_arch = .aarch64, .os_tag = .macos }, + //.{ .cpu_arch = .aarch64, .os_tag = .linux }, + + //.{ .cpu_arch = .x86_64, .os_tag = .linux, .abi = .musl }, + // tried this^ - built but: + // apparently when linking against musl libc for fully static binaries, the dlopen function will only be a stub + // which stops us loading binary modules. + + //From andrewrk on https://github.com/luvit/luvi/issues/231 + //The other option zig cc provides you is "static except glibc" builds, + //and if you pick an old enough glibc version (e.g. matching holy-build-box) + //then your binary tarballs will work on any linux distro that uses glibc and + //standard dynamic linker path (which is most). This is the $arch-linux-gnu target. + + .{ .cpu_arch = .x86_64, .os_tag = .linux, .abi = .gnu }, + .{ .cpu_arch = .x86_64, .os_tag = .windows }, +}; + +pub fn build(b: *std.Build) !void { + const target = b.standardTargetOptions(.{}); + + const optimize = b.standardOptimizeOption(.{}); + + //set up and display some of the same prefix-dependent vars as Makefile for maintainability + const prefix = try std.fmt.allocPrint(b.allocator, "{s}", .{b.install_path}); + const exec_prefix = prefix; + std.debug.print("prefix {s}\n", .{prefix}); + std.debug.print("exec_prefix {s}\n", .{exec_prefix}); + const bindir = b.pathJoin(&.{ prefix, "bin" }); + std.debug.print("bindir {s}\n", .{bindir}); + const libdir = b.pathJoin(&.{ prefix, "lib" }); //TCL_PACKAGE_PATH ? + std.debug.print("libdir {s}\n", .{libdir}); + const includedir = b.pathJoin(&.{ prefix, "include" }); + std.debug.print("includedir {s}\n", .{includedir}); + const datarootdir = b.pathJoin(&.{ prefix, "share" }); + std.debug.print("datarootdir {s}\n", .{datarootdir}); + const runstatedir = b.pathJoin(&.{ prefix, "run" }); + std.debug.print("runstatedir {s}\n", .{runstatedir}); + const mandir = b.pathJoin(&.{ prefix, "man" }); + std.debug.print("mandir {s}\n", .{mandir}); + + const tcl_library = b.pathJoin(&.{ prefix, "lib", "tcl" ++ tcl_dot_version }); + std.debug.print("tcl_library {s}\n", .{tcl_library}); + + const bin_install_dir = bindir; + std.debug.print("bin_install_dir {s}\n", .{bin_install_dir}); + + const lib_install_dir = libdir; //TCL_PACKAGE_PATH ? + std.debug.print("lib_install_dir {s}\n", .{lib_install_dir}); + + const script_install_dir = tcl_library; + std.debug.print("script_install_dir {s}\n", .{script_install_dir}); + const script_install_dir_rel = b.pathJoin(&.{ "lib", "tcl" ++ tcl_dot_version }); + + const module_install_dir = b.pathJoin(&.{ script_install_dir, "..", "tcl" ++ tcl_major_version }); + std.debug.print("module_install_dir {s}\n", .{module_install_dir}); + const module_install_dir_rel = b.pathJoin(&.{ script_install_dir_rel, "..", "tcl" ++ tcl_major_version }); + + const include_install_dir = tcl_library; + std.debug.print("include_install_dir {s}\n", .{include_install_dir}); + //target.result.os.tag = . + //mac dylib? + var tcl_shlib_ext: []const u8 = undefined; + switch (target.result.os.tag) { + .windows => { + tcl_shlib_ext = try std.fmt.allocPrint(b.allocator, "{s}", .{".dll"}); + }, + .macos => { + tcl_shlib_ext = try std.fmt.allocPrint(b.allocator, "{s}", .{".dylib"}); + }, + else => { + tcl_shlib_ext = try std.fmt.allocPrint(b.allocator, "{s}", .{".so"}); + }, + } + + const tcl_dll_file = try std.fmt.allocPrint(b.allocator, "tcl" ++ tcl_nodot_version ++ "{s}", .{tcl_shlib_ext}); + std.debug.print("tcl_dll_file {s}\n", .{tcl_dll_file}); + + //const tcl_lib_file = "libtcl" ++ tcl_nodot_version ++ ".dll.a"; + const tcl_lib_file = try std.fmt.allocPrint(b.allocator, "libtcl" ++ tcl_nodot_version ++ "{s}" ++ ".a", .{tcl_shlib_ext}); + std.debug.print("tcl_lib_file {s}\n", .{tcl_lib_file}); + + const tcl_zip_file = "libtcl" ++ tcl_dot_version ++ tcl_patch_suffix ++ ".zip"; + std.debug.print("tcl_zip_file {s}\n", .{tcl_zip_file}); + const tcl_vfs_path = b.pathJoin(&.{ "libtcl.vfs", "tcl_library" }); + std.debug.print("tcl_vfs_path {s}\n", .{tcl_vfs_path}); + const tcl_vfs_root = "libtcl.vfs"; + std.debug.print("tcl_vfs_root {s}\n", .{tcl_vfs_root}); + + const tcl_stub_lib_file = "libtclstub.a"; + std.debug.print("tcl_stub_lib_file {s}\n", .{tcl_stub_lib_file}); + //const tcl_stub_lib_file = "libtclstub87.a"; + + const dde_dll_file = "tcl9dde14.dll"; + std.debug.print("dde_dll_file {s}\n", .{dde_dll_file}); + const dde_dll_file8 = "tcldde14.dll"; + std.debug.print("dde_dll_file8 {s}\n", .{dde_dll_file8}); + + const reg_dll_file = "tcl9registry13.dll"; + std.debug.print("reg_dll_file {s}\n", .{reg_dll_file}); + const reg_dll_file8 = "tclregistry13.dll"; + std.debug.print("reg_dll_file8 {s}\n", .{reg_dll_file8}); + + //pass the subdirectory as the build_tcl90/build_libtommath sees it ? + + //const tommath_sourcedir = b.pathJoin(&.{ "..", "tcl" ++ tcl_nodot_version, "libtommath" }); + const tommath_sourcedir = tcl_source_folder ++ "/libtommath"; + //var tommath_sourcedir: []const u8 = undefined; + //if (target.result.os.tag == .windows) { + // //tommath_sourcedir = tcl_source_folder ++ "/libtommath"; + // tommath_sourcedir = b.pathJoin(&.{ "..", "tcl" ++ tcl_nodot_version, "libtommath" }); + //} else { + // //tommath_sourcedir = b.pathJoin(&.{ "..", "libtommath" }); + // tommath_sourcedir = b.pathJoin(&.{ "..", "tcl" ++ tcl_nodot_version, "libtommath" }); + //} + + //const tommath_lib_compile = try build_tommath(tommath_sourcedir, b, target, optimize); + + const zlib_sourcedir = tcl_source_folder ++ "/compat/zlib"; + //const zlib_sourcedir = "../zlib" ++ "/compat/zlib"; + + var zlib_lib_compile: *std.Build.Step.Compile = undefined; + zlib_lib_compile = try build_zlib(zlib_sourcedir, b, target, optimize); + //if (target.result.os.tag != .windows) { + //} + + //dependency on tclsh being on the system - review + //despite .cmd extension - should be callable by bash on unix, but as it's a polyglot script can have no shebang so will need to be explicit - review + + //const uuid_cmd = b.addSystemCommand(&.{ + // "wrapfiletofile.cmd", + // "-prefix", + // "#define TCL_VERSION_UUID \\", + // "-prefixnl", + // "1", + // "-input", + //}); + + // ================================================ + // win/tclUuid.h & win/tclUuid.h are in the source tree but need to be created/updated + // The zig recommendation seems to be to make this a separate callable step rather than part of the standard build process. + // In this case it's required for the build, required to be in a specific source location - but shouldn't be checked in to the repo + // Ideally this should be run once on first build (and if source manifest.uuid changes) - and we shouldn't need to ask the user to specifically remember to call it. + // todo - something? + //var interp: []const []const u8 = undefined; + ////note we determine the interp based on the machine running the build - not the target + //if (builtin.os.tag == .windows) { + // interp = &.{ + // "wrapfiletofile.cmd", + // }; + //} else { + // interp = &.{ + // "bash", //explicitly use bash. Sometimes sh is linked to some other shell such as zsh, or dash (e.g debian,ubuntu) which don't understand substitution syntax like bash and ordinary posix sh do + // "wrapfiletofile.cmd", + // }; + //} + //const uuid_cmd = b.addSystemCommand(interp); + //uuid_cmd.addArgs(&.{ + // "-prefix", + // "#define TCL_VERSION_UUID \\", + // "-prefixnl", + // "1", + // "-input", + //}); + ////uuid_cmd.addFileArg(.{ .path = b.pathJoin(&.{ b.pathFromRoot(""), "..", "tcl" ++ tcl_nodot_version, "manifest.uuid" }) }); + ////uuid_cmd.addFileArg(.{ .src_path = b.path(b.pathJoin(&.{ b.pathFromRoot(""), "..", "tcl" ++ tcl_nodot_version, "manifest.uuid" })) }); + ////uuid_cmd.addFileArg(b.path(b.pathJoin(&.{ b.pathFromRoot(""), "..", "tcl" ++ tcl_nodot_version, "manifest.uuid" }))); + //uuid_cmd.addFileArg(b.path(tcl_source_folder ++ "/manifest.uuid" )); + //uuid_cmd.addArg("-output"); + //const tcluuid_file1 = uuid_cmd.addOutputFileArg("tclUuid.h"); + + const prepare_source = b.step("prepare-source", "patch and prep source"); + const wrap_exe = b.addExecutable(.{ + .name = "wrapfiletofile", + .root_source_file = b.path("tools/wrapfiletofile.zig"), + .target = b.host, + }); + //const tool_step = b.addRunArtifact(tool); + const wrap_run = b.addRunArtifact(wrap_exe); + //const wrap_install = b.addInstallArtifact(wrap_exe, .{}); + + wrap_run.addArgs(&.{ + "-prefix", + "#define TCL_VERSION_UUID \\", + "-prefixnl", + "1", + "-input", + }); + wrap_run.addFileArg(b.path(tcl_source_folder ++ "/manifest.uuid")); + wrap_run.addArg("-output"); + const tcluuid_file1 = wrap_run.addOutputFileArg("tclUuid.h"); + + //zig prior to 0.14 - addCopyFileToSource worked with b.addWriteFiles + //zig post 0.14 - b.addUpdateSourcFiles() is required to use addCopyFileToSource + //const wf_uuidh = b.addWriteFiles(); + const wf_uuidh = b.addUpdateSourceFiles(); + + //var uuidh: std.Build.LazyPath = undefined; + if (target.result.os.tag == .windows) { + wf_uuidh.addCopyFileToSource(tcluuid_file1, b.pathJoin(&.{ tcl_source_folder, "win", "tclUuid.h" })); + } else { + wf_uuidh.addCopyFileToSource(tcluuid_file1, b.pathJoin(&.{ tcl_source_folder, "unix", "tclUuid.h" })); + } + wf_uuidh.step.dependOn(&wrap_run.step); + prepare_source.dependOn(&wf_uuidh.step); + + //const copy_uuid = b.addInstallFileWithDir(tcluuid_file1, .prefix, b.pathJoin(&.{ "lib", "tclUuid.h.copy" })); + //copy_uuid.step.dependOn(&wf_uuidh.step); + //b.getInstallStep().dependOn(©_uuid.step); + // ================================================ + + var ac_flags = std.ArrayList([]const u8).init(b.allocator); + defer ac_flags.deinit(); + try ac_flags.appendSlice(&.{ + "-pipe", + "-finput-charset=UTF-8", + "-DPACKAGE_NAME=\"tcl\"", + "-DPACKAGE_TARNAME=\"tcl\"", + "-DPACKAGE_VERSION=\"" ++ tcl_dot_version ++ "\"", + "-DPACKAGE_STRING=\"tcl " ++ tcl_dot_version ++ "\"", + "-DPACKAGE_BUGREPORT=\"\"", + "-DPACKAGE_URL=\"\"", + "-DTCL_CFGVAL_ENCODING=\"utf-8\"", + //WARNING - it is not enough to set TCL_COMPILE_DEBUG & TCL_COMPILE_STATS to 0 - if they exist they will affect performance + //"-DTCL_COMPILE_DEBUG=0", + //"-DTCL_COMPILE_STATS=0", + "-DTCL_CFG_DO64BIT=1", + "-DHAVE_NO_SEH=1", //required for tclWinFCmd.c or we get undeclared identifier '__try' + //JMN2 + //"-DHAVE_CPUID=1", + //"-DHAVE_STDLIB_H=1", + //"-DHAVE_STRING_H=1", + //"-DHAVE_INTTYPES_H=1", + //"-DHAVE_STDINT_H=1", + //"-DHAVE_STRINGS_H=1", + //"-DHAVE_SYS_STAT_H=1", + //"-DHAVE_SYS_TYPES_H=1", + //"-DHAVE_UNISTD_H=1", //probably needs to be 0 if using msvc ? + //"-DSTDC_HEADERS=1", + //"-DNDEBUG=1", + //"-DHAVE_STDBOOL_H=1", + //"-DHAVE_CAST_TO_UNION=1", + //"-DHAVE_INTPTR_T=1", + //"-DHAVE_UINTPTR_T=1", + //"-DHAVE_INTRIN_H=1", + "-DMP_64BIT=1", + "-DHAVE_ZLIB=1", + "-DZIPFS_BUILD=1", //JMN todo + "-DTCL_CFG_OPTIMIZED=1", + "-DTCL_THREADS=1", //probably not required + try std.fmt.allocPrint(b.allocator, "-DTCL_PACKAGE_PATH=\"{s}\"", .{lib_install_dir}), + }); + //"-DTCL_NO_DEPRECATED", + //"-fno-lto", + //"-DMODULE_SCOPE=extern", + if (target.result.os.tag == .windows) { + try ac_flags.appendSlice(&.{ + //"-DTCL_WITH_EXTERNAL_TOMMATH", //required for windows when using tcltommath that *doesn't* come with tcl (?) + "-DHAVE_STDIO_H=1", + "-DMODULE_SCOPE=extern", + "-DHAVE_WSPIAPI_H=1", //windows specific? + }); + //jjj + //try ac_flags.appendSlice(&.{ + // "-DHAVE_STDIO_H=1", + // "-DHAVE_STDLIB_H=1", + // "-DHAVE_STRING_H=1", + // "-DHAVE_INTTYPES_H=1", + // "-DHAVE_STDINT_H=1", + // "-DHAVE_STRINGS_H=1", + // "-DHAVE_SYS_STAT_H=1", + // "-DHAVE_SYS_TYPES_H=1", + // "-DHAVE_UNISTD_H=1", + // "-DHAVE_SYS_TIME_H=1", + // // + // "-DNO_SYS_WAIT_H=1", + // "-DNO_DLFCN_H=1", + // "-DHAVE_SYS_PARAM_H=1", + // // + // "-DHAVE_STDBOOL_H=1", + // // + //}); + + //added to try to fix 'linsert {} 0 a b' crash + //try ac_flags.appendSlice(&.{ + // "-DSTDC_HEADERS=1", + // "-D_REENTRANT=1", + // "-D_THREAD_SAFE=1", + // "-DHAVE_PTHREAD_ATTR_SETSTACKSIZE=1", + // "-DHAVE_DECL_PTHREAD_MUTEX_RECURSIVE=1", + // // + // "-DMODULE_SCOPE=extern", + // "-DHAVE_CAST_TO_UNION=1", + // "-DNDEBUG=1", + // "-DMP_PREC=4", + // "-D_FILE_OFFSET_BITS=64", + // "-DHAVE_LSEEK64=1", + // "-DHAVEGETCWD=1", + // "-DHAVE_MKSTEMP=1", + // "-DNO_GETWD=1", + // "-DNO_WAIT3=1", + // "-DNO_FORK=1", + // "-DNO_MKNOD=1", + // "-DNO_TCDRAIN=1", + // "-DNO_UNAME=1", + // "-DNOREALPATH=1", + // "-DNEED_FAKE_RFC2553=1", + // "-DHAVE_DECL_GETHOSTBYNAME_R=0", + // "-DHAVE_DECL_GETHOSTBYADDR_R=0", + // "-DNO_FD_SET=1", + // // + // "-DHAVE_MKTIME=1", + // "-DHAVE_TIMEZONE_VAR=1", + // "-DHAVE_STRUCT_STAT_ST_RDEV=1", + // "-DNO_FSTATFS=1", + // "-Duid_t=int", + // "-Dgid_t=int", + // "-DHAVE_INTPTR_T=1", + // "-DHAVE_UINTPTR_T=1", + // "-DNO_UNION_WAIT=1", + // "-DHAVE_SIGNED_CHAR=1", + // "-DHAVE_PUTENV_THAT_COPIES=1", + // "-DTCL_UNLOAD_DLLS=1", + // "-DHAVE_CPUID=1", + //}); + + //try ac_flags.appendSlice(&.{ + // "-Dsocklen_t=int", + //}); + + //-DHAVE_ZLIB being deprecated 2024-10 + try ac_flags.appendSlice(&.{ + "-DHAVE_ZLIB=1", + "-DZIPFS_BUILD=1", + //"-DSUPPORT_BUILTIN_ZIP_INSTALL=1", // won't compile win 2024-10-11 - bug reported + }); + + try ac_flags.appendSlice(&.{ + // should be for static build only(?) + "-DTCL_WITH_INTERNAL_ZLIB", + "-DTCL_TOMMATH", + }); + } else { + try ac_flags.appendSlice(&.{ + //"-DTCL_WITH_EXTERNAL_TOMMATH", + "-DHAVE_MEMORY_H=1", + "-DMODULE_SCOPE=extern __attribute__((__visibility__(\"hidden\")))", + "-DHAVE_HIDDEN=1", + "-DHAVE_SYS_PARAM_H=1", + "-DUSE_THREAD_ALLOC=1", + "-D_REENTRANT=1", + "-D_THREAD_SAFE=1", + "-DHAVE_PTHREAD_ATTR_SETSTACKSIZE=1", + "-DHAVE_PTHREAD_ATFORK=1", + + "-D_LARGEFILE64_SOURCE=1", + "-DTCL_WIDE_INT_IS_LONG=1", + "-DHAVE_GETCWD=1", + "-DHAVE_MKSTEMP=1", + "-DHAVE_OPENDIR=1", + "-DHAVE_STRTOL=1", + "-DHAVE_WAITPID=1", + "-DHAVE_GETNAMEINFO=1", + "-DHAVE_GETADDRINFO=1", + "-DHAVE_FREEADDRINFO=1", + "-DHAVE_GAI_STRERROR=1", + "-DHAVE_STRUCT_ADDRINFO=1", + "-DHAVE_STRUCT_IN6_ADDR=1", + "-DHAVE_STRUCT_SOCKADDR_IN6=1", + "-DHAVE_STRUCT_SOCKADDR_STORAGE=1", + "-DHAVE_GETPWUID_R_5=1", + "-DHAVE_GETPWUID_R=1", + "-DHAVE_GETPWNAM_R_5=1", + "-DHAVE_GETPWNAM_R=1", + "-DHAVE_GETGRGID_R_5=1", + "-DHAVE_GETGRGID_R=1", + "-DHAVE_GETGRNAME_R_5=1", + "-DHAVE_GETGRNAME_R=1", + "-DHAVE_DECL_GETHOSTBYNAME_R=1", + "-DHAVE_GETHOSTBYNAME_R_6=1", + "-DHAVE_GETHOSTBYNAME_R=1", + "-DHAVE_DECL_GETHOSTBYADDR_R=1", + "-DHAVE_GETHOSTBYADDR_R_8=1", + "-DHAVE_GETHOSTBYADDR_R=1", + "-DHAVE_TERMIOS_H=1", + "-DHAVE_SYS_IOCTL_H=1", + "-DHAVE_SYS_TIME_H=1", + "-DTIME_WITH_SYS_TIME=1", + "-DHAVE_GMTIME_R=1", + "-DHAVE_LOCALTIME_R=1", + "-DHAVE_TM_GMTOFF=1", + "-DHAVE_TIMEXONE_VAR=1", + "-DHAVE_STRUCT_STAT_ST_BLOCKS=1", + "-DHAVE_STRUCT_STAT_ST_BLKSIZE=1", + "-DHAVE_BLKCNT_T=1", + + "-DNO_UNION_WAIT=1", + "-DHAVE_SIGNED_CHAR=1", + "-DHAVE_LANGINFO=1", + "-DHAVE_MKSTEMPS=1", + //"-DHAVE_FTS=1", + + "-DTCL_UNLOAD_DLLS=1", + //"-fPIC", + + try std.fmt.allocPrint(b.allocator, "-DTCL_SHLIB_EXT=\"{s}\"", .{tcl_shlib_ext}), + try std.fmt.allocPrint(b.allocator, "-DTCL_LIBRARY=\"{s}\"", .{tcl_library}), + }); + } + + //msvc - test + //try ac_flags.appendSlice(&.{ + // "-Dinline=__inline", + // "-D_CRT_SECURE_NO_DEPRECATE", + // "-D_CRT_NONSTDC_NO_DEPRECATE" + //}); + + //"-Wl,-input-charset=UTF-8", + //"-finput-charset=UTF-8" + + var warning_flags = std.ArrayList([]const u8).init(b.allocator); + defer warning_flags.deinit(); + try warning_flags.appendSlice(&.{ + "-Wall", + "-Wextra", + "-Wshadow", + "-Wundef", + "-Wwrite-strings", + "-Wpointer-arith", + "-Wc++-compat", + "-fextended-identifiers", + }); + //"-Werror=return-type", + var optimize_flags = std.ArrayList([]const u8).init(b.allocator); + defer optimize_flags.deinit(); + + //windows? + //try optimize_flags.appendSlice(&.{ + // "-O0", + // "-fomit-frame-pointer", + // //"-g0", + //}); + //try optimize_flags.appendSlice(&.{ + // "-O3", + // "-fomit-frame-pointer", + // //"-g0", + //}); + try optimize_flags.appendSlice(&.{ + "-O3", //?? + //"-O2", + "-fomit-frame-pointer", + //"-g", + "-finput-charset=UTF-8", + }); + //"-fomit-frame-pointer", + + var c_flags = std.ArrayList([]const u8).init(b.allocator); + defer c_flags.deinit(); + try c_flags.appendSlice(optimize_flags.items); + try c_flags.appendSlice(&.{ + "-DMP_FIXED_CUTOFFS", + "-fno-sanitize=undefined", //required on windows to fix: linsert {} 0 a a crash + "-fno-sanitize-trap=undefined", + //"-DMP_NO_STDINT", + //"-D__USE_MINGW_ANSI_STDIO=0", + //"-DTCL_MEM_DEBUG", //must be defined for all modules, or undefined for all modules that are going to be linked together + }); + if (target.result.os.tag == .linux) { + //required to avoid error on linux-musl (at least) - review - check other targets + try c_flags.appendSlice(&.{ + "-fno-sanitize=undefined", + }); + //without it, gdb gives: + //Program received signal SIGILL, Illegal instruction. + //0x0000000001b6c0e6 in Tcl_UniCharToUtfDString (uniStr=0x7fffffffd605, uniLength=0, dsPtr=0x7fffffffcc00) at /mnt/c/buildtcl/2024zig/tcl90/generic/tclUtf.c:332 + //332 while (*w != '\0') { + } + + var config_flags = std.ArrayList([]const u8).init(b.allocator); + defer config_flags.deinit(); + //try config_flags.appendSlice(base_flags.items); + //can't use ++ for non comptime values such as libdir,bindir... + try config_flags.appendSlice(&.{ + try std.fmt.allocPrint(b.allocator, "-DCFG_RUNTIME_LIBDIR=\"{s}\"", .{libdir}), + try std.fmt.allocPrint(b.allocator, "-DCFG_RUNTIME_BINDIR=\"{s}\"", .{bindir}), + try std.fmt.allocPrint(b.allocator, "-DCFG_RUNTIME_INCDIR=\"{s}\"", .{includedir}), + try std.fmt.allocPrint(b.allocator, "-DCFG_RUNTIME_SCRDIR=\"{s}\"", .{tcl_library}), + try std.fmt.allocPrint(b.allocator, "-DCFG_RUNTIME_DOCDIR=\"{s}\"", .{mandir}), + }); + //todo - set default install dirs: windows c:/tcl90, bsd /usr/local/tcl90?, linux /opt/tcl90? + try config_flags.appendSlice(&.{ + try std.fmt.allocPrint(b.allocator, "-DCFG_INSTALL_LIBDIR=\"{s}\"", .{libdir}), + try std.fmt.allocPrint(b.allocator, "-DCFG_INSTALL_BINDIR=\"{s}\"", .{bindir}), + try std.fmt.allocPrint(b.allocator, "-DCFG_INSTALL_INCDIR=\"{s}\"", .{includedir}), + try std.fmt.allocPrint(b.allocator, "-DCFG_INSTALL_SCRDIR=\"{s}\"", .{tcl_library}), + try std.fmt.allocPrint(b.allocator, "-DCFG_INSTALL_DOCDIR=\"{s}\"", .{mandir}), + }); + + //CFG_RUNTIME_DLLFILE used also on unix? seems to be in generic/tclPkgConfig.c + try config_flags.appendSlice(&.{ + //"-DCFG_RUNTIME_DLLFILE=\"tcl" ++ tcl_nodot_version ++ ".dll\"", + try std.fmt.allocPrint(b.allocator, "-DCFG_RUNTIME_DLLFILE=\"{s}\"", .{tcl_dll_file}), + }); + + //BUILD_ needs to be defined for windows + if (target.result.os.tag == .windows) { + try config_flags.appendSlice(&.{ + "-DBUILD_tcl", + }); + } + + //CC_SWITCHES = -I"${BUILD_DIR}" -I"${GENERIC_DIR_NATIVE}" -I"${TOMMATH_DIR_NATIVE}" \ + //-I"${ZLIB_DIR_NATIVE}" -I"${WIN_DIR_NATIVE}" \ + //${CFLAGS} ${CFLAGS_WARNING} ${SHLIB_CFLAGS} -DMP_PREC=4 \ + //${AC_FLAGS} ${COMPILE_DEBUG_FLAGS} ${NO_DEPRECATED_FLAGS} + var cc_flags = std.ArrayList([]const u8).init(b.allocator); + defer cc_flags.deinit(); + try cc_flags.appendSlice(c_flags.items); + try cc_flags.appendSlice(warning_flags.items); + try cc_flags.appendSlice(config_flags.items); + + try cc_flags.appendSlice(&.{ + "-DMP_PREC=4", + }); + try cc_flags.appendSlice(ac_flags.items); + + var base_flags = std.ArrayList([]const u8).init(b.allocator); + defer base_flags.deinit(); + try base_flags.appendSlice(&.{ + "-municode", + "-Wl,--subsystem,windows", + //"-DTCL_MEM_DEBUG", //must be defined for all modules, or undefined for all modules that are going to be linked together + }); + + if (target.result.os.tag == .windows) { + //TODO win64-arm, win32(?) + //b.installFile(tcl_source_folder ++ "/compat/zlib/win64/zlib1.dll", "bin/zlib1.dll"); + b.installFile(tcl_source_folder ++ "/libtommath/win64/libtommath.dll", "bin/libtommath.dll"); + + //TODO - flag to allow independent building of static vs shared build to give failure independence + // if STATIC_BUILD + //b.installFile(tcl_source_folder ++ "/compat/zlib/win64/zlib1.dll", "lib/zdll.lib"); + b.installFile(tcl_source_folder ++ "/libtommath/win64/tommath.lib", "lib/tommath.lib"); + } + + // ================================================================ + //tcl8.7? + //STUB_OBJS = \ + // tclStubLib.$(OBJEXT) \ + // tclTomMathStubLib.$(OBJEXT) \ + // tclOOStubLib.$(OBJEXT) \ + // tclWinPanic.$(OBJEXT) + //tcl9 + //STUB_OBJS = + //tclStubLib.$(OBJEXT) + //tclStubCall.$(OBJEXT) + //tclStubLibTbl.$(OBJEXT) + //tclTomMathStubLib.$(OBJEXT) + //tclOOStubLib.$(OBJEXT) + //tclWinPanic.$(OBJEXT) + + const finalstublib = b.addStaticLibrary(.{ + .name = if (target.result.os.tag == .windows) "libtclstub" else "tclstub", + .target = target, + .optimize = optimize, + }); + var stublib_flags = std.ArrayList([]const u8).init(b.allocator); + try stublib_flags.appendSlice(cc_flags.items); + try stublib_flags.appendSlice(&.{ + "-DSTATIC_BUILD", + "-fno-lto", + }); + //finalstublib.addIncludePath(.{ .path = tcl_source_folder ++ "/generic" }); + //finalstublib.addIncludePath(.{ .src_path = tcl_source_folder ++ "/generic" }); + finalstublib.addIncludePath(b.path(tcl_source_folder ++ "/generic")); + if (target.result.os.tag == .windows) { + //finalstublib.addIncludePath(.{ .path = tcl_source_folder ++ "/win" }); + finalstublib.addIncludePath(b.path(tcl_source_folder ++ "/win")); + } else { + //finalstublib.addIncludePath(.{ .path = tcl_source_folder ++ "/unix" }); + finalstublib.addIncludePath(b.path(tcl_source_folder ++ "/unix")); + } + if (target.result.os.tag == .windows) { + finalstublib.addIncludePath(b.path(tcl_source_folder ++ "/libtommath")); + finalstublib.addIncludePath(b.path(tcl_source_folder ++ "/compat/zlib")); + } else { + finalstublib.addIncludePath(b.path(tommath_sourcedir)); + finalstublib.addIncludePath(b.path(zlib_sourcedir)); + } + finalstublib.addCSourceFile(.{ + .file = b.path(tcl_source_folder ++ "/generic/tclStubLib.c"), + .flags = stublib_flags.items, + }); + //tcl9 + + var stublib_call_flags = std.ArrayList([]const u8).init(b.allocator); + try stublib_call_flags.appendSlice(cc_flags.items); + try stublib_call_flags.appendSlice(config_flags.items); + try stublib_call_flags.appendSlice(&.{ + "-DSTATIC_BUILD", + //try std.fmt.allocPrint(b.allocator, "-DCFG_RUNTIME_BINDIR=\"{s}\"", .{ bindir }), + }); + //if (target.result.os.tag == .windows) { + // try stublib_call_flags.appendSlice(&.{ + // try std.fmt.allocPrint(b.allocator, "-DCFG_RUNTIME_DLLFILE=\"{s}\"", .{ tcl_dll_file }), + // }); + //} + + finalstublib.addCSourceFile(.{ + .file = b.path(tcl_source_folder ++ "/generic/tclStubCall.c"), + .flags = stublib_call_flags.items, + }); + //tcl9 + var stublib_tbl_flags = std.ArrayList([]const u8).init(b.allocator); + try stublib_tbl_flags.appendSlice(cc_flags.items); + try stublib_tbl_flags.appendSlice(&.{ + "-DSTATIC_BUILD", + }); + finalstublib.addCSourceFile(.{ + .file = b.path(tcl_source_folder ++ "/generic/tclStubLibTbl.c"), + .flags = stublib_tbl_flags.items, + }); + var stublib_tom_flags = std.ArrayList([]const u8).init(b.allocator); + try stublib_tom_flags.appendSlice(cc_flags.items); + try stublib_tom_flags.appendSlice(&.{ + "-fno-lto", + }); + finalstublib.addCSourceFile(.{ + .file = b.path(tcl_source_folder ++ "/generic/tclTomMathStubLib.c"), + .flags = stublib_tom_flags.items, + }); + var stublib_oo_flags = std.ArrayList([]const u8).init(b.allocator); + try stublib_oo_flags.appendSlice(cc_flags.items); + try stublib_oo_flags.appendSlice(&.{ + "-fno-lto", + }); + finalstublib.addCSourceFile(.{ + .file = b.path(tcl_source_folder ++ "/generic/tclOOStubLib.c"), + .flags = stublib_oo_flags.items, + }); + var winpaniclib_flags = std.ArrayList([]const u8).init(b.allocator); + try winpaniclib_flags.appendSlice(cc_flags.items); + try winpaniclib_flags.appendSlice(&.{ + "-DSTATIC_BUILD", + }); + if (target.result.os.tag == .windows) { + finalstublib.addCSourceFile(.{ + .file = b.path(tcl_source_folder ++ "/win/tclWinPanic.c"), + .flags = winpaniclib_flags.items, + }); + } + + var windde_obj_flags = std.ArrayList([]const u8).init(b.allocator); + defer windde_obj_flags.deinit(); + try windde_obj_flags.appendSlice(cc_flags.items); + try windde_obj_flags.appendSlice(&.{}); + var winreg_obj_flags = std.ArrayList([]const u8).init(b.allocator); + defer winreg_obj_flags.deinit(); + try winreg_obj_flags.appendSlice(cc_flags.items); + try winreg_obj_flags.appendSlice(&.{}); + + if (target.result.os.tag == .windows) { + finalstublib.addCSourceFile(.{ + .file = b.path(tcl_source_folder ++ "/win/tclWinDde.c"), + .flags = windde_obj_flags.items, + }); + finalstublib.addCSourceFile(.{ + .file = b.path(tcl_source_folder ++ "/win/tclWinReg.c"), + .flags = winreg_obj_flags.items, + }); + } + + finalstublib.linkLibC(); + + b.installArtifact(finalstublib); + + // ================================================================ + + // Special case object targets + + const winpaniclib = b.addObject(.{ + .name = "tclWinPanic", + .target = target, + .optimize = optimize, + }); + if (target.result.os.tag == .windows) { + winpaniclib.addIncludePath(b.path(tcl_source_folder ++ "/generic/")); + winpaniclib.addIncludePath(b.path(tcl_source_folder ++ "/win/")); + winpaniclib.addIncludePath(b.path(tcl_source_folder ++ "/libtommath/")); + winpaniclib.addIncludePath(b.path(tcl_source_folder ++ "/compat/zlib/")); + winpaniclib.addCSourceFile(.{ + .file = b.path(tcl_source_folder ++ "/win/tclWinPanic.c"), + .flags = winpaniclib_flags.items, + }); + winpaniclib.linkLibC(); + } + + if (target.result.os.tag == .windows) { + const winreg_obj = b.addObject(.{ + .name = "tclWinReg", + .target = target, + .optimize = optimize, + }); + winreg_obj.addIncludePath(b.path(tcl_source_folder ++ "/generic/")); + winreg_obj.addIncludePath(b.path(tcl_source_folder ++ "/win/")); + winreg_obj.addIncludePath(b.path(tcl_source_folder ++ "/libtommath/")); + winreg_obj.addIncludePath(b.path(tcl_source_folder ++ "/compat/zlib/")); + winreg_obj.addCSourceFile(.{ + .file = b.path(tcl_source_folder ++ "/win/tclWinReg.c"), + .flags = winreg_obj_flags.items, + }); + winreg_obj.linkLibC(); + // + + const windde_obj = b.addObject(.{ + .name = "tclWinDde", + .target = target, + .optimize = optimize, + }); + windde_obj.addIncludePath(b.path(tcl_source_folder ++ "/generic/")); + windde_obj.addIncludePath(b.path(tcl_source_folder ++ "/win/")); + windde_obj.addIncludePath(b.path(tcl_source_folder ++ "/libtommath/")); + windde_obj.addIncludePath(b.path(tcl_source_folder ++ "/compat/zlib/")); + windde_obj.addCSourceFile(.{ + .file = b.path(tcl_source_folder ++ "/win/tclWinDde.c"), + .flags = windde_obj_flags.items, + }); + windde_obj.linkLibC(); + //DDE_OBJS + } + + // for linking to Tclsh + + var appinit_path: []const u8 = undefined; + if (target.result.os.tag == .windows) { + appinit_path = tcl_source_folder ++ "/win/tclAppInit.c"; + } else { + appinit_path = tcl_source_folder ++ "/unix/tclAppInit.c"; + } + + //end special case object targets + + // ------------------------------------------------------------------ + + //const stubarchive_install_step = &b.addInstallFileWithDir(stubarchive.getEmittedBin(), .prefix, "libtclstubXX.lib").step; + //b.getInstallStep().dependOn(&b.addInstallFileWithDir(stubarchive.getEmittedBin(),.prefix,"libtclstubXX.a").step); + //b.getInstallStep().dependOn(stubarchive_install_step); + + const wf = b.addWriteFiles(); + const stublib_file = b.fmt("buildarchive\\{s}", .{finalstublib.out_filename}); + const lz_stublib_file = wf.addCopyFile(finalstublib.getEmittedBin(), stublib_file); + + //s flag to ar should be equivalent to running ranlib + const create_stublib_archive = b.addSystemCommand(&.{ + "zig", + "ar", + "crs", + "--", + }); + + //no tcl_nodot_version for tcl9 libtclstub.a + const stublib_archive_file = create_stublib_archive.addOutputFileArg("buildarchive\\" ++ tcl_stub_lib_file); + //const out_ranlib = run_ranlib.addOutputFileArg("buildarchive\\tclstub.lib"); + create_stublib_archive.addFileArg(lz_stublib_file); + + const installed_stublib_archive = b.addInstallFileWithDir(stublib_archive_file, .prefix, "lib\\" ++ tcl_stub_lib_file); + //const stublib_archive = b.addInstallFileWithDir(out_ranlib , .prefix, "lib\\tclstub.lib"); + installed_stublib_archive.step.dependOn(&create_stublib_archive.step); + //b.getInstallStep().dependOn(&stublib_archive.step); + + //dde_dll_file and reg_dll_file need to be added to the zip file + var dll_flags = std.ArrayList([]const u8).init(b.allocator); + //try dll_flags.appendSlice(base_flags.items); + try dll_flags.appendSlice(&.{ + "-pipe", + "-municode", + }); + if (target.result.os.tag == .windows) { + try dll_flags.appendSlice(&.{ + "-Wl,--enable-auto-image-base", + "-static-libgcc", + }); + } else {} + + //"-Wl,-static-libgcc", + + //std.fs.path.stem(dde_dll_file) ;// tcl9dde14.dll - tcl9 + //std.fs.path.stem(dde_dll_file8) ;// tcldde14.dll - tcl8 + const dde_dll = b.addSharedLibrary(.{ + .name = std.fs.path.stem(dde_dll_file), + .target = target, + .optimize = optimize, + }); + dde_dll.step.dependOn(&installed_stublib_archive.step); + dde_dll.step.dependOn(&finalstublib.step); + + var install_dde_dll: *std.Build.Step.InstallArtifact = undefined; + if (target.result.os.tag == .windows) { + dde_dll.addIncludePath(b.path(tcl_source_folder ++ "/generic/")); + dde_dll.addIncludePath(b.path(tcl_source_folder ++ "/win/")); + dde_dll.addCSourceFile(.{ + .file = b.path(tcl_source_folder ++ "/win/TclWinDde.c"), + .flags = dll_flags.items, + }); + //LIBS + //dde_dll.addLibraryPath(stublib_archive.source.dirname()); + dde_dll.addObjectFile(finalstublib.getEmittedBin()); + //dde_dll.addObjectFile(installed_stublib_archive.source); + //dde_lib.linkSystemLibrary("tclstub" ++ tcl_nodot_version); //libtclstubXX.a + //dde_lib.linkSystemLibrary("tclstub"); //tcl9 + dde_dll.linkSystemLibrary("netapi32"); + dde_dll.linkSystemLibrary("kernel32"); + dde_dll.linkSystemLibrary("user32"); + dde_dll.linkSystemLibrary("advapi32"); + dde_dll.linkSystemLibrary("userenv"); + dde_dll.linkSystemLibrary("ws2_32"); + //dde_dll.addObjectFile(.{ .path = tcl_source_folder ++ "/libtommath/win64/libtommath.dll.a" }); + //dde_dll.addObjectFile(.{ .path = tcl_source_folder ++ "/compat/zlib/win64/libz.dll.a" }); + dde_dll.addLibraryPath(b.path(tcl_source_folder ++ "/compat/zlib/win64")); + dde_dll.addLibraryPath(b.path(tcl_source_folder ++ "/libtommath/win64")); + //dde_dll.linkSystemLibrary("zlib1"); + //### JMN + dde_dll.linkLibrary(zlib_lib_compile); + dde_dll.linkSystemLibrary("tommath"); + dde_dll.linkLibC(); + //b.installArtifact(dde_dll); + install_dde_dll = b.addInstallArtifact( + dde_dll, + .{ + .dest_dir = .{ + .override = .{ .custom = "./lib/tcl" ++ tcl_dot_version ++ "/dde" }, + }, + }, + ); + //b.default_step.dependOn(&install_dde_dll.step); + } + + //tcl9registry13.dll - tcl9 + //tclregistry13.dll - tcl8 + const reg_dll = b.addSharedLibrary(.{ + .name = std.fs.path.stem(reg_dll_file), + .target = target, + .optimize = optimize, + }); + //reg_lib.step.dependOn(&stublib_archive.step); + reg_dll.step.dependOn(&finalstublib.step); + var install_reg_dll: *std.Build.Step.InstallArtifact = undefined; + if (target.result.os.tag == .windows) { + reg_dll.addIncludePath(b.path(tcl_source_folder ++ "/generic/")); + reg_dll.addIncludePath(b.path(tcl_source_folder ++ "/win/")); + reg_dll.addCSourceFile(.{ + .file = b.path(tcl_source_folder ++ "/win/TclWinReg.c"), + .flags = dll_flags.items, + }); + //LIBS + //reg_dll.addLibraryPath(stublib_archive.source.dirname()); + reg_dll.addObjectFile(finalstublib.getEmittedBin()); + //reg_dll.linkSystemLibrary("tclstub" ++ tcl_nodot_version); //libtclstubXX.a + //reg_dll.linkSystemLibrary("tclstub"); //tcl9 + reg_dll.linkSystemLibrary("netapi32"); + reg_dll.linkSystemLibrary("kernel32"); + reg_dll.linkSystemLibrary("user32"); + reg_dll.linkSystemLibrary("advapi32"); + reg_dll.linkSystemLibrary("userenv"); + reg_dll.linkSystemLibrary("ws2_32"); + //reg_dll.addObjectFile(.{ .path = tcl_source_folder ++ "/libtommath/win64/libtommath.dll.a" }); + //reg_dll.addObjectFile(.{ .path = tcl_source_folder ++ "/compat/zlib/win64/libz.dll.a" }); + reg_dll.addLibraryPath(b.path(tcl_source_folder ++ "/compat/zlib/win64")); + reg_dll.addLibraryPath(b.path(tcl_source_folder ++ "/libtommath/win64")); + //reg_dll.linkSystemLibrary("zlib1"); + //### JMN + reg_dll.linkLibrary(zlib_lib_compile); + reg_dll.linkSystemLibrary("tommath"); + reg_dll.linkLibC(); + //b.installArtifact(reg_dll); + + //https://www.reddit.com/r/Zig/comments/1cxn08x/question_how_do_i_setup_a_custom_install_location/ + install_reg_dll = b.addInstallArtifact( + reg_dll, + .{ + .dest_dir = .{ + .override = .{ .custom = "./lib/tcl" ++ tcl_dot_version ++ "/registry" }, + }, + }, + ); + //b.default_step.dependOn(&install_reg_dll.step); + } + + //COREOBJS + var generic_sources = std.ArrayList([]const u8).init(b.allocator); + defer generic_sources.deinit(); + try generic_sources.append(tcl_source_folder ++ "/generic/regcomp.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/regexec.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/regfree.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/regerror.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclAlloc.c"); + + //tcl9.0 + try generic_sources.append(tcl_source_folder ++ "/generic/tclArithSeries.c"); + + try generic_sources.append(tcl_source_folder ++ "/generic/tclAssembly.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclAsync.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclBasic.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclBinary.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclCkalloc.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclClock.c"); + + //tcl9.0 + try generic_sources.append(tcl_source_folder ++ "/generic/tclClockFmt.c"); //tcl 9? + + try generic_sources.append(tcl_source_folder ++ "/generic/tclCmdAH.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclCmdIL.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclCmdMZ.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclCompCmds.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclCompCmdsGR.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclCompCmdsSZ.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclCompExpr.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclCompile.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclConfig.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclDate.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclDictObj.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclDisassemble.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclEncoding.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclEnsemble.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclEnv.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclEvent.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclExecute.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclFCmd.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclFileName.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclGet.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclHash.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclHistory.c"); + + //tcl9.0 + try generic_sources.append(tcl_source_folder ++ "/generic/tclIcu.c"); + + try generic_sources.append(tcl_source_folder ++ "/generic/tclIndexObj.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclInterp.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclIO.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclIOCmd.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclIOGT.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclIORChan.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclIORTrans.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclIOSock.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclIOUtil.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclLink.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclLiteral.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclListObj.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclLoad.c"); + //tclmainW mainw_obj + //try generic_sources.append(tcl_source_folder ++ "/generic/tclMainW.c"); + + try generic_sources.append(tcl_source_folder ++ "/generic/tclMain.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclNamesp.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclNotify.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclOO.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclOOBasic.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclOOCall.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclOODefineCmds.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclOOInfo.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclOOMethod.c"); + + //tcl9.0 + try generic_sources.append(tcl_source_folder ++ "/generic/tclOOProp.c"); + + try generic_sources.append(tcl_source_folder ++ "/generic/tclOOStubInit.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclObj.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclOptimize.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclPanic.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclParse.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclPathObj.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclPipe.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclPkg.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclPkgConfig.c"); //pkgconfig_obj + try generic_sources.append(tcl_source_folder ++ "/generic/tclPosixStr.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclPreserve.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclProc.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclProcess.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclRegexp.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclResolve.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclResult.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclScan.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclStringObj.c"); + + //tcl 9.0 + try generic_sources.append(tcl_source_folder ++ "/generic/tclStrIdxTree.c"); + + try generic_sources.append(tcl_source_folder ++ "/generic/tclStrToD.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclStubInit.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclThread.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclThreadAlloc.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclThreadJoin.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclThreadStorage.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclTimer.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclTomMathInterface.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclTrace.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclUtf.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclUtil.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclVar.c"); + try generic_sources.append(tcl_source_folder ++ "/generic/tclZipfs.c"); //zipfs_obj + try generic_sources.append(tcl_source_folder ++ "/generic/tclZlib.c"); + + //PLATFORMOBJS - win_source or unix_sources + var win_sources = std.ArrayList([]const u8).init(b.allocator); + defer win_sources.deinit(); + var unix_sources = std.ArrayList([]const u8).init(b.allocator); + defer unix_sources.deinit(); + + switch (target.result.os.tag) { + .windows => { + try win_sources.append(tcl_source_folder ++ "/win/tclWin32Dll.c"); + try win_sources.append(tcl_source_folder ++ "/win/tclWinChan.c"); + try win_sources.append(tcl_source_folder ++ "/win/tclWinConsole.c"); + try win_sources.append(tcl_source_folder ++ "/win/tclWinSerial.c"); + try win_sources.append(tcl_source_folder ++ "/win/tclWinError.c"); + try win_sources.append(tcl_source_folder ++ "/win/tclWinFCmd.c"); + try win_sources.append(tcl_source_folder ++ "/win/tclWinFile.c"); + try win_sources.append(tcl_source_folder ++ "/win/tclWinInit.c"); //wininit_obj + try win_sources.append(tcl_source_folder ++ "/win/tclWinLoad.c"); + try win_sources.append(tcl_source_folder ++ "/win/tclWinNotify.c"); + try win_sources.append(tcl_source_folder ++ "/win/tclWinPipe.c"); //winpipe_obj + try win_sources.append(tcl_source_folder ++ "/win/tclWinSock.c"); + try win_sources.append(tcl_source_folder ++ "/win/tclWinThrd.c"); + try win_sources.append(tcl_source_folder ++ "/win/tclWinTime.c"); + }, + else => { + try unix_sources.append(tcl_source_folder ++ "/unix/tclUnixChan.c"); + try unix_sources.append(tcl_source_folder ++ "/unix/tclUnixEvent.c"); + try unix_sources.append(tcl_source_folder ++ "/unix/tclUnixFCmd.c"); + try unix_sources.append(tcl_source_folder ++ "/unix/tclUnixFile.c"); + try unix_sources.append(tcl_source_folder ++ "/unix/tclUnixPipe.c"); + try unix_sources.append(tcl_source_folder ++ "/unix/tclUnixSock.c"); + try unix_sources.append(tcl_source_folder ++ "/unix/tclUnixTime.c"); + try unix_sources.append(tcl_source_folder ++ "/unix/tclUnixInit.c"); + try unix_sources.append(tcl_source_folder ++ "/unix/tclUnixThrd.c"); + try unix_sources.append(tcl_source_folder ++ "/unix/tclUnixCompat.c"); + + //NOTIFY_SRCS + try unix_sources.append(tcl_source_folder ++ "/unix/tclEpollNotfy.c"); + try unix_sources.append(tcl_source_folder ++ "/unix/tclKqueueNotfy.c"); + try unix_sources.append(tcl_source_folder ++ "/unix/tclSelectNotfy.c"); + //try unix_sources.append(tcl_source_folder ++ "/unix/tclUnixNotfy.c"); + switch (target.result.os.tag) { + .macos => { + try unix_sources.append(tcl_source_folder ++ "/unix/tclLoadDyld.c"); + //MAC_OSX_SRCS + try unix_sources.append(tcl_source_folder ++ "/macosx/tclMacOSXBundle.c"); + try unix_sources.append(tcl_source_folder ++ "/macosx/tclMacOSXFCmd.c"); + try unix_sources.append(tcl_source_folder ++ "/macosx/tclMacOSXNotify.c"); + }, + else => { + try unix_sources.append(tcl_source_folder ++ "/unix/tclLoadDL.c"); + }, + } + }, + } + + var tommath_sources = std.ArrayList([]const u8).init(b.allocator); + //{ + // //const subdir = "../libtommath"; + // //const subdir = tcl_source_folder ++ "/libtommath"; + // var dir = try fs.cwd().openDir(tommath_sourcedir, .{ .iterate = true }); + // defer dir.close(); + // var it = dir.iterate(); + // const allowed_exts = [_][]const u8{ + // ".c", + // }; + // while (try it.next()) |entry| { + // if (entry.kind == .file) { + // const ext = fs.path.extension(entry.name); + // const include_file = for (allowed_exts) |e| { + // if (std.mem.eql(u8, ext, e)) break true; + // } else false; + // if (include_file) { + // try tommath_sources.append(b.pathJoin(&.{ + // tommath_sourcedir, + // entry.name, + // })); + // } + // } + // } + //} + + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_add.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_add_d.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_and.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_clamp.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_clear.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_clear_multi.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_cmp.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_cmp_d.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_cmp_mag.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_cnt_lsb.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_copy.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_count_bits.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_div.c"); + //tcl9.0 + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_div_d.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_div_2.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_div_2d.c"); + + //tcl9.0 + try tommath_sources.append(tommath_sourcedir ++ "/bn_s_mp_div_3.c"); + + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_exch.c"); + //tcl9.0 + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_expt_n.c"); + + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_get_mag_u64.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_grow.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_init.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_init_copy.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_init_i64.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_init_multi.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_init_set.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_init_size.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_init_u64.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_lshd.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_mod.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_mod_2d.c"); + //tcl9.0 + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_mul.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_mul_2.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_mul_2d.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_mul_d.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_neg.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_or.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_pack.c"); + //tcl9.0 + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_pack_count.c"); + + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_radix_size.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_radix_smap.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_read_radix.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_rshd.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_set_i64.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_set_u64.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_shrink.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_sqr.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_sqrt.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_sub.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_sub_d.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_signed_rsh.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_to_ubin.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_to_radix.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_ubin_size.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_unpack.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_xor.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_mp_zero.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_s_mp_add.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_s_mp_balance_mul.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_s_mp_karatsuba_mul.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_s_mp_karatsuba_sqr.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_s_mp_mul_digs.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_s_mp_mul_digs_fast.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_s_mp_reverse.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_s_mp_sqr_fast.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_s_mp_sqr.c"); + try tommath_sources.append(tommath_sourcedir ++ "/bn_s_mp_sub.c"); + //tcl 9.0 + try tommath_sources.append(tommath_sourcedir ++ "/bn_s_mp_toom_mul.c"); + + try tommath_sources.append(tommath_sourcedir ++ "/bn_s_mp_toom_sqr.c"); + + // larger set + var tcl_objs_static_sources = std.ArrayList([]const u8).init(b.allocator); + defer tcl_objs_static_sources.deinit(); + try tcl_objs_static_sources.appendSlice(generic_sources.items); + if (target.result.os.tag == .windows) { + try tcl_objs_static_sources.appendSlice(win_sources.items); + } else { + try tcl_objs_static_sources.appendSlice(unix_sources.items); + } + try tcl_objs_static_sources.appendSlice(tommath_sources.items); + if (target.result.os.tag == .windows) { + var panic_dde_reg_sources = std.ArrayList([]const u8).init(b.allocator); + defer panic_dde_reg_sources.deinit(); + try panic_dde_reg_sources.append(tcl_source_folder ++ "/win/tclWinPanic.c"); + try panic_dde_reg_sources.append(tcl_source_folder ++ "/win/tclWinReg.c"); + try panic_dde_reg_sources.append(tcl_source_folder ++ "/win/tclWinDde.c"); + try tcl_objs_static_sources.appendSlice(panic_dde_reg_sources.items); + } + + //smaller set + var tcl_objs_shared_sources = std.ArrayList([]const u8).init(b.allocator); + defer tcl_objs_shared_sources.deinit(); + try tcl_objs_shared_sources.appendSlice(generic_sources.items); + if (target.result.os.tag == .windows) { + try tcl_objs_shared_sources.appendSlice(win_sources.items); + } else { + try tcl_objs_shared_sources.appendSlice(unix_sources.items); + } + + //shouldn't need to be added ?? + try tcl_objs_shared_sources.appendSlice(tommath_sources.items); + + var tclobjs_flags = std.ArrayList([]const u8).init(b.allocator); + try tclobjs_flags.appendSlice(cc_flags.items); + try tclobjs_flags.appendSlice(&.{ + "-DBUILD_tcl", + }); + + // ============================================================================================================== + const Flaginfo = struct { flags: std.ArrayList([]const u8) }; + var build_specials = std.StringHashMap(Flaginfo).init(b.allocator); + defer build_specials.deinit(); + // -------------------------------------------------------------------------------------------------------------- + var mainw_flags = std.ArrayList([]const u8).init(b.allocator); + defer mainw_flags.deinit(); + + try build_specials.put("tclWinPanic", .{ .flags = winpaniclib_flags }); + try build_specials.put("tclWinReg", .{ .flags = winreg_obj_flags }); + try build_specials.put("tclWinDde", .{ .flags = windde_obj_flags }); + + var appinit_flags = std.ArrayList([]const u8).init(b.allocator); + defer appinit_flags.deinit(); + try appinit_flags.appendSlice(cc_flags.items); + try appinit_flags.appendSlice(&.{ + "-DUNICODE", + "-D_UNICODE", + }); + try build_specials.put("tclAppInit", .{ .flags = appinit_flags }); + + try mainw_flags.appendSlice(cc_flags.items); + try mainw_flags.appendSlice(&.{ + "-DBUILD_tcl", + "-DUNICODE", + "-D_UNICODE", + }); + try build_specials.put("tclMain", .{ .flags = mainw_flags }); + + var wininit_obj_flags = std.ArrayList([]const u8).init(b.allocator); + defer wininit_obj_flags.deinit(); + try wininit_obj_flags.appendSlice(cc_flags.items); + try wininit_obj_flags.appendSlice(&.{ + "-DBUILD_tcl", + }); + try build_specials.put("tclWinInit", .{ .flags = wininit_obj_flags }); + + //try build_specials.put("tclPkgConfig",.{ .flags = config_flags}); + try build_specials.put("tclPkgConfig", .{ .flags = cc_flags }); //cc_flags includes config_flags + + var zipfs_flags = std.ArrayList([]const u8).init(b.allocator); + defer zipfs_flags.deinit(); + try zipfs_flags.appendSlice(cc_flags.items); + try zipfs_flags.appendSlice(&.{ + "-DBUILD_tcl", + }); + try build_specials.put("tclZipfs", .{ .flags = zipfs_flags }); + //zipfs_obj.addIncludePath(.{ .path = tcl_source_folder ++ "/compat/zlib/contrib/minizip" }); + + var pipe_obj_flags = std.ArrayList([]const u8).init(b.allocator); + defer pipe_obj_flags.deinit(); + try pipe_obj_flags.appendSlice(cc_flags.items); + try pipe_obj_flags.appendSlice(&.{ + "-DBUILD_tcl", + }); + try build_specials.put("tclWinPipe", .{ .flags = pipe_obj_flags }); + + // ============================================================================================================== + + const tcl_objs_static = b.addStaticLibrary(.{ + .name = "tclobjs" ++ tcl_nodot_version, + .target = target, + .optimize = optimize, + }); + + tcl_objs_static.addIncludePath(b.path(tcl_source_folder ++ "/generic")); + if (target.result.os.tag == .windows) { + tcl_objs_static.addIncludePath(b.path(tcl_source_folder ++ "/win")); + } else { + tcl_objs_static.addIncludePath(b.path(tcl_source_folder ++ "/unix")); + } + tcl_objs_static.addIncludePath(b.path(tommath_sourcedir)); + tcl_objs_static.addIncludePath(b.path(tcl_source_folder ++ "/compat/zlib")); + tcl_objs_static.addIncludePath(b.path(tcl_source_folder ++ "/compat/zlib/contrib/minizip")); //only required by tclZipfs - but ok for all? + + //tclMain.c needs to be built twice on windows - with and without unicode flags + if (target.result.os.tag == .windows) { + tcl_objs_static.addCSourceFile(.{ + .file = b.path(tcl_source_folder ++ "/generic/tclMain.c"), + .flags = mainw_flags.items, + }); + } + var current_flagset: std.ArrayList([]const u8) = undefined; + for (tcl_objs_static_sources.items) |src| { + if (build_specials.get(std.fs.path.stem(src))) |val| { + //std.debug.print(">>> {s}\n", .{ std.fs.path.stem(src)}); + current_flagset = val.flags; + } else { + //std.debug.print("--- {s}", .{ std.fs.path.stem(src)}); + current_flagset = tclobjs_flags; + } + tcl_objs_static.addCSourceFile(.{ + .file = b.path(src), + .flags = current_flagset.items, + }); + } + tcl_objs_static.linkLibC(); + //b.installArtifact(tcl_objs); + + //const tcl_objs_shared = b.addStaticLibrary(.{ + // .name = "tclobjsshared" ++ tcl_nodot_version, + // .target = target, + // .optimize = optimize, + //}); + //tcl_objs_shared.addIncludePath(b.path(tcl_source_folder ++ "/generic")); + //if (target.result.os.tag == .windows) { + // tcl_objs_shared.addIncludePath(b.path(tcl_source_folder ++ "/win")); + //} else { + // tcl_objs_shared.addIncludePath(b.path(tcl_source_folder ++ "/unix")); + //} + //tcl_objs_shared.addIncludePath(b.path(tommath_sourcedir)); + //tcl_objs_shared.addIncludePath(b.path(tcl_source_folder ++ "/compat/zlib")); + //tcl_objs_shared.addIncludePath(b.path(tcl_source_folder ++ "/compat/zlib/contrib/minizip")); //only required by tclZipfs - but ok for all? + //if (target.result.os.tag == .windows) { + // tcl_objs_shared.addCSourceFile(.{ + // .file = b.path(tcl_source_folder ++ "/generic/tclMain.c"), + // .flags = mainw_flags.items, + // }); + //} + //var current_flagset_obj_shared: std.ArrayList([]const u8) = undefined; + //for (tcl_objs_shared_sources.items) |src| { + // if (build_specials.get(std.fs.path.stem(src))) |val| { + // //std.debug.print(">>> {s}\n", .{ std.fs.path.stem(src)}); + // current_flagset_obj_shared = val.flags; + // } else { + // //std.debug.print("--- {s}", .{ std.fs.path.stem(src)}); + // current_flagset_obj_shared = tclobjs_flags; + // } + // tcl_objs_shared.addCSourceFile(.{ + // .file = b.path(src), + // .flags = current_flagset_obj_shared.items, + // }); + //} + ////tcl_objs_shared.addObjectFile(b.path(tcl_source_folder ++ "/libtommath/win64/libtommath.dll.a")); + //tcl_objs_shared.addObjectFile(b.path(tcl_source_folder ++ "/libtommath/win64/tommath.lib")); + ////tcl_objs_shared.addObjectFile(b.path(tcl_source_folder ++ "/compat/zlib/win64/libz.dll.a")); + //tcl_objs_shared.addObjectFile(b.path(tcl_source_folder ++ "/compat/zlib/win64/zdll.lib")); + //tcl_objs_shared.linkLibC(); + + //-- --- --- + + //const tcl_lib_static = b.addStaticLibrary(.{ + // //libtcl90.dll.a ? + // .name = if (target.result.os.tag == .windows) "libtcl" ++ tcl_nodot_version ++ ".dll" else "libtcl" ++ tcl_nodot_version ++ ".so", //zig will append .lib or .a? + // .target = target, + // .optimize = optimize, + //}); + + ////jmn3 -test + //tcl_lib_static.step.dependOn(&zlib_lib_compile.step); + ////tcl_lib_static.step.dependOn(&tommath_lib_compile.step); + + //tcl_lib_static.step.dependOn(&wf_uuidh.step); + //tcl_lib_static.addIncludePath(b.path(tcl_source_folder ++ "/generic")); + //if (target.result.os.tag == .windows) { + // tcl_lib_static.addIncludePath(b.path(tcl_source_folder ++ "/win")); + //} else { + // tcl_lib_static.addIncludePath(b.path(tcl_source_folder ++ "/unix")); + //} + //tcl_lib_static.addIncludePath(b.path(tommath_sourcedir)); + //if (target.result.os.tag == .windows) { + // tcl_lib_static.addIncludePath(b.path(zlib_sourcedir)); + // tcl_lib_static.addIncludePath(b.path(zlib_sourcedir ++ "/contrib/minizip")); //only required by tclZipfs - but ok for all? + //} else { + // //tcl_lib_static.addIncludePath(b.path("../zlib")); + // //tcl_lib_static.addIncludePath(b.path("../zlib/contrib/minizip")); + // tcl_lib_static.addIncludePath(b.path(zlib_sourcedir)); + // tcl_lib_static.addIncludePath(b.path(zlib_sourcedir ++ "/contrib/minizip")); //only required by tclZipfs - but ok for all? + //} + + //for (tcl_lib_sources.items) |src| { + // if (build_specials.get(std.fs.path.stem(src))) |val| { + // //std.debug.print(">>> {s}\n", .{ std.fs.path.stem(src)}); + // current_flagset = val.flags; + // } else { + // //std.debug.print("--- {s}", .{ std.fs.path.stem(src)}); + // current_flagset = tclobjs_flags; + // } + // tcl_lib_static.addCSourceFile(.{ + // .file = b.path(src), + // .flags = current_flagset.items, + // }); + //} + + //jmn3 + //tcl_lib_static.linkLibrary(zlib_lib_compile); + //tcl_lib_static.linkLibrary(tommath_lib_compile); + + //tcl_lib_static.linkLibC(); + //b.installArtifact(tcl_lib_static); + + // ============================================================================================================== + // ============================================================================================================== + + //tclXX.dll or .so + var tcl_lib_shared_flags = std.ArrayList([]const u8).init(b.allocator); + try tcl_lib_shared_flags.appendSlice(base_flags.items); + try tcl_lib_shared_flags.appendSlice(&.{ + "-pipe", + "-municode", + }); + if (target.result.os.tag == .windows) { + try tcl_lib_shared_flags.appendSlice(&.{ + "-static-libgcc", + }); + + //jmn3 + try tcl_lib_shared_flags.appendSlice(&.{ + "-Wl,-out-implib,tcl90.dll.a", + }); + } + //try tcl_slib_flags.appendSlice(&.{ + // "-DUNICODE", + // "-D_UNICODE", + //}); + try tcl_lib_shared_flags.appendSlice(c_flags.items); + + const tcl_lib_shared = b.addSharedLibrary(.{ + .name = "tcl" ++ tcl_nodot_version, + .target = target, + .optimize = optimize, + }); + + //tcl_lib_shared.verbose_link = true; + //tcl_lib_shared.setVerboseLink(true); + //tcl_lib_shared.step.dependOn(&tcl_objs_shared.step); + + //jmn3 test + //if (target.result.os.tag == .linux) { + // tcl_slib.step.dependOn(&zlib_lib_compile.step); + //} + + tcl_lib_shared.addIncludePath(b.path(tcl_source_folder ++ "/generic")); + if (target.result.os.tag == .windows) { + tcl_lib_shared.addIncludePath(b.path(tcl_source_folder ++ "/win")); + tcl_lib_shared.addIncludePath(b.path(tcl_source_folder ++ "/compat/zlib")); + tcl_lib_shared.addIncludePath(b.path(tcl_source_folder ++ "/compat/zlib/contrib/minizip")); + } else { + tcl_lib_shared.addIncludePath(b.path(tcl_source_folder ++ "/unix")); + tcl_lib_shared.addIncludePath(b.path(zlib_sourcedir)); + tcl_lib_shared.addIncludePath(b.path(zlib_sourcedir ++ "/contrib/minizip")); //only required by tclZipfs - but ok for all? + } + tcl_lib_shared.addIncludePath(b.path(tommath_sourcedir)); + + // --- + // ?? needed for shared lib? + //if (target.result.os.tag == .windows) { + // tcl_lib_shared.addCSourceFile(.{ + // .file = b.path(tcl_source_folder ++ "/generic/tclMain.c"), + // .flags = mainw_flags.items, + // }); + //} + // --- + for (tcl_objs_shared_sources.items) |src| { + if (build_specials.get(std.fs.path.stem(src))) |val| { + //std.debug.print(">>> {s}\n", .{ std.fs.path.stem(src)}); + current_flagset = val.flags; + } else { + //std.debug.print("--- {s}", .{ std.fs.path.stem(src)}); + current_flagset = tclobjs_flags; + } + tcl_lib_shared.addCSourceFile(.{ + .file = b.path(src), + .flags = current_flagset.items, + }); + } + + if (target.result.os.tag == .windows) { + tcl_lib_shared.addLibraryPath(b.path(tcl_source_folder ++ "/compat/zlib/win64")); + tcl_lib_shared.addLibraryPath(b.path(tcl_source_folder ++ "/libtommath/win64")); + } + + if (target.result.os.tag == .windows) { + //tcl_lib_shared.addObjectFile(b.path(tcl_source_folder ++ "/libtommath/win64/libtommath.dll.a")); + //tcl_lib_shared.addObjectFile(b.path(tcl_source_folder ++ "/compat/zlib/win64/libz.dll.a")); + tcl_lib_shared.linkSystemLibrary2("tommath", .{ .preferred_link_mode = .dynamic }); + //tcl_lib_shared.linkSystemLibrary2("zlib1", .{ .preferred_link_mode = .dynamic }); + tcl_lib_shared.linkLibrary(zlib_lib_compile); + //tcl_lib_shared.linkSystemLibrary("tommath"); + //tcl_lib_shared.linkSystemLibrary("zlib1"); + } else { + //tcl_lib_shared.linkLibrary(tommath_lib_compile); + tcl_lib_shared.linkLibrary(zlib_lib_compile); + //tcl_lib_shared.linkSystemLibrary("zlib1"); + } + //JMN2024 install_path problem (sub_path is expected to be relative to the build root) + //tcl_lib_shared.addLibraryPath(b.path( b.pathJoin(&.{ b.install_path, "" }) )); + tcl_lib_shared.linkLibC(); + + //SHLIB_LD_LIBS (LIBS) + if (target.result.os.tag == .windows) { + tcl_lib_shared.linkSystemLibrary("netapi32"); + tcl_lib_shared.linkSystemLibrary("kernel32"); + tcl_lib_shared.linkSystemLibrary("user32"); + tcl_lib_shared.linkSystemLibrary("advapi32"); + tcl_lib_shared.linkSystemLibrary("userenv"); + tcl_lib_shared.linkSystemLibrary("ws2_32"); + } + //tclshlib.linkSystemLibrary("libtommath"); + //tclshlib.linkSystemLibrary("zlib1"); + tcl_lib_shared.addWin32ResourceFile(.{ + .file = b.path(tcl_source_folder ++ "/win/tcl.rc"), + .flags = &.{ + "/I", + tcl_source_folder ++ "/generic", + }, + }); + b.installArtifact(tcl_lib_shared); + + var ldflags_console = std.ArrayList([]const u8).init(b.allocator); + if (target.result.os.tag == .windows) { + try ldflags_console.appendSlice(&.{ + "-mconsole", + "-static-libgcc", + "-Wl,--enable-auto-image-base", + "-Wl,--subsystem,console", + "-DTCL_BROKEN_MAINARGS", + }); + } + try ldflags_console.appendSlice(&.{ + //"-mwindows", + "-pipe", + "-municode", + }); + //"-DTCL_MEM_DEBUG", + + var tclsh_flags = std.ArrayList([]const u8).init(b.allocator); + try tclsh_flags.appendSlice(c_flags.items); + try tclsh_flags.appendSlice(appinit_flags.items); + try tclsh_flags.appendSlice(ldflags_console.items); + + const tclsh_exe = b.addExecutable(.{ + .name = tclsh_static, //e.g tclsh90s (becomes tclsh90s.exe on windows) + //.root_source_file = .{ .path = appinit_path}, + .root_source_file = b.path("src/main.zig"), + .target = target, + .optimize = optimize, + }); + //9.0.5 sources dropped TCL_BROKEN_MAINARGS: tclAppInit.c now provides _tmain, which is + //wmain under -DUNICODE, so the mingw CRT must use the unicode entry (zig's -municode). + tclsh_exe.mingw_unicode_entry_point = true; + //tclsh_exe.setVerboseLink(true); + //tclsh_exe.link_gc_sections = false; + //tclsh_exe.want_lto = false; + tclsh_exe.step.dependOn(&finalstublib.step); + //tclsh.step.dependOn(&install_tcl_lib_file.step); + tclsh_exe.step.dependOn(&tcl_objs_static.step); + //tclsh_exe.step.dependOn(&tcl_lib_shared.step); + //tclsh_exe.step.dependOn(&tommath_lib_compile.step); + //JMN3 test + //if (target.result.os.tag == .linux) { + // tclsh_exe.step.dependOn(&zlib_lib_compile.step); + //} + + tclsh_exe.addIncludePath(b.path(tcl_source_folder ++ "/generic")); + if (target.result.os.tag == .windows) { + tclsh_exe.addIncludePath(b.path(tcl_source_folder ++ "/win")); + tclsh_exe.addIncludePath(b.path(tcl_source_folder ++ "/compat/zlib")); + tclsh_exe.addIncludePath(b.path(tcl_source_folder ++ "/compat/zlib/contrib/minizip")); + } else { + tclsh_exe.addIncludePath(b.path(tcl_source_folder ++ "/unix")); + tclsh_exe.addIncludePath(b.path(zlib_sourcedir)); + tclsh_exe.addIncludePath(b.path(zlib_sourcedir ++ "/contrib/minizip")); + } + tclsh_exe.addIncludePath(b.path(tommath_sourcedir)); + + //tclMain needs to be compiled twice on windows - with and without unicode + //we have already configured the one in the sources list to compile with mainw_flags (DUNICODE etc) + if (target.result.os.tag == .windows) { + tclsh_exe.addCSourceFile(.{ + .file = b.path(tcl_source_folder ++ "/generic/tclMain.c"), + .flags = tclobjs_flags.items, + }); + } + tclsh_exe.addCSourceFile(.{ + .file = b.path(appinit_path), + .flags = tclsh_flags.items, + }); + // TCL_LIB_FILE libtclxx.dll.a (not the implib which is tclxx.dll.a) + // -- + //tclsh_exe.addObjectFile(install_tcl_lib_file.source); + //tclsh_exe.addObjectFile(tcl_lib_static.getEmittedBin()); + for (tcl_objs_static_sources.items) |src| { + if (build_specials.get(std.fs.path.stem(src))) |val| { + std.debug.print(">>> {s}\n", .{std.fs.path.stem(src)}); + current_flagset = val.flags; + } else { + //std.debug.print("--- {s}", .{ std.fs.path.stem(src)}); + current_flagset = tclobjs_flags; + } + tclsh_exe.addCSourceFile(.{ + .file = b.path(src), + .flags = current_flagset.items, + }); + } + //tclsh_exe.addObjectFile(finalstublib.getEmittedBin()); + tclsh_exe.addCSourceFile(.{ + .file = b.path(tcl_source_folder ++ "/generic/tclStubLib.c"), + .flags = stublib_flags.items, + }); + //experiment + //tclsh_exe.addCSourceFiles(.{ + // .files = &.{ + // "generic/tclStubCall.c", + // "tclStubLibTbl.c", + // }, + // .flags = stublib_call_flags.items, + //}); + + //tcl9 + tclsh_exe.addCSourceFile(.{ + .file = b.path(tcl_source_folder ++ "/generic/tclStubCall.c"), + .flags = stublib_call_flags.items, + }); + //tcl9 + tclsh_exe.addCSourceFile(.{ + .file = b.path(tcl_source_folder ++ "/generic/tclStubLibTbl.c"), + .flags = stublib_tbl_flags.items, + }); + tclsh_exe.addCSourceFile(.{ + .file = b.path(tcl_source_folder ++ "/generic/tclTomMathStubLib.c"), + .flags = stublib_tom_flags.items, + }); + tclsh_exe.addCSourceFile(.{ + .file = b.path(tcl_source_folder ++ "/generic/tclOOStubLib.c"), + .flags = stublib_oo_flags.items, + }); + if (target.result.os.tag == .windows) { + tclsh_exe.addCSourceFile(.{ + .file = b.path(tcl_source_folder ++ "/win/tclWinPanic.c"), + .flags = winpaniclib_flags.items, + }); + } + if (target.result.os.tag == .windows) { + tclsh_exe.linkSystemLibrary("netapi32"); + tclsh_exe.linkSystemLibrary("kernel32"); + tclsh_exe.linkSystemLibrary("user32"); + tclsh_exe.linkSystemLibrary("advapi32"); + tclsh_exe.linkSystemLibrary("userenv"); + tclsh_exe.linkSystemLibrary("ws2_32"); + } + if (target.result.os.tag == .windows) { + tclsh_exe.addObjectFile(b.path(tcl_source_folder ++ "/libtommath/win64/libtommath.dll.a")); + //### jmn + //tclsh_exe.addObjectFile(b.path(tcl_source_folder ++ "/compat/zlib/win64/libz.dll.a")); + } else { + //tclsh_exe.linkLibrary(tommath_lib_compile); + //tclsh_exe.linkLibrary(zlib_lib_compile); + } + //### jmn + tclsh_exe.step.dependOn(&zlib_lib_compile.step); + tclsh_exe.linkLibrary(zlib_lib_compile); + //tclsh.addLibraryPath(.{ .path = tcl_source_folder ++ "/compat/zlib/win64"}); + //tclsh.addLibraryPath(.{ .path = tcl_source_folder ++ "/libtommath/win64"}); + //tclsh.linkSystemLibrary("zlib1"); + //tclsh.linkSystemLibrary("tommath"); + + //////////////////// tclvfs + //const tclvfs_compile = try tclvfs_static.build_tclvfs(tcl_source_folder, "../tclvfs", b, target, optimize, finalstublib); + //const build_tclvfs_step = b.step("build-tclvfs", "build tclvfs static library"); + //build_tclvfs_step.dependOn(&tclvfs_compile.step); + //tclsh_exe.step.dependOn(&tclvfs_compile.step); + //tclsh_exe.linkLibrary(tclvfs_compile); + //////////////////// + const tclvfs_compile = try tclvfs_shared.build_tclvfs(tcl_source_folder, "../tclvfs", b, target, optimize, finalstublib); + const build_tclvfs_step = b.step("build-tclvfs", "build tclvfs shared library"); + build_tclvfs_step.dependOn(&tclvfs_compile.step); + tclsh_exe.step.dependOn(&tclvfs_compile.step); // review + //////////////////// + + if (target.result.os.tag == .windows) { + const vqtcl_compile = try vqtcl_shared.build_vqtcl(tcl_source_folder, "../vqtcl", b, target, optimize, finalstublib); + const build_vqtcl_step = b.step("build-vqtcl", "build vqtcl shared library"); + build_vqtcl_step.dependOn(&vqtcl_compile.step); + tclsh_exe.step.dependOn(&vqtcl_compile.step); //review - find better dependOn for this? + } + + tclsh_exe.linkLibC(); + + //LDFLAGS_CONSOLE= -mconsole -pipe -static-libgcc -municode -Wl,--enable-auto-image-base + tclsh_exe.addWin32ResourceFile(.{ + .file = b.path(tcl_source_folder ++ "/win/tclsh.rc"), + .flags = &.{ + "/I", + tcl_source_folder ++ "/generic", + }, + }); + const install_tclsh = b.addInstallArtifact(tclsh_exe, .{}); + std.debug.print("\n", .{}); + std.debug.print("tclsh.kind {s}\n", .{@tagName(tclsh_exe.kind)}); + std.debug.print("prefix {s}\n", .{b.install_path}); + b.getInstallStep().dependOn(&install_tclsh.step); + + //OPTIONAL steps + const install_tzdata_step = b.step("install-tzdata", "install tcl timezone data"); + + //addInstallDirectory is recursive + const tzdata_install = b.addInstallDirectory(.{ + .source_dir = b.path(tcl_source_folder ++ "/library/tzdata"), + .install_dir = .prefix, + .install_subdir = b.pathJoin(&.{ script_install_dir_rel, "tzdata" }), + }); + install_tzdata_step.dependOn(&tzdata_install.step); + + //**************************** + //zig build install-libraries + const install_libraries = b.step("install-libraries", "install tcl libraries,tzdata,msgs (not required if zipfs being used)"); + install_libraries.dependOn(&tclsh_exe.step); + if (target.result.os.tag == .windows) { + install_libraries.dependOn(®_dll.step); + install_libraries.dependOn(&dde_dll.step); + } + + //Install library files - non recursive + var library_dir = try fs.cwd().openDir(tcl_source_folder ++ "/library", .{ .iterate = true }); + defer library_dir.close(); + const allowed_exts = [_][]const u8{ + ".tcl", + "", + }; + var it = library_dir.iterate(); + //var copy_libfile: []const u8 = undefined; + //var copy_libfile_step: *std.Build.Step = undefined; + var install_libfile: *std.Build.Step.InstallFile = undefined; + while (try it.next()) |entry| { + if (entry.kind == .file) { + const ext = fs.path.extension(entry.name); + const include_file = for (allowed_exts) |e| { + if (std.mem.eql(u8, ext, e)) break true; + } else false; + if (include_file) { + //try generic_sources.append(b.pathJoin(&.{"tcl" ++ tcl_nodot_version ++ "/generic", entry.name,})); + install_libfile = b.addInstallFileWithDir(b.path(b.pathJoin(&.{ tcl_source_folder ++ "/library", entry.name })), .prefix, b.pathJoin(&.{ script_install_dir_rel, entry.name })); + install_libraries.dependOn(&install_libfile.step); + } + } + } + + //Makefile for tcl9.0b1 uses target folder /opt0.4 /cookiejar0.2 - but we don't really need the version as part of the folder structure + //At least some distributions of tcl9 don't include the version - which seems simpler + const cookiejar_install = b.addInstallDirectory(.{ + .source_dir = b.path(tcl_source_folder ++ "/library/cookiejar"), + .include_extensions = &.{ ".tcl", ".gz" }, + .install_dir = .prefix, + //.install_subdir = b.pathJoin(&.{ script_install_dir_rel, "cookiejar0.2" }), + .install_subdir = b.pathJoin(&.{ script_install_dir_rel, "cookiejar" }), + }); + install_libraries.dependOn(&cookiejar_install.step); + + const tm_http_install = b.addInstallFileWithDir(b.path(tcl_source_folder ++ "/library/http/http.tcl"), .prefix, b.pathJoin(&.{ module_install_dir_rel, tcl_dot_version, "http-2.10.0.tm" })); + tm_http_install.step.dependOn(&b.addSystemCommand(&.{ "echo", "\n--Installing package http 2.10.0 as a Tcl Module--" }).step); + install_libraries.dependOn(&tm_http_install.step); + //opt/*.tcl + + const opt_tcl_install = b.addInstallDirectory(.{ + .source_dir = b.path(tcl_source_folder ++ "/library/opt"), + .include_extensions = &.{".tcl"}, + .install_dir = .prefix, + //.install_subdir = b.pathJoin(&.{ script_install_dir_rel, "opt0.4" }), + .install_subdir = b.pathJoin(&.{ script_install_dir_rel, "opt" }), + }); + install_libraries.dependOn(&opt_tcl_install.step); + + const opt_registry_install = b.addInstallDirectory(.{ + .source_dir = b.path(tcl_source_folder ++ "/library/registry"), + .include_extensions = &.{".tcl"}, + .install_dir = .prefix, + .install_subdir = b.pathJoin(&.{ script_install_dir_rel, "registry" }), + }); + install_libraries.dependOn(&opt_registry_install.step); + const pkgindex_install = b.addInstallFile(b.path(tcl_source_folder ++ "/library/manifest.txt"), b.pathJoin(&.{ script_install_dir_rel, "pkgIndex.tcl" })); + install_libraries.dependOn(&pkgindex_install.step); + + const tm_msgcat_install = b.addInstallFileWithDir(b.path(tcl_source_folder ++ "/library/msgcat/msgcat.tcl"), .prefix, b.pathJoin(&.{ module_install_dir_rel, tcl_dot_version, "msgcat-1.7.1.tm" })); + tm_msgcat_install.step.dependOn(&b.addSystemCommand(&.{ "echo", "\n--Installing package msgcat 1.7.1 as a Tcl Module--" }).step); + install_libraries.dependOn(&tm_msgcat_install.step); + + const tm_tcltest_install = b.addInstallFileWithDir(b.path(tcl_source_folder ++ "/library/tcltest/tcltest.tcl"), .prefix, b.pathJoin(&.{ module_install_dir_rel, tcl_dot_version, "tcltest-2.5.8.tm" })); + tm_tcltest_install.step.dependOn(&b.addSystemCommand(&.{ "echo", "\n--Installing package tcltest 2.5.8 as a Tcl Module--" }).step); + install_libraries.dependOn(&tm_tcltest_install.step); + + const tm_platform_install = b.addInstallFileWithDir(b.path(tcl_source_folder ++ "/library/platform/platform.tcl"), .prefix, b.pathJoin(&.{ module_install_dir_rel, tcl_dot_version, "platform-1.0.19.tm" })); + tm_platform_install.step.dependOn(&b.addSystemCommand(&.{ "echo", "\n--Installing package platform 1.0.19 as a Tcl Module--" }).step); + install_libraries.dependOn(&tm_platform_install.step); + + const tm_shell_install = b.addInstallFileWithDir(b.path(tcl_source_folder ++ "/library/platform/shell.tcl"), .prefix, b.pathJoin(&.{ module_install_dir_rel, tcl_dot_version, "platform", "shell-1.1.4.tm" })); + tm_shell_install.step.dependOn(&b.addSystemCommand(&.{ "echo", "\n--Installing package platform::shell 1.1.4 as a Tcl Module--" }).step); + install_libraries.dependOn(&tm_shell_install.step); + + const encodings_install = b.addInstallDirectory(.{ + .source_dir = b.path(tcl_source_folder ++ "/library/encoding"), + .include_extensions = &.{".enc"}, + .install_dir = .prefix, + .install_subdir = b.pathJoin(&.{ script_install_dir_rel, "encoding" }), + }); + install_libraries.dependOn(&encodings_install.step); + install_libraries.dependOn(install_tzdata_step); + + if (target.result.os.tag == .windows) { + install_libraries.dependOn(&install_dde_dll.step); + } + + //**************************** + + //**************************** + //zig build install-libraries + + const make_vfs_root = b.addWriteFiles(); + const tcl_library_path = make_vfs_root.addCopyDirectory(b.path(tcl_source_folder ++ "/library"), "base/tcl_library", .{}); + //_ = make_vfs_root.addCopyDirectory(b.path(tcl_source_folder ++ "/library"), "tcl_library", .{}); + _ = make_vfs_root.addCopyFile(b.path(tcl_source_folder ++ "/library/manifest.txt"), "base/tcl_library/pkgIndex.tcl"); + _ = make_vfs_root.addCopyFile(b.path(tcl_source_folder ++ "/library/manifest.txt"), "base/tcl_library/pkgIndex.tcl"); + + if (target.result.os.tag == .windows) { + _ = make_vfs_root.addCopyFile(install_dde_dll.artifact.getEmittedBin(), "base/tcl_library/dde/" ++ dde_dll_file); + //_ = make_vfs_root.addCopyFile(dde_dll.getEmittedBin(), "tcl_library/dde/" ++ dde_dll_file); + _ = make_vfs_root.addCopyFile(reg_dll.getEmittedBin(), "base/tcl_library/registry/" ++ reg_dll_file); + + make_vfs_root.step.dependOn(®_dll.step); + make_vfs_root.step.dependOn(&dde_dll.step); + } + + //make_vfs_root.step.dependOn(&tclvfs_compile.step); + // The build_tclvfs_xxx.zig module is responsible for what files tclvfs needs to add the vfs root + // -pass it the *WriteFile we're building and let it add stuff + + // ***************************** + // tclvfs shared/static - todo + //_ = try tclvfs_static.vfsadd_tclvfs_files(tcl_source_folder, "../tclvfs", b, make_vfs_root); + _ = try tclvfs_shared.vfsadd_tclvfs_files(tcl_source_folder, "../tclvfs", b, make_vfs_root); + //hack + _ = make_vfs_root.addCopyFile(tclvfs_compile.getEmittedBin(), "base/lib/vfs1.4.2/tcl9vfs142.dll"); + // ***************************** + + //we are putting vqtcl in the zipkit root - *not* a metakit - as we're loading vlerq dynamically and not using standard tclkit startup method + _ = try vqtcl_shared.vfsadd_vqtcl_files(tcl_source_folder, "../vqtcl", b, make_vfs_root); + //hack + + if (target.result.os.tag == .windows) { + //_ = make_vfs_root.addCopyFile(vqtcl_compile.getEmittedBin(), "base/lib/vqtcl4.1/tcl9vlerq41.dll"); + } else { + //unix/linux + } + + //pass make_vfs_root to build_tclvfs + + make_vfs_root.step.dependOn(install_libraries); + + // ** system zip - problematic to call in the way we need from zig.build + // I know of no way to get the resulting zip file to strip the containing directory path when using addDirectoryArg. + // Normally this is done by passing a relative path as the input folder to be archived - but we need to use zig's addDirectoryArg instead of just addArg with a string + // If we don't use addDirectoryArg - the zig cache will return stale results despite the systemzip step depending on make_vfs_root.step, etc (why??) + // addDirectoryArg seems only able to provide a full path to the system command - not the relative path we would need to strip the containing folder. + // -j option of zip doesn't help as it strips all paths. + // This isn't a great concern here - as we have a partially built tclsh and we would prefer to use the less platform-dependant 'zipfs mkzip' functionality provided therein anyway + // But it would have been nice for debug/testing purposes to compare with a system zip + // zipfs mkzip may be fine for our purposes but doesn't give us some of the potential customisability of a system zip command + // + const systemzip = b.addSystemCommand(&.{ "zip", "-r" }); + //systemzip.step.dependOn(&make_vfs_root.step); + + systemzip.setCwd(make_vfs_root.getDirectory()); + const out_zip = systemzip.addOutputFileArg("zipfs.zip"); + //systemzip.addDirectoryArg(tcl_library_path); + systemzip.addArg("tcl_library"); + const install_systemzip = b.addInstallFileWithDir(out_zip, .prefix, "zipfs.zip"); + install_systemzip.step.dependOn(&systemzip.step); + //b.getInstallStep().dependOn(&install_systemzip.step); + + // ** *** mkzip + var mkzip_run: *std.Build.Step.Run = undefined; + //mkzip_run.step.dependOn(&make_vfs_root.step); // ?????? + //mkzip_run.step.dependOn(install_libraries); + if (target.result.os.tag == builtin.os.tag) { + mkzip_run = b.addRunArtifact(tclsh_exe); + } else { + mkzip_run = b.addSystemCommand(&.{"tclsh90"}); + } + mkzip_run.addFileArg(b.path("tools/zipfs_mkzip.tcl")); + mkzip_run.addArg("-outfile"); + const out_mkzip = mkzip_run.addOutputFileArg("mkzipfs.zip"); + mkzip_run.addArg("-indir"); + mkzip_run.addDirectoryArg(tcl_library_path.dirname()); + mkzip_run.addArg("-strip"); + mkzip_run.addDirectoryArg(tcl_library_path.dirname()); + + //mkzip_run.addArg(make_vfs_root.getDirectory()); + const install_mkzip = b.addInstallFileWithDir(out_mkzip, .prefix, "mkzipfs.zip"); + install_mkzip.step.dependOn(&mkzip_run.step); + + const make_zipfs = b.step("make-zipfs", "make zipfs and attach to executable"); + //make_zipfs.dependOn(&tclsh_exe.step); + make_zipfs.dependOn(&install_mkzip.step); + //make_zipfs.dependOn(&install_systemzip.step); //not really required + // ** *** + + // ** *** *** mkimg + var mkimg_run: *std.Build.Step.Run = undefined; + if (target.result.os.tag == builtin.os.tag) { + mkimg_run = b.addRunArtifact(tclsh_exe); + } else { + //require an existing tclsh90 - with zipfs support on the path for x-builds + mkimg_run = b.addSystemCommand(&.{"tclsh90"}); + } + mkimg_run.addFileArg(b.path("tools/zipfs_mkimg.tcl")); + mkimg_run.addArg("-outfile"); + var out_mkimg: std.Build.LazyPath = undefined; + if (target.result.os.tag == .windows) { + out_mkimg = mkimg_run.addOutputFileArg("tclsh90szip.exe"); + } else { + out_mkimg = mkimg_run.addOutputFileArg("tclsh90szip"); + } + mkimg_run.addArg("-indir"); + mkimg_run.addDirectoryArg(tcl_library_path.dirname()); + mkimg_run.addArg("-strip"); + mkimg_run.addDirectoryArg(tcl_library_path.dirname()); + if (target.result.os.tag == .windows) { + //we can just leave off the -infile argument to use the calling interp as the prepended file + } else { + mkimg_run.addArg("-infile"); + mkimg_run.addArtifactArg(tclsh_exe); + } + var install_mkimg: *std.Build.Step.InstallFile = undefined; + if (target.result.os.tag == .windows) { + install_mkimg = b.addInstallFileWithDir(out_mkimg, .prefix, "bin/tclsh90szip.exe"); + } else { + install_mkimg = b.addInstallFileWithDir(out_mkimg, .prefix, "bin/tclsh90szip"); + } + install_mkimg.step.dependOn(&mkimg_run.step); + make_zipfs.dependOn(&install_mkimg.step); + // ** *** *** + + //**************************** + + const thread_lib_compile = try build_tclthread(tcl_source_folder, "../tclthread", b, target, optimize, finalstublib); + const build_tclthread_step = b.step("build-tclthread", "build tcl thread library"); + build_tclthread_step.dependOn(&thread_lib_compile.step); + b.getInstallStep().dependOn(build_tclthread_step); + + //if !ZIPFS_BUILD + //install without zipfs + //b.getInstallStep().dependOn(install_libraries); + +} diff --git a/src/buildsuites/suite_tcl90/build_libtommath/build_libtommath.zig b/src/buildsuites/suite_tcl90/build_libtommath/build_libtommath.zig new file mode 100644 index 00000000..4dcd110c --- /dev/null +++ b/src/buildsuites/suite_tcl90/build_libtommath/build_libtommath.zig @@ -0,0 +1,190 @@ +const std = @import("std"); +const fs = std.fs; + +// Although this function looks imperative, note that its job is to +// declaratively construct a build graph that will be executed by an external +// runner. +//pub fn build(b: *std.Build) !void {} +pub fn build_libtommath(comptime subdir: []const u8, b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) !*std.Build.Step.Compile { + const lib = b.addStaticLibrary(.{ + .name = "tommath", + .target = target, + .optimize = optimize, + }); + + var flags = std.ArrayList([]const u8).init(b.allocator); + defer flags.deinit(); + //try flags.appendSlice(&.{ "-Wall", "-O2" }); + try flags.appendSlice(&.{ "-Wall", "-O2", "-Wextra", "-Werror=return-type" }); + //libtom relies on dead code elimination - see s_mp_rand_platform.c + //The -O2 seems to fix the issue where dead code elimination is not performed (on windows anyway) + + var sources = std.ArrayList([]const u8).init(b.allocator); + { + var dir = try fs.cwd().openDir(subdir, .{ .iterate = true }); + defer dir.close(); + var it = dir.iterate(); + const allowed_exts = [_][]const u8{ + ".c", + }; + while (try it.next()) |entry| { + if (entry.kind == .file) { + const ext = fs.path.extension(entry.name); + const include_file = for (allowed_exts) |e| { + if (std.mem.eql(u8, ext, e)) break true; + } else false; + if (include_file) { + try sources.append(b.pathJoin(&.{ + subdir, + entry.name, + })); + } + } + //const ext = std.fs.path.extension(entry.basename); + } + } + + //std.debug.print("sources: {any}",.{sources.items}); + lib.linkLibC(); + if (target.result.os.tag == .windows) { + lib.linkSystemLibrary("advapi32"); //crypt + } + //lib.addIncludePath(.{ .path = subdir }); + lib.addIncludePath(b.path(subdir)); + lib.addIncludePath(b.path("../tcl90/generic")); //todo - fix + lib.addCSourceFiles(.{ + .files = sources.items, + .flags = flags.items, + }); + + // This declares intent for the library to be installed into the standard + // location when the user invokes the "install" step (the default step when + // running `zig build`). + b.installArtifact(lib); + + const exe = b.addExecutable(.{ + .name = "test_libtommath", + .target = target, + .optimize = optimize, + }); + exe.step.dependOn(&lib.step); + exe.linkLibC(); + if (target.result.os.tag == .windows) { + //exe.linkSystemLibrary("netapi32"); + //exe.linkSystemLibrary("kernel32"); + //exe.linkSystemLibrary("user32"); + exe.linkSystemLibrary("advapi32"); //crypt + //exe.linkSystemLibrary("userenv"); + //exe.linkSystemLibrary("ws2_32"); + } + //exe.addIncludePath(.{ .path = subdir }); + exe.addIncludePath(b.path(subdir)); + //exe.addIncludePath(.{ .path = subdir ++ "/demo" }); + exe.addIncludePath(b.path(subdir ++ "/demo")); + exe.addCSourceFile(.{ + //.file = .{ .path = subdir ++ "/demo/test.c" }, + .file = b.path(subdir ++ "/demo/test.c"), + .flags = flags.items, + }); + exe.addCSourceFile(.{ + //.file = .{ .path = subdir ++ "/demo/shared.c" }, + .file = b.path(subdir ++ "/demo/shared.c"), + .flags = flags.items, + }); + exe.linkLibrary(lib); + + // This declares intent for the executable to be installed into the + // standard location when the user invokes the "install" step (the default + // step when running `zig build`). + b.installArtifact(exe); + + // This *creates* a Run step in the build graph, to be executed when another + // step is evaluated that depends on it. The next line below will establish + // such a dependency. + const run_cmd = b.addRunArtifact(exe); + + if (target.result.os.tag == .windows) { + try flags.appendSlice(&.{ + "-Wl,--out-implib=libtommath.dll.a", + }); + const dll = b.addSharedLibrary(.{ + .name = "libtommath", + .target = target, + .optimize = optimize, + }); + dll.linkLibC(); + dll.linkSystemLibrary("advapi32"); //crypt + //dll.addIncludePath(.{ .path = subdir }); + dll.addIncludePath(b.path(subdir)); + dll.addCSourceFiles(.{ + .files = sources.items, + .flags = flags.items, + }); + b.installArtifact(dll); + } else { + const shlib_tom = b.addSharedLibrary(.{ + .name = "tommath", + .target = target, + .optimize = optimize, + }); + shlib_tom.linkLibC(); + //shlib_tom.addIncludePath(.{ .path = subdir }); + shlib_tom.addIncludePath(b.path(subdir)); + shlib_tom.addCSourceFiles(.{ + .files = sources.items, + .flags = flags.items, + }); + b.installArtifact(shlib_tom); + } + + // By making the run step depend on the install step, it will be run from the + // installation directory rather than directly from within the cache directory. + // This is not necessary, however, if the application depends on other installed + // files, this ensures they will be present and in the expected location. + run_cmd.step.dependOn(b.getInstallStep()); + + // This allows the user to pass arguments to the application in the build + // command itself, like this: `zig build run -- arg1 arg2 etc` + if (b.args) |args| { + run_cmd.addArgs(args); + } + + // This creates a build step. It will be visible in the `zig build --help` menu, + // and can be selected like this: `zig build run` + // This will evaluate the `run` step rather than the default, which is "install". + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run_cmd.step); + + const prepare = b.addSystemCommand(&.{ + "echo", + "--system command prepare--", + }); + run_cmd.step.dependOn(&prepare.step); + b.getInstallStep().dependOn(&prepare.step); + return lib; + + // Creates a step for unit testing. This only builds the test executable + // but does not run it. + //const lib_unit_tests = b.addTest(.{ + // //.root_source_file = .{ .path = "src/root.zig" }, + // .target = target, + // .optimize = optimize, + //}); + + //const run_lib_unit_tests = b.addRunArtifact(lib_unit_tests); + + //const exe_unit_tests = b.addTest(.{ + // .root_source_file = .{ .path = "src/main.zig" }, + // .target = target, + // .optimize = optimize, + //}); + + //const run_exe_unit_tests = b.addRunArtifact(exe_unit_tests); + + // Similar to creating the run step earlier, this exposes a `test` step to + // the `zig build --help` menu, providing a way for the user to request + // running the unit tests. + //const test_step = b.step("test", "Run unit tests"); + //test_step.dependOn(&run_lib_unit_tests.step); + //test_step.dependOn(&run_exe_unit_tests.step); +} diff --git a/src/buildsuites/suite_tcl90/build_tclthread/build_tclthread.zig b/src/buildsuites/suite_tcl90/build_tclthread/build_tclthread.zig new file mode 100644 index 00000000..b109478d --- /dev/null +++ b/src/buildsuites/suite_tcl90/build_tclthread/build_tclthread.zig @@ -0,0 +1,152 @@ +const std = @import("std"); +const fs = std.fs; +const builtin = @import("builtin"); + +const mkvar_thread_zip_file = "libthread3.0.1.zip"; +const mkvar_thread_vfs_root = "libthread.vfs"; +const mkvar_thread_vfs_path = mkvar_thread_vfs_root ++ "/thread_library"; + +const mkvar_pkg_lib_file = "tcl9thread301.dll"; + +// Although this function looks imperative, note that its job is to +// declaratively construct a build graph that will be executed by an external +// runner. +//pub fn build(b: *std.Build) !void {} +pub fn build_tclthread(comptime tcldir: []const u8, comptime subdir: []const u8, b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, stublib: *std.Build.Step.Compile) !*std.Build.Step.Compile { + const wrapfilecmd = b.addExecutable(.{ + .name = "wrapfiletofile", + .root_source_file = b.path("tools/wrapfiletofile.zig"), + .target = b.host, + }); + const uuidcmd_step = b.addRunArtifact(wrapfilecmd); + uuidcmd_step.addArgs(&.{ + "-prefix", + "#define THREAD_VERSION_UUID \\", + "-prefixnl", + "1", + "-input", + }); + uuidcmd_step.addFileArg(b.path(subdir ++ "/manifest.uuid")); + uuidcmd_step.addArg("-output"); + const threaduuid_file = uuidcmd_step.addOutputFileArg("threadUuid.h"); + + //var interp: []const []const u8 = undefined; + ////note we determine the interp based on the machine running the build - not the target + //if (builtin.os.tag == .windows) { + // interp = &.{ + // "wrapfiletofile.cmd", + // }; + //} else { + // interp = &.{ + // "bash", //explicitly use bash. Sometimes sh is linked to some other shell such as zsh, or dash (e.g debian,ubuntu) which don't understand substitution syntax like bash and ordinary posix sh do + // "wrapfiletofile.cmd", + // }; + //} + //const uuid_cmd = b.addSystemCommand(interp); + //uuid_cmd.addArgs(&.{ + // "-prefix", + // "#define THREAD_VERSION_UUID \\", + // "-prefixnl", + // "1", + // "-input", + //}); + ////uuid_cmd.addFileArg(.{ .path = b.pathJoin(&.{ b.pathFromRoot(""), "..", "tcl" ++ tcl_version, "manifest.uuid" }) }); + //uuid_cmd.addFileArg(b.path(subdir ++ "/manifest.Uuid")); + //uuid_cmd.addArg("-output"); + //const tcluuid_file1 = uuid_cmd.addOutputFileArg("threadUuid.h"); + + //const wf_uuidh = b.addWriteFiles(); + const wf_uuidh = b.addUpdateSourceFiles(); + if (target.result.os.tag == .windows) { + wf_uuidh.addCopyFileToSource(threaduuid_file, b.pathJoin(&.{ subdir, "win", "threadUuid.h" })); + } else { + wf_uuidh.addCopyFileToSource(threaduuid_file, b.pathJoin(&.{ subdir, "unix", "threadUuid.h" })); + } + + wf_uuidh.step.dependOn(&uuidcmd_step.step); + b.getInstallStep().dependOn(&wf_uuidh.step); + + const lib = b.addSharedLibrary(.{ + .name = "tcl9thread301", + .target = target, + .optimize = optimize, + }); + //lib.step.dependOn(&wf_uuidh.step); + var flags = std.ArrayList([]const u8).init(b.allocator); + defer flags.deinit(); + //try flags.appendSlice(&.{ "-Wall", "-O2", "-fomit-frame-pointer", "-DNDEBUG" }); + try flags.appendSlice(&.{ "-Wall", "-O3", "-fomit-frame-pointer" }); + try flags.appendSlice(&.{ + "-DPACKAGE_NAME=\"thread\"", + "-DPACKAGE_TARNAME=\"thread\"", + "-DPACKAGE_VERSION=\"3.0.1\"", + "-DPACKAGE_STRING=\"thread 3.0.1\"", + "-DPACKAGE_BUGREPORT=\"\"", + "-DPACKAGE_URL=\"\"", + "-DTCL_CFG_OPTIMIZED=1", + "-DUSE_TCL_STUBS=1", + "-DZIPFS_BUILD=1", + "-DTCL_WIDE_INT_TYPE=long long", + //"-DHAVE_STDIO_H=1", + //"-DHAVE_STDLIB_H=1", + //"-DHAVE_STRING_H=1", + "-DHAVE_INTTYPES_H=1", + //"-DHAVE_STDINT_H=1", + //"-DHAVE_STRINGS_H=1", + //"-DHAVE_SYS_STAT_H=1", + //"-DHAVE_SYS_TYPES_H=1", + //"-DHAVE_FILE_OFFSET_BITS=64", + //"-DHAVE_STRUCT_STAT64=1", + //"-DHAVE_LSEEK64=1", + + "-static-libgcc", + }); + + //BUILD_ needs to be defined for windows + if (target.result.os.tag == .windows) { + try flags.appendSlice(&.{ + "-DBUILD_thread=/**/", + }); + } + + var tclthread_sources = std.ArrayList([]const u8).init(b.allocator); + try tclthread_sources.append(subdir ++ "/generic/threadNs.c"); + try tclthread_sources.append(subdir ++ "/generic/threadCmd.c"); + try tclthread_sources.append(subdir ++ "/generic/threadSvCmd.c"); + try tclthread_sources.append(subdir ++ "/generic/threadSpCmd.c"); + try tclthread_sources.append(subdir ++ "/generic/threadPoolCmd.c"); + try tclthread_sources.append(subdir ++ "/generic/psGdbm.c"); + try tclthread_sources.append(subdir ++ "/generic/psLmdb.c"); + try tclthread_sources.append(subdir ++ "/generic/threadSvListCmd.c"); + try tclthread_sources.append(subdir ++ "/generic/threadSvKeyListCmd.c"); + try tclthread_sources.append(subdir ++ "/generic/tclXkeylist.c"); + + //if (target.result.os.tag == .windows) { + // lib.linkSystemLibrary("advapi32"); //crypt + //} + lib.addIncludePath(b.path(subdir)); + lib.addIncludePath(b.path(subdir ++ "/generic")); + //generated threadUuid.h: current thread trunk #includes it (upstream makefiles + //generate it into their build dir); using the generator's output dir as an include + //path also gives the compile its dependency on the generation step. + lib.addIncludePath(threaduuid_file.dirname()); + lib.addIncludePath(b.path(tcldir ++ "/generic")); //todo - fix + lib.addCSourceFiles(.{ + .files = tclthread_sources.items, + .flags = flags.items, + }); + + lib.linkLibrary(stublib); + lib.linkLibC(); + lib.addWin32ResourceFile(.{ + .file = b.path(subdir ++ "/win/thread.rc"), + .flags = &.{ + "-DPACKAGE_MAJOR=3", + "-DPACKAGE_MINOR=0", + "-DPACKAGE_VERSION=3.0b2", + }, + }); //ignored for non-windows targets + b.installArtifact(lib); + + return lib; +} diff --git a/src/buildsuites/suite_tcl90/build_tclvfs/build_tclvfs_shared.zig b/src/buildsuites/suite_tcl90/build_tclvfs/build_tclvfs_shared.zig new file mode 100644 index 00000000..4ec3ee8c --- /dev/null +++ b/src/buildsuites/suite_tcl90/build_tclvfs/build_tclvfs_shared.zig @@ -0,0 +1,81 @@ +const std = @import("std"); +const fs = std.fs; + +const tclvfs_dotversion = "1.4.2"; +const tclvfs_nodotversion = "142"; + +pub fn vfsadd_tclvfs_files(comptime tcldir: []const u8, comptime subdir: []const u8, b: *std.Build, vfswrite: *std.Build.Step.WriteFile) !*std.Build.Step.WriteFile { + //_ = tcldir; + //const version = "1.4.2"; + //recursive copy + //_ = make_vfs_root.addCopyDirectory(b.path(tcl_source_folder ++ "/../tclvfs/library"), "base/lib/vfs1.4.2", .{}); + _ = vfswrite.addCopyDirectory(b.path(tcldir ++ "/" ++ subdir ++ "/library"), b.pathJoin(&.{ "base", "lib", "vfs" ++ tclvfs_dotversion }), .{}); + + return vfswrite; +} +pub fn build_tclvfs(comptime tcldir: []const u8, comptime subdir: []const u8, b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, stublib: *std.Build.Step.Compile) !*std.Build.Step.Compile { + //review - libname Vfs vs vfs??? + const lib = b.addSharedLibrary(.{ + .name = "tcl9vfs142", + .target = target, + .optimize = optimize, + }); + //_ = stublib; + var flags = std.ArrayList([]const u8).init(b.allocator); + defer flags.deinit(); + //try flags.appendSlice(&.{ "-Wall", "-O3" }); + try flags.appendSlice(&.{ "-Wall", "-O3", "-fomit-frame-pointer" }); + try flags.appendSlice(&.{ + "-DPACKAGE_NAME=\"vfs\"", + "-DPACKAGE_TARNAME=\"vfs\"", + "-DPACKAGE_VERSION=\"" ++ tclvfs_dotversion ++ "\"", + "-DPACKAGE_STRING=\"vfs " ++ tclvfs_dotversion ++ "\"", + "-DPACKAGE_BUGREPORT=\"\"", + "-DPACKAGE_URL=\"\"", + "-DBUILD_VFS=1", + "-DTCL_CFG_OPTIMIZED=1", + "-DUSE_TCL_STUBS=1", + "-DZIPFS_BUILD=1", + "-DTCL_WIDE_INT_TYPE=long long", + }); + if (target.result.os.tag == .windows) { + try flags.appendSlice(&.{ + "-static-libgcc", + }); + } + //-DBUILD_VFS only on windows? value? + + var sources = std.ArrayList([]const u8).init(b.allocator); + try sources.append(subdir ++ "/generic/vfs.c"); + lib.addIncludePath(b.path(subdir)); + lib.addIncludePath(b.path(subdir ++ "/generic")); + lib.addIncludePath(b.path(tcldir ++ "/generic")); + lib.addIncludePath(b.path(tcldir ++ "/generic")); + if (target.result.os.tag == .windows) { + lib.addIncludePath(b.path(tcldir ++ "/win")); + } else { + lib.addIncludePath(b.path(tcldir ++ "/unix")); + } + lib.addCSourceFiles(.{ + .files = sources.items, + .flags = flags.items, + }); + + lib.linkLibrary(stublib); + lib.linkLibC(); + lib.addWin32ResourceFile(.{ + .file = b.path(subdir ++ "/win/tclvfs.rc"), + .flags = &.{ + "-DPACKAGE_MAJOR=1", + "-DPACKAGE_MINOR=4", + "-DPACKAGE_VERSION=" ++ tclvfs_dotversion, + "-DDOTVERSION=" ++ tclvfs_dotversion, + "-DCOMMAVERSION=" ++ tclvfs_dotversion, + "-DVERSION=" ++ tclvfs_nodotversion, + }, + }); //ignored for non-windows targets + // COMMAVERSION??? VERSION??? + + b.installArtifact(lib); + return lib; //static library +} diff --git a/src/buildsuites/suite_tcl90/build_tclvfs/build_tclvfs_static.zig b/src/buildsuites/suite_tcl90/build_tclvfs/build_tclvfs_static.zig new file mode 100644 index 00000000..77faae8a --- /dev/null +++ b/src/buildsuites/suite_tcl90/build_tclvfs/build_tclvfs_static.zig @@ -0,0 +1,76 @@ +const std = @import("std"); +const fs = std.fs; + +const tclvfs_dotversion = "1.4.2"; +const tclvfs_nodotversion = "142"; + +pub fn vfsadd_tclvfs_files(comptime tcldir: []const u8, comptime subdir: []const u8, b: *std.Build, vfswrite: *std.Build.Step.WriteFile) !*std.Build.Step.WriteFile { + //_ = tcldir; + //const version = "1.4.2"; + //recursive copy + //_ = make_vfs_root.addCopyDirectory(b.path(tcl_source_folder ++ "/../tclvfs/library"), "base/lib/vfs1.4.2", .{}); + _ = vfswrite.addCopyDirectory(b.path(tcldir ++ "/" ++ subdir ++ "/library"), b.pathJoin(&.{ "base", "lib", "vfs" ++ tclvfs_dotversion }), .{}); + + return vfswrite; +} +pub fn build_tclvfs(comptime tcldir: []const u8, comptime subdir: []const u8, b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, stublib: *std.Build.Step.Compile) !*std.Build.Step.Compile { + //review - libname Vfs vs vfs??? + const slib = b.addStaticLibrary(.{ + .name = "Vfs", + .target = target, + .optimize = optimize, + }); + + _ = stublib; + var flags = std.ArrayList([]const u8).init(b.allocator); + defer flags.deinit(); + //try flags.appendSlice(&.{ "-Wall", "-O3" }); + try flags.appendSlice(&.{ "-Wall", "-O2", "-fomit-frame-pointer" }); + try flags.appendSlice(&.{ + "-DPACKAGE_NAME=\"vfs\"", + "-DPACKAGE_TARNAME=\"vfs\"", + "-DPACKAGE_VERSION=\"" ++ tclvfs_dotversion ++ "\"", + "-DPACKAGE_STRING=\"vfs " ++ tclvfs_dotversion ++ "\"", + "-DPACKAGE_BUGREPORT=\"\"", + "-DPACKAGE_URL=\"\"", + "-DBUILD_VFS=1", + "-DTCL_CFG_OPTIMIZED=1", + "-DUSE_TCL_STUBS=0", + "-DZIPFS_BUILD=1", + "-DTCL_WIDE_INT_TYPE=long long", + "-DSTATIC_BUILD", + // ... + //"-static-libgcc", + }); + //-DBUILD_VFS only on windows? value? + + var sources = std.ArrayList([]const u8).init(b.allocator); + try sources.append(subdir ++ "/generic/vfs.c"); + slib.addIncludePath(b.path(subdir)); + slib.addIncludePath(b.path(subdir ++ "/generic")); + slib.addIncludePath(b.path(tcldir ++ "/generic")); + slib.addIncludePath(b.path(tcldir ++ "/generic")); + slib.addIncludePath(b.path(tcldir ++ "/win")); + slib.addCSourceFiles(.{ + .files = sources.items, + .flags = flags.items, + }); + + //slib.linkLibrary(stublib); + slib.linkLibC(); + slib.addWin32ResourceFile(.{ + .file = b.path(subdir ++ "/win/tclvfs.rc"), + .flags = &.{ + "-DPACKAGE_MAJOR=1", + "-DPACKAGE_MINOR=4", + "-DPACKAGE_VERSION=" ++ tclvfs_dotversion, + "-DDOTVERSION=" ++ tclvfs_dotversion, + "-DCOMMAVERSION=" ++ tclvfs_dotversion, + "-DVERSION=" ++ tclvfs_nodotversion, + }, + }); //ignored for non-windows targets + // COMMAVERSION??? VERSION??? + + //b.installArtifact(slib); + return slib; //static library +} diff --git a/src/buildsuites/suite_tcl90/build_vqtcl/build_vqtcl_shared.zig b/src/buildsuites/suite_tcl90/build_vqtcl/build_vqtcl_shared.zig new file mode 100644 index 00000000..0606c818 --- /dev/null +++ b/src/buildsuites/suite_tcl90/build_vqtcl/build_vqtcl_shared.zig @@ -0,0 +1,80 @@ +const std = @import("std"); +const fs = std.fs; + +const vqtcl_dotversion = "4.1"; +const vqtcl_nodotversion = "41"; + +pub fn vfsadd_vqtcl_files(comptime tcldir: []const u8, comptime subdir: []const u8, b: *std.Build, vfswrite: *std.Build.Step.WriteFile) !*std.Build.Step.WriteFile { + //_ = tcldir; + //recursive copy + //_ = make_vfs_root.addCopyDirectory(b.path(tcl_source_folder ++ "/../tclvfs/library"), "base/lib/vfs1.4.2", .{}); + _ = vfswrite.addCopyDirectory(b.path(tcldir ++ "/" ++ subdir ++ "/library"), b.pathJoin(&.{ "base", "lib", "vqtcl" ++ vqtcl_dotversion }), .{}); + + return vfswrite; +} +pub fn build_vqtcl(comptime tcldir: []const u8, comptime subdir: []const u8, b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode, stublib: *std.Build.Step.Compile) !*std.Build.Step.Compile { + const lib = b.addSharedLibrary(.{ + .name = "tcl9vlerq" ++ vqtcl_nodotversion, + .target = target, + .optimize = optimize, + }); + //_ = stublib; + var flags = std.ArrayList([]const u8).init(b.allocator); + defer flags.deinit(); + //try flags.appendSlice(&.{ "-Wall", "-O3" }); + //try flags.appendSlice(&.{ "-Wall", "-O2", "-fomit-frame-pointer" }); + try flags.appendSlice(&.{ "-O3", "-fomit-frame-pointer" }); + try flags.appendSlice(&.{ + "-DPACKAGE_NAME=\"vfs\"", + "-DPACKAGE_TARNAME=\"vfs\"", + "-DPACKAGE_VERSION=\"" ++ vqtcl_dotversion ++ "\"", + "-DPACKAGE_STRING=\"vfs " ++ vqtcl_dotversion ++ "\"", + "-DPACKAGE_BUGREPORT=\"\"", + "-DPACKAGE_URL=\"\"", + "-DTCL_CFG_OPTIMIZED=1", + "-DUSE_TCL_STUBS=1", + "-DZIPFS_BUILD=1", + "-DTCL_WIDE_INT_TYPE=long long", + }); + // "-DTCL_MEM_DEBUG=1", //define for all or none of modules that are linked together + + // "-DTCL_MAJOR_VERSION=9", + //"-static-libgcc", //argument unused - review + + var sources = std.ArrayList([]const u8).init(b.allocator); + try sources.append(subdir ++ "/generic/vlerq.c"); + lib.addIncludePath(b.path(subdir)); + lib.addIncludePath(b.path(subdir ++ "/generic")); + lib.addIncludePath(b.path(subdir ++ "/win")); //header for MSVC only - possibly not needed here - unless zig build can use it? + lib.addIncludePath(b.path(tcldir ++ "/generic")); + lib.addIncludePath(b.path(tcldir ++ "/generic")); + if (target.result.os.tag == .windows) { + lib.addIncludePath(b.path(tcldir ++ "/win")); + } else { + lib.addIncludePath(b.path(tcldir ++ "/unix")); + } + lib.addCSourceFiles(.{ + .files = sources.items, + .flags = flags.items, + }); + + lib.linkLibrary(stublib); + lib.linkLibC(); + + // no resource file - todo - make one? + //lib.addWin32ResourceFile(.{ + // .file = b.path(subdir ++ "/win/tclvfs.rc"), + // .flags = &.{ + // "-DPACKAGE_MAJOR=1", + // "-DPACKAGE_MINOR=4", + // "-DPACKAGE_VERSION=" ++ vqtcl_dotversion, + // "-DDOTVERSION=" ++ vqtcl_dotversion, + // "-DCOMMAVERSION=" ++ vqtcl_dotversion, + // "-DVERSION=" ++ vqtcl_nodotversion, + // }, + //}); //ignored for non-windows targets + // COMMAVERSION??? VERSION??? + + b.installArtifact(lib); + return lib; //static library +} diff --git a/src/buildsuites/suite_tcl90/build_zlib/build_zlib.zig b/src/buildsuites/suite_tcl90/build_zlib/build_zlib.zig new file mode 100644 index 00000000..89803e60 --- /dev/null +++ b/src/buildsuites/suite_tcl90/build_zlib/build_zlib.zig @@ -0,0 +1,161 @@ +const std = @import("std"); +const fs = std.fs; + +pub fn build_zlib(comptime subdir: []const u8, b: *std.Build, target: std.Build.ResolvedTarget, optimize: std.builtin.OptimizeMode) !*std.Build.Step.Compile { + var statlibname: []const u8 = undefined; + if (target.result.os.tag == .windows) { + statlibname = "libz"; + } else { + statlibname = "z"; + } + + const statlib = b.addStaticLibrary(.{ + .name = statlibname, + .target = target, + .optimize = optimize, + }); + var zlib_flags = std.ArrayList([]const u8).init(b.allocator); + defer zlib_flags.deinit(); + //try zlib_flags.appendSlice(&.{ "-Wall", "-static-libgcc", "-Wno-error=implicit-function-declaration", "-O3" }); //DL_info undeclared + //try zlib_flags.appendSlice(&.{ "-Wall", "-static-libgcc", "-O3" }); //DL_info undeclared + //try zlib_flags.appendSlice(&.{ "-Wall", "-Wno-error=implicit-function-declaration", "-O3", "-fPIC" }); //seems to work with linux-musl + //try zlib_flags.appendSlice(&.{ "-Wall", "-Wno-error=implicit-function-declaration", "-O3", "-fPIC", "-fno-omit-frame-pointer", "-fsanitize=undefined" }); + + //2024 - seems to work + try zlib_flags.appendSlice(&.{ "-Wall", "-Wno-error=implicit-function-declaration", "-O3", "-fPIC", "-fno-omit-frame-pointer", "-fno-sanitize=undefined" }); + + //2024 trial + //try zlib_flags.appendSlice(&.{ "-Wall", "-Wno-error=implicit-function-declaration", "-O2", "-fPIC", "-fomit-frame-pointer", "-fno-sanitize=undefined" }); + //try zlib_flags.appendSlice(&.{ "-Wall", "-Wno-error=implicit-function-declaration", "-fPIC", "-fomit-frame-pointer", "-fno-sanitize=undefined" }); + + //try zlib_flags.appendSlice(&.{ "-Wall", "-O3" }); + //try zlib_flags.appendSlice(&.{"-O"}); //C99 and later do not support implicit function declarations + //try zlib_flags.appendSlice(&.{ "-O3", "-Wall", "-Wwrite-strings", "-Wpointer-arith", "-Wconversion", "-Wstrict-prototypes", "-Wmissing-prototypes" }); + + var zlib_sources = std.ArrayList([]const u8).init(b.allocator); + { + var dir = try fs.cwd().openDir(subdir, .{ .iterate = true }); + defer dir.close(); + + //var walker = try dir.walk(b.allocator); + //defer walker.deinit(); + var it = dir.iterate(); + + const allowed_exts = [_][]const u8{ + ".c", + }; + while (try it.next()) |entry| { + if (entry.kind == .file) { + const ext = fs.path.extension(entry.name); + const include_file = for (allowed_exts) |e| { + if (std.mem.eql(u8, ext, e)) break true; + } else false; + if (include_file) { + try zlib_sources.append(b.pathJoin(&.{ + subdir, + entry.name, + })); + } + } + } + } + statlib.linkLibC(); + statlib.addIncludePath(b.path(subdir)); + statlib.addIncludePath(b.path(subdir ++ "/contrib/minzip")); + statlib.addCSourceFiles(.{ + .files = zlib_sources.items, + .flags = zlib_flags.items, + }); + b.installArtifact(statlib); + var dylib_flags = std.ArrayList([]const u8).init(b.allocator); + try dylib_flags.appendSlice(zlib_flags.items); + + //trial + //try dylib_flags.appendSlice(&.{ + // "-DZLIB_DLL", + //}); + + //"-Wl,-with-default-msvcrt=ucrtbase", //no effect - seems to be unnecessary anyway - ldd does show msvcrt as well as ucrtbase, but shims seem to all use ucrtbase.dll + //"-Wl,-out-implib,libz.dll.a", //seems to have no effect. zig always creates a .lib + //"-DZLIB_WINAPI", + //"-Wl,-exclude-libs=ALL", + std.debug.print("build_zlib.zig flags {s}\n", .{dylib_flags.items}); + const dylib = b.addSharedLibrary(.{ + .name = "zlib1", + .target = target, + .optimize = optimize, + }); + dylib.linkLibC(); + dylib.addIncludePath(b.path(subdir)); + dylib.addIncludePath(b.path(subdir ++ "/contrib/minizip")); + dylib.addCSourceFiles(.{ + .files = zlib_sources.items, + .flags = dylib_flags.items, + }); + //dylib.addWin32ResourceFile(.{ .file = .{ .path = "zlib/win32/zlib1.rc" } }); //ignored for non-windows targets + dylib.addWin32ResourceFile(.{ .file = b.path(subdir ++ "/win32/zlib1.rc") }); //ignored for non-windows targets + b.installArtifact(dylib); + + const mgz_exe = b.addExecutable(.{ + .name = "minigzip", + .target = target, + .optimize = optimize, + }); + mgz_exe.step.dependOn(&statlib.step); + mgz_exe.addIncludePath(b.path(subdir)); + mgz_exe.addCSourceFile(.{ + .file = b.path(subdir ++ "/test/minigzip.c"), + .flags = zlib_flags.items, + }); + mgz_exe.linkLibC(); + mgz_exe.linkLibrary(statlib); + b.installArtifact(mgz_exe); + + const eg_exe = b.addExecutable(.{ + .name = "zlib_example", + .target = target, + .optimize = optimize, + }); + eg_exe.step.dependOn(&statlib.step); + eg_exe.addIncludePath(b.path(subdir)); + eg_exe.addCSourceFile(.{ + .file = b.path(subdir ++ "/test/example.c"), + .flags = zlib_flags.items, + }); + eg_exe.linkLibC(); + eg_exe.linkLibrary(statlib); + b.installArtifact(eg_exe); + + const egd_exe = b.addExecutable(.{ + .name = "zlib_example_d", + .target = target, + .optimize = optimize, + }); + egd_exe.step.dependOn(&statlib.step); + egd_exe.addIncludePath(b.path(subdir)); + egd_exe.addCSourceFile(.{ + .file = b.path(subdir ++ "/test/example.c"), + .flags = dylib_flags.items, + }); + egd_exe.linkLibrary(dylib); + egd_exe.root_module.addRPathSpecial("$ORIGIN/../lib"); + egd_exe.linkLibC(); + b.installArtifact(egd_exe); + + const mgzd_exe = b.addExecutable(.{ + .name = "minigzip_d", + .target = target, + .optimize = optimize, + }); + mgzd_exe.step.dependOn(&statlib.step); + mgzd_exe.addIncludePath(b.path(subdir)); + mgzd_exe.addCSourceFile(.{ + .file = b.path(subdir ++ "/test/minigzip.c"), + .flags = dylib_flags.items, + }); + mgzd_exe.root_module.addRPathSpecial("$ORIGIN/../lib"); + mgzd_exe.linkLibrary(dylib); + b.installArtifact(mgzd_exe); + + return statlib; +} diff --git a/src/buildsuites/suite_tcl90/patches/README.md b/src/buildsuites/suite_tcl90/patches/README.md new file mode 100644 index 00000000..dcef94e3 --- /dev/null +++ b/src/buildsuites/suite_tcl90/patches/README.md @@ -0,0 +1,41 @@ +# Recovered 2024 Tcl source patches (G-096) + +Origin: `c:/buildtcl/2024zig/build_tcl90/patch/` (reference snapshot +`TEMP_REFERENCE/2024zig/build_tcl90/patch/`), written against ~Tcl 9.0b4-era sources +(Aug 2024; tclZipfs/tclCmdIL Nov 2024). Recovered into tracked form 2026-07-20 - these +files previously existed only in those two VCS-ignored on-disk copies. + +NONE of these are applied by the suite's default build: `suite.tcl build` compiles +stock upstream sources. Rebasing/applying is per-patch opt-in work. + +## tclMain.c.piperepl.patch / tclMain_piperepl.c (the TCLSH_PIPEREPL capability) + +`tclMain_piperepl.c` is the full patched file; the `.patch` is its diff against the +era's stock `tclMain.c`. + +Purpose (the G-096 goal capability): allow returning to a standard C-level tcl repl +after launching from a kit with its own `main.tcl` - not possible with unmodified +sources. Gated by the `TCLSH_PIPEREPL` env var (unset/`0` = stock behaviour). When +enabled: + +- Publishes `::tclsh(istty)` (unlinked fact) plus linked `::tclsh(dorepl)` and + `::tclsh(evalinput)` before the startup script runs; a script-arg launch defaults + `dorepl` to 0 (stock semantics) but the script may set `::tclsh(dorepl) 1` to drop + into the interactive repl after it completes. +- Piped (non-tty) input the script did not consume is accumulated into + `::tclsh(inputbuffer)` rather than evaluated as commands, unless the script opts in + with `::tclsh(evalinput) 1` - protects arbitrary piped data from accidental eval. +- On stdin eof with `dorepl` set, stdin is reopened from the console (`CONIN$` on + windows, `/dev/tty` elsewhere) and installed as the std channel, yielding a live + standard repl after a pipeline ends. + +Status: NOT yet rebased onto current Tcl 9 sources. Note the punkshell-level analogue +for the punk repl is G-038 (piped-to-interactive session continuity) - this patch is +the plain-tclsh/kit-runtime counterpart. + +## tclZipfs.patch, tclCmdIL.patch + +Companion experiment patches from the same era (zipfs behaviour and tclCmdIL tweak), +recovered for durability; unexamined in detail. See the fossil-era notes in +`TEMP_REFERENCE/2024zig/build_tcl90/patch/` (doc/, prev/, test_zipfs_patch/) for their +surrounding experiment context. diff --git a/src/buildsuites/suite_tcl90/patches/tclCmdIL.patch b/src/buildsuites/suite_tcl90/patches/tclCmdIL.patch new file mode 100644 index 00000000..317b9922 --- /dev/null +++ b/src/buildsuites/suite_tcl90/patches/tclCmdIL.patch @@ -0,0 +1,13 @@ +--- tclCmdIL_orig.c Sat Oct 05 06:09:52 2024 ++++ tclCmdIL.c Mon Nov 18 13:59:01 2024 +@@ -3926,6 +3926,10 @@ + itemPtr = SelectObjFromSublist(listv[i+groupOffset], + &sortInfo); + Tcl_ListObjAppendElement(interp, listPtr, itemPtr); ++ } else if (returnSubindices && (sortInfo.indexc == 0) && (groupSize > 1)) { ++ Tcl_BounceRefCount(itemPtr); ++ itemPtr = listv[i + groupOffset]; ++ Tcl_ListObjAppendElement(interp, listPtr, itemPtr); + } else if (groupSize > 1) { + Tcl_ListObjReplace(interp, listPtr, LIST_MAX, 0, + groupSize, &listv[i]); diff --git a/src/buildsuites/suite_tcl90/patches/tclMain.c.piperepl.patch b/src/buildsuites/suite_tcl90/patches/tclMain.c.piperepl.patch new file mode 100644 index 00000000..a4a284a7 --- /dev/null +++ b/src/buildsuites/suite_tcl90/patches/tclMain.c.piperepl.patch @@ -0,0 +1,233 @@ +--- tclMain.c Fri Aug 16 04:10:58 2024 ++++ tclMain_piperepl.c Mon Aug 19 01:24:03 2024 +@@ -105,6 +105,22 @@ + * commands. */ + } InteractiveState; + ++typedef struct { ++ int istty; /* Non-zero means standard input is a ++ * terminal-like device ++ * Unlike InteractiveState.tty this is ++ * unaffected by whether a script path ++ * was specified at argv0 */ ++ int dorepl; /* whether to run the default repl ++ * linked to ::tclsh(dorepl) ++ * so script file or stdin script ++ * can influence */ ++ int reopened; /* if 1, we are processing from console - not piped input*/ ++ int evalinput; /* default 0 - whether to evaluate piped input as commands ++ * This is input the script (if any) didn't consume ++ */ ++ Tcl_Obj *inputbuffer; ++} PipeRepl; + /* + * Forward declarations for functions defined later in this file. + */ +@@ -291,6 +307,10 @@ + Tcl_MainLoopProc *mainLoopProc; + Tcl_Channel chan; + InteractiveState is; ++ PipeRepl piperepl; ++ Tcl_Obj *tclInteractive; //JMN ++ int ttyAtStart; // Whether we initially had piped data or not ++ int inputReopen; // flag for reopening stdin + + TclpSetInitialEncodings(); + if (argc > 0) { +@@ -359,6 +379,37 @@ + */ + + is.tty = isatty(0); ++ ttyAtStart = is.tty; //JMN ++ int hasPipeRepl; //flag for whether piperepl and ::tclsh() behaviour enabled ++ { ++ const char *s; ++ Tcl_DString ds; ++ s = TclGetEnv("TCLSH_PIPEREPL", &ds); ++ hasPipeRepl = ((s != NULL) && strcmp(s, "0")); ++ if (s != NULL) { ++ Tcl_DStringFree(&ds); ++ } ++ } ++ piperepl.reopened = 0; ++ piperepl.dorepl = 0; ++ piperepl.evalinput = 0; ++ if (hasPipeRepl) { ++ TclNewObj(piperepl.inputbuffer); ++ piperepl.istty = ttyAtStart; ++ piperepl.dorepl = ttyAtStart; ++ //unlinked - setting from script should have no effect ++ Tcl_SetVar2Ex(interp, "tclsh", "istty", ++ Tcl_NewBooleanObj(ttyAtStart), TCL_GLOBAL_ONLY); ++ //will be linked so script/stdin can influence ++ // if path (script) supplied, but no stdin ++ // - will be set 0 to match default 'tclsh