From 2171511c91d5bdb98551297fcd1715aad7b42113 Mon Sep 17 00:00:00 2001 From: David Gonzalez Martin Date: Mon, 29 Jan 2024 09:11:59 +0100 Subject: [PATCH] better handle program arguments with commands --- bootstrap/Compilation.zig | 72 +++++++++++++++++++-------------------- bootstrap/main.zig | 62 ++++++++++++++++++++++++++++++--- build.zig | 10 ++++-- build/test_runner.zig | 3 +- 4 files changed, 102 insertions(+), 45 deletions(-) diff --git a/bootstrap/Compilation.zig b/bootstrap/Compilation.zig index 131167b..ee59a6f 100644 --- a/bootstrap/Compilation.zig +++ b/bootstrap/Compilation.zig @@ -32,9 +32,25 @@ fn reportUnterminatedArgumentError(string: []const u8) noreturn { std.debug.panic("Unterminated argument: {s}", .{string}); } -fn parseArguments(context: *const Context) !Descriptor { - const allocator = context.allocator; - const arguments = (try std.process.argsAlloc(allocator))[1..]; +pub fn foo(context: *const Context) !Descriptor { + _ = context; // autofix +} + +pub fn buildExecutable(allocator: Allocator, arguments: [][:0]u8) !void { + const context: *Context = try allocator.create(Context); + + const self_exe_path = try std.fs.selfExePathAlloc(allocator); + const self_exe_dir_path = std.fs.path.dirname(self_exe_path).?; + context.* = .{ + .allocator = allocator, + .cwd_absolute_path = try realpathAlloc(allocator, "."), + .executable_absolute_path = self_exe_path, + .directory_absolute_path = self_exe_dir_path, + .build_directory = try std.fs.cwd().makeOpenPath("nat", .{}), + }; + + try context.build_directory.makePath(cache_dir_name); + try context.build_directory.makePath(installation_dir_name); var maybe_executable_path: ?[]const u8 = null; var maybe_main_package_path: ?[]const u8 = null; @@ -196,43 +212,25 @@ fn parseArguments(context: *const Context) !Descriptor { break :blk result; }; - return .{ - .main_package_path = main_package_path, - .executable_path = executable_path, - .target = target, - .is_build = is_build, - .only_parse = only_parse, - .link_libc = switch (target.os.tag) { - .linux => link_libc, - .macos => true, - .windows => link_libc, - else => unreachable, - }, - .generate_debug_information = generate_debug_information, - .name = executable_name, - }; -} - -pub fn init(allocator: Allocator) !void { - const context: *Context = try allocator.create(Context); - - const self_exe_path = try std.fs.selfExePathAlloc(allocator); - const self_exe_dir_path = std.fs.path.dirname(self_exe_path).?; - context.* = .{ - .allocator = allocator, - .cwd_absolute_path = try realpathAlloc(allocator, "."), - .executable_absolute_path = self_exe_path, - .directory_absolute_path = self_exe_dir_path, - .build_directory = try std.fs.cwd().makeOpenPath("nat", .{}), - }; - - try context.build_directory.makePath(cache_dir_name); - try context.build_directory.makePath(installation_dir_name); - const unit = try context.allocator.create(Unit); unit.* = .{ - .descriptor = try parseArguments(context), + .descriptor = .{ + .main_package_path = main_package_path, + .executable_path = executable_path, + .target = target, + .is_build = is_build, + .only_parse = only_parse, + .link_libc = switch (target.os.tag) { + .linux => link_libc, + .macos => true, + .windows => link_libc, + else => unreachable, + }, + .generate_debug_information = generate_debug_information, + .name = executable_name, + }, }; + try unit.compile(context); } diff --git a/bootstrap/main.zig b/bootstrap/main.zig index bbbd932..af90707 100644 --- a/bootstrap/main.zig +++ b/bootstrap/main.zig @@ -1,14 +1,66 @@ const std = @import("std"); const Allocator = std.mem.Allocator; +const equal = std.mem.eql; const Compilation = @import("Compilation.zig"); pub const panic = Compilation.panic; -pub fn main() !void { - var arena_allocator = std.heap.ArenaAllocator.init(std.heap.page_allocator); - try Compilation.init(arena_allocator.allocator()); +const env_detecting_libc_paths = "NATIVITY_IS_DETECTING_LIBC_PATHS"; + +fn todo() noreturn { + @setCold(true); + @panic("TODO"); } -test { - _ = Compilation; +pub fn main() !void { + var arena_allocator = std.heap.ArenaAllocator.init(std.heap.page_allocator); + const allocator = arena_allocator.allocator(); + const arguments = try std.process.argsAlloc(allocator); + + if (arguments.len <= 1) { + return error.InvalidInput; + } + + if (std.process.can_execv and std.os.getenvZ(env_detecting_libc_paths) != null) { + todo(); + } + + const command = arguments[1]; + const command_arguments = arguments[2..]; + + if (equal(u8, command, "build")) { + todo(); + } else if (equal(u8, command, "clang") or equal(u8, command, "-cc1") or equal(u8, command, "-cc1as")) { + const exit_code = try clangMain(allocator, arguments); + std.process.exit(exit_code); + } else if (equal(u8, command, "cc")) { + // TODO: transform our arguments to Clang and invoke it + todo(); + } else if (equal(u8, command, "c++")) { + // TODO: transform our arguments to Clang and invoke it + todo(); + } else if (equal(u8, command, "exe")) { + try Compilation.buildExecutable(allocator, command_arguments); + } else if (equal(u8, command, "lib")) { + todo(); + } else if (equal(u8, command, "obj")) { + todo(); + } else { + todo(); + } +} + +fn argsCopyZ(alloc: Allocator, args: []const []const u8) ![:null]?[*:0]u8 { + var argv = try alloc.allocSentinel(?[*:0]u8, args.len, null); + for (args, 0..) |arg, i| { + argv[i] = try alloc.dupeZ(u8, arg); // TODO If there was an argsAllocZ we could avoid this allocation. + } + return argv; +} + +extern "c" fn NativityClangMain(argc: c_int, argv: [*:null]?[*:0]u8) c_int; +fn clangMain(allocator: Allocator, arguments: []const []const u8) !u8 { + const argv = try argsCopyZ(allocator, arguments); + const exit_code = NativityClangMain(@as(c_int, @intCast(arguments.len)), argv.ptr); + return @as(u8, @bitCast(@as(i8, @truncate(exit_code)))); } diff --git a/build.zig b/build.zig index 6c059e6..c4ba414 100644 --- a/build.zig +++ b/build.zig @@ -98,8 +98,14 @@ pub fn build(b: *std.Build) !void { const llvm_include_dir = try std.mem.concat(b.allocator, u8, &.{ llvm_path, "/include" }); const llvm_lib_dir = try std.mem.concat(b.allocator, u8, &.{ llvm_path, "/lib" }); compiler.addIncludePath(std.Build.LazyPath.relative(llvm_include_dir)); - compiler.addCSourceFile(.{ - .file = std.Build.LazyPath.relative("bootstrap/backend/llvm.cpp"), + const cpp_files = .{ + "bootstrap/backend/llvm.cpp", + "bootstrap/frontend/clang/main.cpp", + "bootstrap/frontend/clang/cc1.cpp", + "bootstrap/frontend/clang/cc1as.cpp", + }; + compiler.addCSourceFiles(.{ + .files = &cpp_files, .flags = &.{"-g"}, }); diff --git a/build/test_runner.zig b/build/test_runner.zig index 06ba0d3..94ff32c 100644 --- a/build/test_runner.zig +++ b/build/test_runner.zig @@ -39,7 +39,8 @@ pub fn main() !void { const source_file_path = try std.mem.concat(allocator, u8, &.{standalone_test_dir_path, "/", standalone_test_name, "/main.nat"}); const process_run = try std.ChildProcess.run(.{ .allocator = allocator, - .argv = &.{"zig-out/bin/nat", "-main_source_file", source_file_path}, + // TODO: delete -main_source_file? + .argv = &.{"zig-out/bin/nat", "exe", "-main_source_file", source_file_path}, }); const result: TestError!bool = switch (process_run.term) { .Exited => |exit_code| if (exit_code == 0) true else error.abnormal_exit_code,