Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 11 additions & 20 deletions CompileCheck.zig
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ fn make(step: *std.Build.Step, options: std.Build.Step.MakeOptions) anyerror!voi
const source_path = check.source_path.getPath2(b, step);

const result = blk: {
var zig_args: std.ArrayList([]const u8) = .init(b.allocator);
var zig_args: std.array_list.Managed([]const u8) = .init(b.allocator);
defer zig_args.deinit();
try zig_args.append(b.graph.zig_exe);
try zig_args.append(switch (check.kind) {
Expand All @@ -170,7 +170,7 @@ fn make(step: *std.Build.Step, options: std.Build.Step.MakeOptions) anyerror!voi
.other_step => |other| {
switch (other.kind) {
.exe => return step.fail("cannot link with an executable build artifact", .{}),
.@"test" => return step.fail("cannot link with a test", .{}),
.@"test", .test_obj => return step.fail("cannot link with a test", .{}),
.obj => {
try zig_args.append(other.getEmittedBin().getPath2(b, step));
},
Expand Down Expand Up @@ -248,7 +248,7 @@ fn make(step: *std.Build.Step, options: std.Build.Step.MakeOptions) anyerror!voi
.undeclared_identifier_count = undeclared_identifier_count,
} };
},
inline else => return step.fail("zig {}", .{fmtTerm(result.term)}),
inline else => return step.fail("zig {f}", .{fmtTerm(result.term)}),
}
}

Expand All @@ -265,38 +265,29 @@ fn getGeneratedFilePath(compile: *std.Build.Step.Compile, comptime tag_name: []c

const generated_file = maybe_path orelse {
{
std.debug.lockStdErr();
defer std.debug.unlockStdErr();
const stderr = std.io.getStdErr();
std.Build.dumpBadGetPathHelp(&compile.step, stderr, compile.step.owner, asking_step) catch {};
const stderr = std.debug.lockStderrWriter(&.{});
defer std.debug.unlockStderrWriter();
std.Build.dumpBadGetPathHelp(&compile.step, stderr, .detect(.stderr()), compile.step.owner, asking_step) catch {};
}
@panic("missing emit option for " ++ tag_name);
};

const path = generated_file.path orelse {
{
std.debug.lockStdErr();
defer std.debug.unlockStdErr();
const stderr = std.io.getStdErr();
std.Build.dumpBadGetPathHelp(&compile.step, stderr, compile.step.owner, asking_step) catch {};
const stderr = std.debug.lockStderrWriter(&.{});
defer std.debug.unlockStderrWriter();
std.Build.dumpBadGetPathHelp(&compile.step, stderr, .detect(.stderr()), compile.step.owner, asking_step) catch {};
}
@panic(tag_name ++ " is null. Is there a missing step dependency?");
};

return path;
}

fn fmtTerm(term: ?std.process.Child.Term) std.fmt.Formatter(formatTerm) {
fn fmtTerm(term: ?std.process.Child.Term) std.fmt.Alt(?std.process.Child.Term, formatTerm) {
return .{ .data = term };
}
fn formatTerm(
term: ?std.process.Child.Term,
comptime fmt: []const u8,
options: std.fmt.FormatOptions,
writer: anytype,
) !void {
_ = fmt;
_ = options;
fn formatTerm(term: ?std.process.Child.Term, writer: *std.Io.Writer) error{WriteFailed}!void {
if (term) |t| switch (t) {
.Exited => |code| try writer.print("exited with code {}", .{code}),
.Signal => |sig| try writer.print("terminated with signal {}", .{sig}),
Expand Down
26 changes: 14 additions & 12 deletions build.zig
Original file line number Diff line number Diff line change
Expand Up @@ -432,18 +432,12 @@ fn addPythonExe(
) *std.Build.Step.Compile {
const exe = b.addExecutable(.{
.name = args.name,
.target = target,
.optimize = optimize,
.root_module = b.createModule(.{
.target = target,
.optimize = optimize,
}),
});

switch (args.pyconfig.version) {
.@"3.11.13" => {
// workaround dictobject.c memcpy alignment issue
exe.root_module.sanitize_c = false;
},
.@"3.12.11" => {},
}

exe.root_module.addCMacro("Py_BUILD_CORE", "");
exe.root_module.addCMacro("_GNU_SOURCE", "");
switch (optimize) {
Expand Down Expand Up @@ -593,7 +587,15 @@ fn addPythonExe(
},
}),
},
.flags = &flags_common,
.flags = concat(b.allocator, &.{
&flags_common,
switch (args.pyconfig.version) {
// workaround dictobject.c memcpy alignment issue
.@"3.11.13" => &.{"-fno-sanitize=alignment"},
// tokenizer.c uses pointer overflow in restore_fstring_buffers
.@"3.12.11" => &.{"-fno-sanitize=pointer-overflow"},
},
}),
});

exe.addCSourceFile(.{
Expand Down Expand Up @@ -1235,7 +1237,7 @@ fn addPyconfig(
};

const config_header = b.addConfigHeader(.{
.style = .{ .autoconf = upstream.path("pyconfig.h.in") },
.style = .{ .autoconf_undef = upstream.path("pyconfig.h.in") },
.include_path = "pyconfig.h",
}, .{
.ALIGNOF_LONG = 8,
Expand Down
10 changes: 5 additions & 5 deletions build.zig.zon
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
.name = .cpython,
.fingerprint = 0x3224901d1babdd14,
.version = "0.0.0",
.minimum_zig_version = "0.14.1",
.minimum_zig_version = "0.15.2",
.dependencies = .{
.@"upstream_3.11.13" = .{
.url = "git+https://github.com/python/cpython#498b971ea3673012a1d4b21860b229d55fc6e575",
Expand All @@ -15,12 +15,12 @@
.lazy = true,
},
.zlib = .{
.url = "https://github.com/allyourcodebase/zlib/archive/6c72830882690c1eb2567a537525c3f432c1da50.tar.gz",
.hash = "zlib-1.3.1-ZZQ7lVgMAACwO4nUUd8GLhsuQ5JQq_VAhlEiENJTUv6h",
.url = "git+https://github.com/allyourcodebase/zlib#c2585c096171b8fbc8e5f78ab6c91b39e3573e15",
.hash = "zlib-1.3.1-ZZQ7lcMNAABPzkWdm_9y0tjlN17kF7czIiTVQ7h10rMR",
},
.openssl = .{
.url = "https://github.com/allyourcodebase/openssl/archive/f348124c5382bcc377f1b3277357cbf2ed2fb8db.tar.gz",
.hash = "openssl-3.3.1-2-TC9C3Se3ZACF5WO_CjoD7Bt_X94oCsAAbbwhOp1rTZBe",
.url = "git+https://github.com/allyourcodebase/openssl#7d4b2590b3b05fbc0e5cc20e2704a968e63503b1",
.hash = "openssl-3.3.2-TC9C3Vy3ZABkts70T3a6QfLYghNUy0tI42ksiW7jRmvd",
.lazy = true,
},
},
Expand Down
91 changes: 54 additions & 37 deletions makesetup.zig
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ pub fn main() !void {
// no need to free

if (all_args.len <= 1) {
try std.io.getStdErr().writer().writeAll("usage: makesetup UPSTREAM_SRC OUT_DIR SETUP_FILES...\n");
var stderr = std.fs.File.stderr().writer(&.{});
try stderr.interface.writeAll("usage: makesetup UPSTREAM_SRC OUT_DIR SETUP_FILES...\n");
std.process.exit(0xff);
}
const args = all_args[1..];
Expand Down Expand Up @@ -36,51 +37,67 @@ pub fn main() !void {
{
var file = try out_dir.createFile("config.c", .{});
defer file.close();
var bw = std.io.bufferedWriter(file.writer());
const writer = bw.writer();
try writer.print("/* Generated automatically from {s} by makesetup. */\n", .{config_in_path});
var lines = std.mem.splitScalar(u8, config_in, '\n');
while (lines.next()) |line| {
if (std.mem.indexOf(u8, line, "MARKER 1")) |_| {
var it = setup.modules.iterator();
while (it.next()) |entry| {
if (!entry.value_ptr.enabled) continue;
try writer.print("extern PyObject* PyInit_{s}(void);\n", .{entry.key_ptr.*});
}
} else if (std.mem.indexOf(u8, line, "MARKER 2")) |_| {
var it = setup.modules.iterator();
while (it.next()) |entry| {
if (!entry.value_ptr.enabled) continue;
try writer.print(" {{\"{s}\", PyInit_{0s}}},\n", .{entry.key_ptr.*});
}
}
try writer.writeAll(line);
try writer.writeByte('\n');
}
try bw.flush();
var out_file_buf: [4096]u8 = undefined;
var file_writer = file.writer(&out_file_buf);
writeConfigC(setup, config_in_path, config_in, &file_writer.interface) catch |err| switch (err) {
error.WriteFailed => return file_writer.err orelse error.Unexpected,
};
}

{
var out_file = try out_dir.createFile("module-compile-args.txt", .{});
defer out_file.close();
var bw = std.io.bufferedWriter(out_file.writer());
const writer = bw.writer();
var out_file_buf: [4096]u8 = undefined;
var file_writer = out_file.writer(&out_file_buf);
writeCompileArgs(setup, &file_writer.interface) catch |err| switch (err) {
error.WriteFailed => return file_writer.err orelse error.Unexpected,
};
}
}

var it = setup.modules.iterator();
while (it.next()) |entry| {
const module_name = entry.key_ptr.*;
{
const suffix: []const u8 = if (entry.value_ptr.enabled) "" else " (DISABLED)";
try writer.print("# Module '{s}'{s}\n", .{ module_name, suffix });
fn writeConfigC(
setup: Setup,
config_in_path: []const u8,
config_in: []const u8,
writer: *std.Io.Writer,
) error{WriteFailed}!void {
try writer.print("/* Generated automatically from {s} by makesetup. */\n", .{config_in_path});
var lines = std.mem.splitScalar(u8, config_in, '\n');
while (lines.next()) |line| {
if (std.mem.indexOf(u8, line, "MARKER 1")) |_| {
var it = setup.modules.iterator();
while (it.next()) |entry| {
if (!entry.value_ptr.enabled) continue;
try writer.print("extern PyObject* PyInit_{s}(void);\n", .{entry.key_ptr.*});
}
const prefix: []const u8 = if (entry.value_ptr.enabled) "" else "# ";
for (entry.value_ptr.compile_args) |compile_arg| switch (compile_arg) {
.source => |src| try writer.print("{s}Modules/{s}\n", .{ prefix, src }),
.include => |inc| try writer.print("{s}-I{s}\n", .{ prefix, inc }),
};
} else if (std.mem.indexOf(u8, line, "MARKER 2")) |_| {
var it = setup.modules.iterator();
while (it.next()) |entry| {
if (!entry.value_ptr.enabled) continue;
try writer.print(" {{\"{s}\", PyInit_{0s}}},\n", .{entry.key_ptr.*});
}
}
try writer.writeAll(line);
try writer.writeByte('\n');
}
try writer.flush();
}

fn writeCompileArgs(setup: Setup, writer: *std.Io.Writer) error{WriteFailed}!void {
var it = setup.modules.iterator();
while (it.next()) |entry| {
const module_name = entry.key_ptr.*;
{
const suffix: []const u8 = if (entry.value_ptr.enabled) "" else " (DISABLED)";
try writer.print("# Module '{s}'{s}\n", .{ module_name, suffix });
}
try bw.flush();
const prefix: []const u8 = if (entry.value_ptr.enabled) "" else "# ";
for (entry.value_ptr.compile_args) |compile_arg| switch (compile_arg) {
.source => |src| try writer.print("{s}Modules/{s}\n", .{ prefix, src }),
.include => |inc| try writer.print("{s}-I{s}\n", .{ prefix, inc }),
};
}
try writer.flush();
}

const CompileArg = union(enum) {
Expand Down
56 changes: 35 additions & 21 deletions replace.zig
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ pub fn main() !void {
// no need to free

if (all_args.len <= 1) {
try std.io.getStdErr().writer().writeAll("usage: replace IN_FILE OUT_FILE NAME=VALUE...\n");
var stderr = std.fs.File.stderr().writer(&.{});
try stderr.interface.writeAll("usage: replace IN_FILE OUT_FILE NAME=VALUE...\n");
std.process.exit(0xff);
}
const args = all_args[1..];
Expand All @@ -17,10 +18,7 @@ pub fn main() !void {
const out_path = args[1];
const replacements = args[2..];

var map: std.StringHashMapUnmanaged(struct {
count: usize,
value: []const u8,
}) = .{};
var map: std.StringHashMapUnmanaged(MapNode) = .{};
for (replacements) |r| {
const eq_index = std.mem.indexOfScalar(u8, r, '=') orelse errExit(
"expected NAME=VALUE cmdline arg but got '{s}'",
Expand All @@ -41,9 +39,38 @@ pub fn main() !void {

var out_file = try std.fs.cwd().createFile(out_path, .{});
defer out_file.close();
var bw = std.io.bufferedWriter(out_file.writer());
const writer = bw.writer();

var out_file_buf: [4096]u8 = undefined;
var file_writer = out_file.writer(&out_file_buf);
writeFile(in_path, in, &map, &file_writer.interface) catch |err| switch (err) {
error.WriteFailed => return file_writer.err orelse error.Unexpected,
};

var unused_count: usize = 0;
var it = map.iterator();
while (it.next()) |entry| {
if (entry.value_ptr.count == 0) {
std.log.err("unused variable '{s}'", .{entry.key_ptr.*});
unused_count += 1;
}
}
if (unused_count != 0) {
std.log.err("{} unused variable(s), the did not appear in template '{s}'", .{ unused_count, in_path });
std.process.exit(0xff);
}
}

const MapNode = struct {
count: usize,
value: []const u8,
};

fn writeFile(
in_path: []const u8,
in: []const u8,
map: *const std.StringHashMapUnmanaged(MapNode),
writer: *std.Io.Writer,
) error{WriteFailed}!void {
var missing_count: usize = 0;
var offset: usize = 0;
while (true) {
Expand All @@ -65,21 +92,8 @@ pub fn main() !void {
offset = end + 1;
}
try writer.writeAll(in[offset..]);
try bw.flush();
try writer.flush();
if (missing_count > 0) errExit("{} missing variable(s) for template '{s}'", .{ missing_count, in_path });

var unused_count: usize = 0;
var it = map.iterator();
while (it.next()) |entry| {
if (entry.value_ptr.count == 0) {
std.log.err("unused variable '{s}'", .{entry.key_ptr.*});
unused_count += 1;
}
}
if (unused_count != 0) {
std.log.err("{} unused variable(s), the did not appear in template '{s}'", .{ unused_count, in_path });
std.process.exit(0xff);
}
}

fn errExit(comptime fmt: []const u8, args: anytype) noreturn {
Expand Down