You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

161 lines
7.3 KiB

const std = @import("std");
const common = @import("../build_common.zig");
//build_tclvfs86 - tclvfs (TRUNK, 1.4.2 era) loadable extension for the 8.6
//suite (G-099). Forked from suite_tcl90/build_tclvfs/build_tclvfs_shared.zig
//(duplication-with-a-note posture) with the 8.6 differences:
// - the dll is BUILT UNDER THE TCL8 TEA-NMAKE NAME (vfs<nodots>t.dll, e.g
// vfs142t.dll - rules.vc PRJLIBNAME8 with PROJECT=vfs, SUFX 't' kept on a
// tcl86 host): the configured library/vfs.tcl.in loads @PKG_LIB_FILE8@
// with NO explicit init symbol, so Tcl's load-time package-name guessing
// derives the _Init name from the file's alpha prefix - 'vfs...' guesses
// Vfs_Init (correct); a 'tclvfs...' spelling guesses Tclvfs_Init and
// fails. @PKG_LIB_FILE9@ is still substituted so the script is complete.
// - the 9.0 fork's ZIPFS_BUILD / TCL_WIDE_INT_TYPE defines dropped (9-isms).
// - trunk vfs.c uses the same lowercase BUILD_vfs export guard as forTcl9
// (verified in the staged tree), so the guard define carries over.
//The include-order shim carries over: under zig's mingw headers '__stat64' is
//a MACRO for _stat64 (_mingw_stat64.h, pulled in by <sys/stat.h>); tcl.h's
//'typedef struct __stat64 Tcl_StatBuf' parsed BEFORE that include binds a raw
//forever-incomplete __stat64 tag (8.6 tcl.h uses the same typedef under
//_WIN64). Compiling a generated TU that includes <sys/stat.h> first makes the
//macro visible when tcl.h parses.
pub const TclvfsInfo = struct {
dotversion: []const u8, //e.g "1.4.2"
nodots: []const u8, //e.g "142"
dll_file: []const u8, //the tcl8-named dll this suite builds, e.g "vfs142t.dll"
dll9_file: []const u8, //tcl9 spelling for template substitution completeness
major: []const u8,
minor: []const u8,
};
pub fn versionInfo(b: *std.Build, comptime tree_from_root: []const u8) TclvfsInfo {
const dotversion = common.acInitVersion(b, tree_from_root);
const nodots = common.stripChars(b, dotversion, ".");
var parts = std.mem.splitScalar(u8, dotversion, '.');
const major = parts.next() orelse "0";
const minor = parts.next() orelse "0";
return .{
.dotversion = dotversion,
.nodots = nodots,
.dll_file = b.fmt("vfs{s}t.dll", .{nodots}),
.dll9_file = b.fmt("tcl9vfs{s}.dll", .{nodots}),
.major = b.dupe(major),
.minor = b.dupe(minor),
};
}
//configure-products (vfs.tcl, pkgIndex.tcl) generated from their .in templates
//at configure time.
fn configuredContent(b: *std.Build, comptime subdir: []const u8, comptime template: []const u8, info: TclvfsInfo) []const u8 {
var t: []const u8 = common.readSourceFile(b, subdir ++ "/" ++ template);
t = common.replaceAll(b, t, "@PACKAGE_VERSION@", info.dotversion);
t = common.replaceAll(b, t, "@PKG_LIB_FILE9@", info.dll9_file);
t = common.replaceAll(b, t, "@PKG_LIB_FILE8@", info.dll_file);
return t;
}
//install the tclvfs script package (lib/vfs<ver>) into the prefix - the two
//generated configure-products, the library scripts + template dir copied, and
//the dll alongside (vfs.tcl loads it from its own dir via ::vfs::self).
pub fn install_tclvfs_package(comptime subdir: []const u8, b: *std.Build, tclvfs_compile: *std.Build.Step.Compile) !void {
const info = versionInfo(b, subdir);
const pkgsub = b.fmt("lib/vfs{s}", .{info.dotversion});
const install_scripts = b.addInstallDirectory(.{
.source_dir = b.path(subdir ++ "/library"),
.install_dir = .prefix,
.install_subdir = pkgsub,
.include_extensions = &.{".tcl"},
});
b.getInstallStep().dependOn(&install_scripts.step);
//template dir wholesale (carries non-.tcl support files such as tclIndex)
const install_template = b.addInstallDirectory(.{
.source_dir = b.path(subdir ++ "/library/template"),
.install_dir = .prefix,
.install_subdir = b.fmt("{s}/template", .{pkgsub}),
});
b.getInstallStep().dependOn(&install_template.step);
const wf = b.addWriteFiles();
inline for (.{
.{ "library/vfs.tcl.in", "vfs.tcl" },
.{ "pkgIndex.tcl.in", "pkgIndex.tcl" },
}) |pair| {
const gen = wf.add(pair[1], configuredContent(b, subdir, pair[0], info));
const inst = b.addInstallFileWithDir(gen, .prefix, b.fmt("{s}/{s}", .{ pkgsub, pair[1] }));
b.getInstallStep().dependOn(&inst.step);
}
const dll_inst = b.addInstallFileWithDir(tclvfs_compile.getEmittedBin(), .prefix, b.fmt("{s}/{s}", .{ pkgsub, info.dll_file }));
b.getInstallStep().dependOn(&dll_inst.step);
}
pub fn build_tclvfs86(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 info = versionInfo(b, subdir);
const lib = b.addLibrary(.{
.linkage = .dynamic,
.name = b.fmt("vfs{s}t", .{info.nodots}),
.root_module = b.createModule(.{
.target = target,
.optimize = optimize,
}),
});
var flags = std.array_list.Managed([]const u8).init(b.allocator);
defer flags.deinit();
try flags.appendSlice(&.{ "-Wall", "-O3", "-fomit-frame-pointer" });
try flags.appendSlice(&.{
"-DPACKAGE_NAME=\"vfs\"",
"-DPACKAGE_TARNAME=\"vfs\"",
b.fmt("-DPACKAGE_VERSION=\"{s}\"", .{info.dotversion}),
b.fmt("-DPACKAGE_STRING=\"vfs {s}\"", .{info.dotversion}),
"-DPACKAGE_BUGREPORT=\"\"",
"-DPACKAGE_URL=\"\"",
//vfs.c guards <sys/stat.h> paths behind HAVE_SYS_STAT_H and needs the
//COMPLETE Tcl_StatBuf - see the include-order shim below.
"-DHAVE_SYS_STAT_H=1",
"-DTCL_CFG_OPTIMIZED=1",
"-DUSE_TCL_STUBS=1",
});
if (target.result.os.tag == .windows) {
try flags.appendSlice(&.{
"-DBUILD_vfs=/**/",
});
}
lib.root_module.addIncludePath(b.path(subdir));
lib.root_module.addIncludePath(b.path(subdir ++ "/generic"));
lib.root_module.addIncludePath(b.path(tcldir ++ "/generic"));
if (target.result.os.tag == .windows) {
lib.root_module.addIncludePath(b.path(tcldir ++ "/win"));
} else {
lib.root_module.addIncludePath(b.path(tcldir ++ "/unix"));
}
//Include-order shim (overlay TU - source trees never written): see the
//header comment for the __stat64 macro-vs-tag story.
const wf_shim = b.addWriteFiles();
const vfs_shim = wf_shim.add("vfs_statorder_shim.c",
\\/* generated include-order shim - see build_tclvfs86.zig */
\\#include <sys/stat.h>
\\#include "vfs.c"
\\
);
lib.root_module.addCSourceFile(.{
.file = vfs_shim,
.flags = flags.items,
});
lib.root_module.linkLibrary(stublib);
lib.root_module.link_libc = true;
lib.root_module.addWin32ResourceFile(.{
.file = b.path(subdir ++ "/win/tclvfs.rc"),
.flags = &.{
b.fmt("-DPACKAGE_MAJOR={s}", .{info.major}),
b.fmt("-DPACKAGE_MINOR={s}", .{info.minor}),
b.fmt("-DPACKAGE_VERSION={s}", .{info.dotversion}),
b.fmt("-DDOTVERSION={s}", .{info.dotversion}),
b.fmt("-DCOMMAVERSION={s}", .{info.dotversion}),
b.fmt("-DVERSION={s}", .{info.nodots}),
},
}); //ignored for non-windows targets
return lib;
}