Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

ccPrintFileName

caller owns returned memory

LibCInstallation.ccPrintFileName
fn ccPrintFileName(gpa: Allocator, io: Io, args: CCPrintFileNameOptions) ![]u8

File

lib/std/zig/LibCInstallation.zig:569

Code

fn ccPrintFileName(gpa: Allocator, io: Io, args: CCPrintFileNameOptions) ![]u8 {
    // Detect infinite loops.
    var environ_map = try args.environ_map.clone(gpa);
    defer environ_map.deinit();
    const skip_cc_env_var = if (environ_map.get(inf_loop_env_key)) |phase| blk: {
        if (std.mem.eql(u8, phase, "1")) {
            try environ_map.put(inf_loop_env_key, "2");
            break :blk true;
        } else {
            return error.ZigIsTheCCompiler;
        }
    } else blk: {
        try environ_map.put(inf_loop_env_key, "1");
        break :blk false;
    };

    var argv = std.array_list.Managed([]const u8).init(gpa);
    defer argv.deinit();

    const arg1 = try std.fmt.allocPrint(gpa, "-print-file-name={s}", .{args.search_basename});
    defer gpa.free(arg1);

    try appendCcExe(&argv, skip_cc_env_var, &environ_map);
    try argv.append(arg1);

    const run_res = std.process.run(gpa, io, .{
        .stdout_limit = .limited(1024 * 1024),
        .stderr_limit = .limited(1024 * 1024),
        .argv = argv.items,
        .environ_map = &environ_map,
        // Some C compilers, such as Clang, are known to rely on argv[0] to find the path
        // to their own executable, without even bothering to resolve PATH. This results in the message:
        // error: unable to execute command: Executable "" doesn't exist!
        // So we use the expandArg0 variant of ChildProcess to give them a helping hand.
        .expand_arg0 = .expand,
    }) catch |err| switch (err) {
        error.OutOfMemory => |e| return e,
        else => return error.UnableToSpawnCCompiler,
    };
    defer {
        gpa.free(run_res.stdout);
        gpa.free(run_res.stderr);
    }
    switch (run_res.term) {
        .exited => |code| if (code != 0) {
            printVerboseInvocation(argv.items, args.search_basename, args.verbose, run_res.stderr);
            return error.CCompilerExitCode;
        },
        else => {
            printVerboseInvocation(argv.items, args.search_basename, args.verbose, run_res.stderr);
            return error.CCompilerCrashed;
        },
    }

    var it = std.mem.tokenizeAny(u8, run_res.stdout, "\n\r");
    const line = it.next() orelse return error.LibCRuntimeNotFound;
    // When this command fails, it returns exit code 0 and duplicates the input file name.
    // So we detect failure by checking if the output matches exactly the input.
    if (std.mem.eql(u8, line, args.search_basename)) return error.LibCRuntimeNotFound;
    switch (args.want_dirname) {
        .full_path => return gpa.dupe(u8, line),
        .only_dir => {
            const dirname = fs.path.dirname(line) orelse return error.LibCRuntimeNotFound;
            return gpa.dupe(u8, dirname);
        },
    }
}