diff --git a/build.zig b/build.zig index ad95ab7..472ca8c 100644 --- a/build.zig +++ b/build.zig @@ -628,14 +628,10 @@ pub fn ldcBuildStep(b: *Build, options: DCompileStep) !*std.Build.Step.InstallDi installdir.step.dependOn(&ldc_exec.step); if (options.zig_cc) { - const zcc = buildZigCC(b); - const install = b.addInstallArtifact(zcc, .{ .dest_dir = .{ .override = .{ .custom = "tools" } } }); - const zcc_path = b.pathJoin(&.{ b.install_prefix, "tools", if (options.target.result.os.tag == .windows) "zcc.exe" else "zcc" }); - const zcc_exists = !std.meta.isError(std.fs.accessAbsolute(zcc_path, .{})); - if (!zcc_exists) - ldc_exec.step.dependOn(&install.step); - ldc_exec.addArg(b.fmt("--gcc={s}", .{zcc_path})); - ldc_exec.addArg(b.fmt("--linker={s}", .{zcc_path})); + const target_options = try buildOptions(b, options.target); + const zcc = buildZigCC(b, target_options); + ldc_exec.addPrefixedFileArg("--gcc=", zcc.getEmittedBin()); + ldc_exec.addPrefixedFileArg("--linker=", zcc.getEmittedBin()); } const example_run = b.addSystemCommand(&.{b.pathJoin(&.{ b.install_path, outputDir, options.name })}); @@ -738,16 +734,156 @@ pub fn path(b: *std.Build, sub_path: []const u8) std.Build.LazyPath { // -------------------------- Others Configuration -------------------------- // zig-cc wrapper for ldc2 -pub fn buildZigCC(b: *Build) *CompileStep { +pub fn buildZigCC(b: *std.Build, options: *std.Build.Step.Options) *std.Build.Step.Compile { + const zigcc = b.addWriteFiles(); + const exe = b.addExecutable(.{ .name = "zcc", .target = b.graph.host, .optimize = .ReleaseSafe, - .root_source_file = b.path("tools/zigcc.zig"), + .root_source_file = zigcc.add("zcc.zig", generated_zcc), }); + exe.root_module.addOptions("build_options", options); return exe; } +pub fn buildOptions(b: *std.Build, target: std.Build.ResolvedTarget) !*std.Build.Step.Options { + const zigcc_options = b.addOptions(); + + // Native target, zig can read 'zig libc' contents and also link system libraries. + const native = if (target.query.isNative()) switch (target.result.abi) { + .msvc => "native-native-msvc", + else => "native-native", + } else try target.result.zigTriple(b.allocator); + zigcc_options.addOption( + ?[]const u8, + "triple", + native, + ); + zigcc_options.addOption( + ?[]const u8, + "cpu", + target.result.cpu.model.name, + ); + return zigcc_options; +} + +const generated_zcc = + \\ const std = @import("std"); + \\ const builtin = @import("builtin"); + \\ const build_options = @import("build_options"); + \\ // [NOT CHANGE!!] => skip flag + \\ // replace system-provider resources to zig provider resources + \\ + \\ pub fn main() !void { + \\ var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + \\ defer _ = std.debug.assert(gpa.deinit() == .ok); // ok or leak + \\ const allocator = gpa.allocator(); + \\ + \\ var args = try std.process.argsWithAllocator(allocator); + \\ defer args.deinit(); + \\ + \\ _ = args.skip(); // skip arg[0] + \\ + \\ var cmds = std.ArrayList([]const u8).init(allocator); + \\ defer cmds.deinit(); + \\ + \\ try cmds.append("zig"); + \\ try cmds.append("cc"); + \\ + \\ while (args.next()) |arg| { + \\ // HACK: ldmd2 emit '-target' flag for Darwin, but zigcc already have it + \\ if (std.mem.startsWith(u8, arg, "arm64-apple-") or + \\ std.mem.startsWith(u8, arg, "x86_64-apple-")) + \\ { + \\ // NOT CHANGE!! + \\ } else if (std.mem.startsWith(u8, arg, "-target")) { + \\ // NOT CHANGE!! + \\ } else if (std.mem.endsWith(u8, arg, "-group")) { + \\ try cmds.appendSlice(&.{ + \\ "-Wl,--start-group", + \\ "-Wl,--end-group", + \\ }); + \\ } else if (std.mem.endsWith(u8, arg, "-dynamic")) { + \\ try cmds.append("-Wl,--export-dynamic"); + \\ } else if (std.mem.eql(u8, arg, "--exclude-libs") or std.mem.eql(u8, arg, "ALL")) { + \\ // NOT CHANGE!! + \\ } else if (std.mem.endsWith(u8, arg, "rv64gc") or + \\ std.mem.endsWith(u8, arg, "rv32i_zicsr_zifencei")) + \\ { + \\ // NOT CHANGE!! + \\ } else if (std.mem.startsWith(u8, arg, "--hash-style")) { + \\ // NOT CHANGE!! + \\ } else if (std.mem.startsWith(u8, arg, "--build-id")) { + \\ // NOT CHANGE!! + \\ } else if (std.mem.endsWith(u8, arg, "whole-archive")) { + \\ // NOT CHANGE!! + \\ } else if (std.mem.startsWith(u8, arg, "--eh-frame-hdr")) { + \\ // NOT CHANGE!! + \\ } else if (std.mem.endsWith(u8, arg, "as-needed")) { + \\ // NOT CHANGE!! + \\ } else if (std.mem.endsWith(u8, arg, "gcc") or + \\ std.mem.endsWith(u8, arg, "gcc_s")) + \\ { + \\ // NOT CHANGE!! + \\ } else if (std.mem.startsWith(u8, arg, "-lFortran")) { + \\ // NOT CHANGE!! + \\ } else if (std.mem.endsWith(u8, arg, "linkonceodr-outlining")) { + \\ // NOT CHANGE!! + \\ } else if (std.mem.startsWith(u8, arg, "aarch64linux") or + \\ std.mem.startsWith(u8, arg, "elf")) + \\ { + \\ // NOT CHANGE!! + \\ } else if (std.mem.startsWith(u8, arg, "/lib/ld-") or + \\ std.mem.startsWith(u8, arg, "-dynamic-linker")) + \\ { + \\ // NOT CHANGE!! + \\ } else if (std.mem.endsWith(u8, arg, "crtendS.o") or + \\ std.mem.endsWith(u8, arg, "crtn.o")) + \\ { + \\ // NOT CHANGE!! + \\ } else if (std.mem.endsWith(u8, arg, "crtbeginS.o") or + \\ std.mem.endsWith(u8, arg, "crti.o") or + \\ std.mem.endsWith(u8, arg, "Scrt1.o")) + \\ { + \\ // NOT CHANGE!! + \\ } else if (std.mem.startsWith(u8, arg, "-m") or + \\ std.mem.startsWith(u8, arg, "elf_")) + \\ { + \\ // NOT CHANGE!! + \\ } else { + \\ try cmds.append(arg); + \\ } + \\ } + \\ + \\ if (build_options.triple) |triple_target| { + \\ try cmds.append("-target"); + \\ try cmds.append(triple_target); + \\ } + \\ if (build_options.cpu) |cpu| { + \\ try cmds.append(std.fmt.comptimePrint("-mcpu={s}", .{cpu})); + \\ } + \\ + \\ if (builtin.os.tag != .windows) { + \\ try cmds.append("-lunwind"); + \\ } + \\ + \\ var proc = std.process.Child.init(cmds.items, allocator); + \\ + \\ try std.io.getStdOut().writer().print("[zig cc] flags: \"", .{}); + \\ for (cmds.items) |cmd| { + \\ if (std.mem.startsWith(u8, cmd, "zig")) continue; + \\ if (std.mem.startsWith(u8, cmd, "cc")) continue; + \\ try std.io.getStdOut().writer().print("{s} ", .{cmd}); + \\ } + \\ try std.io.getStdOut().writer().print("\"\n", .{}); + \\ + \\ _ = try proc.spawnAndWait(); + \\ } +; + +// -------------------------- Build Steps -------------------------- + // a separate step to compile shaders, expects the shader compiler in ../sokol-tools-bin/ fn buildShaders(b: *Build, target: Build.ResolvedTarget) void { if (b.lazyDependency("shdc", .{})) |dep| { diff --git a/tools/zigcc.zig b/tools/zigcc.zig deleted file mode 100644 index d595dbb..0000000 --- a/tools/zigcc.zig +++ /dev/null @@ -1,68 +0,0 @@ -//! zig-cc wrapper for ldc2 -//! Copyright (c) 2023 Matheus Catarino França -//! Zlib license - -const std = @import("std"); -const builtin = @import("builtin"); - -pub fn main() !void { - var gpa = std.heap.GeneralPurposeAllocator(.{}){}; - defer _ = std.debug.assert(gpa.deinit() == .ok); // ok or leak - const allocator = gpa.allocator(); - - var args = try std.process.argsWithAllocator(allocator); - defer args.deinit(); - - _ = args.skip(); // skip arg[0] - - var cmds = std.ArrayList([]const u8).init(allocator); - defer cmds.deinit(); - - try cmds.append("zig"); - try cmds.append("cc"); - - if (builtin.os.tag != .windows) { - // not working on msvc target (nostdlib++) - try cmds.append("-lunwind"); - } - - // LDC2 not setting triple targets on host build to cc/linker, except Apple (why?) - var isNative = true; - while (args.next()) |arg| { - // MacOS M1/M2 target, replace aarch64 to arm64 - if (std.mem.eql(u8, arg, std.fmt.comptimePrint("{s}-apple-{s}", .{ if (builtin.cpu.arch.isAARCH64()) "arm64" else @tagName(builtin.cpu.arch), @tagName(builtin.os.tag) }))) { - try cmds.append("native-native"); - try cmds.append("-fapple-link-rtlib"); - } else if (std.mem.eql(u8, arg, std.fmt.comptimePrint("{s}-unknown-unknown-{s}", .{ @tagName(builtin.cpu.arch), @tagName(builtin.os.tag) }))) { - // wasm32 or wasm64 - try cmds.append(std.fmt.comptimePrint("{s}-emscripten", .{@tagName(builtin.cpu.arch)})); - } else if (std.mem.eql(u8, arg, std.fmt.comptimePrint("{s}-unknown-{s}", .{ @tagName(builtin.cpu.arch), @tagName(builtin.os.tag) }))) { - try cmds.append(std.fmt.comptimePrint("{s}-{s}", .{ @tagName(builtin.cpu.arch), @tagName(builtin.os.tag) })); - } else if (std.mem.eql(u8, arg, "-target")) { - isNative = false; - try cmds.append(arg); // get "-target" flag - } else if (std.mem.eql(u8, arg, "/NOLOGO")) { - // SKIP - } else { - try cmds.append(arg); - } - } - // Why native? See: https://github.com/kassane/sokol-d/issues/1 - if (isNative) { - try cmds.append("-target"); - if (builtin.os.tag == .windows) - try cmds.append("native-native-msvc") - else { - try cmds.append("native-native"); - } - } - - var proc = std.process.Child.init(cmds.items, allocator); - - // See all flags - // std.debug.print("debug flags: ", .{}); - // for (cmds.items) |cmd| - // std.debug.print("{s} ", .{cmd}); - - _ = try proc.spawnAndWait(); -}