zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

libc.zig (4869B) - Raw


      1 const std = @import("std");
      2 const mem = std.mem;
      3 const io = std.io;
      4 const LibCInstallation = std.zig.LibCInstallation;
      5 
      6 const usage_libc =
      7     \\Usage: zig libc
      8     \\
      9     \\    Detect the native libc installation and print the resulting
     10     \\    paths to stdout. You can save this into a file and then edit
     11     \\    the paths to create a cross compilation libc kit. Then you
     12     \\    can pass `--libc [file]` for Zig to use it.
     13     \\
     14     \\Usage: zig libc [paths_file]
     15     \\
     16     \\    Parse a libc installation text file and validate it.
     17     \\
     18     \\Options:
     19     \\  -h, --help             Print this help and exit
     20     \\  -target [name]         <arch><sub>-<os>-<abi> see the targets command
     21     \\  -includes              Print the libc include directories for the target
     22     \\
     23 ;
     24 
     25 var stdout_buffer: [4096]u8 = undefined;
     26 
     27 pub fn main() !void {
     28     var arena_instance = std.heap.ArenaAllocator.init(std.heap.page_allocator);
     29     defer arena_instance.deinit();
     30     const arena = arena_instance.allocator();
     31     const gpa = arena;
     32 
     33     const args = try std.process.argsAlloc(arena);
     34     const zig_lib_directory = args[1];
     35 
     36     var input_file: ?[]const u8 = null;
     37     var target_arch_os_abi: []const u8 = "native";
     38     var print_includes: bool = false;
     39     var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
     40     const stdout = &stdout_writer.interface;
     41     {
     42         var i: usize = 2;
     43         while (i < args.len) : (i += 1) {
     44             const arg = args[i];
     45             if (mem.startsWith(u8, arg, "-")) {
     46                 if (mem.eql(u8, arg, "-h") or mem.eql(u8, arg, "--help")) {
     47                     try stdout.writeAll(usage_libc);
     48                     try stdout.flush();
     49                     return std.process.cleanExit();
     50                 } else if (mem.eql(u8, arg, "-target")) {
     51                     if (i + 1 >= args.len) fatal("expected parameter after {s}", .{arg});
     52                     i += 1;
     53                     target_arch_os_abi = args[i];
     54                 } else if (mem.eql(u8, arg, "-includes")) {
     55                     print_includes = true;
     56                 } else {
     57                     fatal("unrecognized parameter: '{s}'", .{arg});
     58                 }
     59             } else if (input_file != null) {
     60                 fatal("unexpected extra parameter: '{s}'", .{arg});
     61             } else {
     62                 input_file = arg;
     63             }
     64         }
     65     }
     66 
     67     const target_query = std.zig.parseTargetQueryOrReportFatalError(gpa, .{
     68         .arch_os_abi = target_arch_os_abi,
     69     });
     70     const target = std.zig.resolveTargetQueryOrFatal(target_query);
     71 
     72     if (print_includes) {
     73         const libc_installation: ?*LibCInstallation = libc: {
     74             if (input_file) |libc_file| {
     75                 const libc = try arena.create(LibCInstallation);
     76                 libc.* = LibCInstallation.parse(arena, libc_file, &target) catch |err| {
     77                     fatal("unable to parse libc file at path {s}: {s}", .{ libc_file, @errorName(err) });
     78                 };
     79                 break :libc libc;
     80             } else {
     81                 break :libc null;
     82             }
     83         };
     84 
     85         const is_native_abi = target_query.isNativeAbi();
     86 
     87         const libc_dirs = std.zig.LibCDirs.detect(
     88             arena,
     89             zig_lib_directory,
     90             &target,
     91             is_native_abi,
     92             true,
     93             libc_installation,
     94         ) catch |err| {
     95             const zig_target = try target.zigTriple(arena);
     96             fatal("unable to detect libc for target {s}: {s}", .{ zig_target, @errorName(err) });
     97         };
     98 
     99         if (libc_dirs.libc_include_dir_list.len == 0) {
    100             const zig_target = try target.zigTriple(arena);
    101             fatal("no include dirs detected for target {s}", .{zig_target});
    102         }
    103 
    104         for (libc_dirs.libc_include_dir_list) |include_dir| {
    105             try stdout.writeAll(include_dir);
    106             try stdout.writeByte('\n');
    107         }
    108         try stdout.flush();
    109         return std.process.cleanExit();
    110     }
    111 
    112     if (input_file) |libc_file| {
    113         var libc = LibCInstallation.parse(gpa, libc_file, &target) catch |err| {
    114             fatal("unable to parse libc file at path {s}: {s}", .{ libc_file, @errorName(err) });
    115         };
    116         defer libc.deinit(gpa);
    117     } else {
    118         if (!target_query.canDetectLibC()) {
    119             fatal("unable to detect libc for non-native target", .{});
    120         }
    121         var libc = LibCInstallation.findNative(.{
    122             .allocator = gpa,
    123             .verbose = true,
    124             .target = &target,
    125         }) catch |err| {
    126             fatal("unable to detect native libc: {s}", .{@errorName(err)});
    127         };
    128         defer libc.deinit(gpa);
    129 
    130         try libc.render(stdout);
    131         try stdout.flush();
    132     }
    133 }
    134 
    135 fn fatal(comptime format: []const u8, args: anytype) noreturn {
    136     std.log.err(format, args);
    137     std.process.exit(1);
    138 }