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.

Directories

zig.Directories
pub const Directories = struct

File

lib/std/zig.zig:1272

Code

pub const Directories = struct {
    /// The string returned by `introspect.getResolvedCwd`. This is typically an absolute path,
    /// but on WASI is the empty string "" instead, because WASI does not have absolute paths.
    cwd: []const u8,
    /// The Zig 'lib' directory.
    /// `zig_lib.path` is resolved (`resolvePath`) or `null` for cwd.
    /// Guaranteed to be a different path from `global_cache` and `local_cache`.
    zig_lib: Cache.Directory,
    /// The global Zig cache directory.
    /// `global_cache.path` is resolved (`resolvePath`) or `null` for cwd.
    global_cache: Cache.Directory,
    /// The local Zig cache directory.
    /// `local_cache.path` is resolved (`resolvePath`) or `null` for cwd.
    /// This may be the same as `global_cache`.
    local_cache: Cache.Directory,

    pub fn deinit(dirs: *Directories, io: Io) void {
        // The local and global caches could be the same.
        const close_local = dirs.local_cache.handle.handle != dirs.global_cache.handle.handle;

        dirs.global_cache.handle.close(io);
        if (close_local) dirs.local_cache.handle.close(io);
        dirs.zig_lib.handle.close(io);
    }

    /// Returns a `Directories` where `local_cache` is replaced with `global_cache`, intended for
    /// use by sub-compilations (e.g. compiler_rt). Do not `deinit` the returned `Directories`; it
    /// shares handles with `dirs`.
    pub fn withoutLocalCache(dirs: Directories) Directories {
        return .{
            .cwd = dirs.cwd,
            .zig_lib = dirs.zig_lib,
            .global_cache = dirs.global_cache,
            .local_cache = dirs.global_cache,
        };
    }

    const LocalCacheStrategy = union(enum) {
        override: []const u8,
        search,
        global,
    };

    /// Uses `std.process.fatal` on error conditions.
    pub fn init(
        arena: Allocator,
        io: Io,
        override_zig_lib: ?[]const u8,
        override_global_cache: ?[]const u8,
        local_cache_strat: LocalCacheStrategy,
        preopens: std.process.Preopens,
        self_exe_path: switch (builtin.target.os.tag) {
            .wasi => void,
            else => []const u8,
        },
        environ_map: *const std.process.Environ.Map,
        cwd: []const u8,
    ) Directories {
        const wasi = builtin.target.os.tag == .wasi;

        const zig_lib: Cache.Directory = d: {
            if (override_zig_lib) |path| break :d openUnresolved(arena, io, cwd, path, .@"zig lib");
            if (wasi) break :d getPreopen(preopens, "/lib");
            break :d findZigLibDirFromSelfExe(arena, io, cwd, self_exe_path) catch |err| {
                fatal("unable to find zig installation directory from executable path {q}: {t}", .{ self_exe_path, err });
            };
        };

        const global_cache: Cache.Directory = d: {
            if (override_global_cache) |path| break :d openUnresolved(arena, io, cwd, path, .@"global cache");
            if (wasi) break :d getPreopen(preopens, "/cache");
            const path = resolveGlobalCacheDir(arena, environ_map) catch |err| {
                fatal("unable to resolve zig cache directory: {t}", .{err});
            };
            break :d openUnresolved(arena, io, cwd, path, .@"global cache");
        };

        const local_cache = getLocalCacheDirectory(arena, io, cwd, global_cache, local_cache_strat);

        if (mem.eql(u8, zig_lib.path orelse "", global_cache.path orelse "")) {
            fatal("zig lib directory '{f}' cannot be equal to global cache directory '{f}'", .{ zig_lib, global_cache });
        }
        if (mem.eql(u8, zig_lib.path orelse "", local_cache.path orelse "")) {
            fatal("zig lib directory '{f}' cannot be equal to local cache directory '{f}'", .{ zig_lib, local_cache });
        }

        return .{
            .cwd = cwd,
            .zig_lib = zig_lib,
            .global_cache = global_cache,
            .local_cache = local_cache,
        };
    }

    fn getLocalCacheDirectory(
        arena: Allocator,
        io: Io,
        cwd: []const u8,
        global_cache: Cache.Directory,
        local_cache_strat: LocalCacheStrategy,
    ) Cache.Directory {
        return switch (local_cache_strat) {
            .override => |path| openUnresolved(arena, io, cwd, path, .@"local cache"),
            .search => d: {
                const maybe_path = resolveSuitableLocalCacheDir(arena, io, cwd) catch |err|
                    fatal("unable to resolve zig cache directory: {t}", .{err});
                const path = maybe_path orelse break :d global_cache;
                break :d openUnresolved(arena, io, cwd, path, .@"local cache");
            },
            .global => global_cache,
        };
    }

    fn getPreopen(preopens: std.process.Preopens, name: []const u8) Cache.Directory {
        return .{
            .path = if (mem.eql(u8, name, ".")) null else name,
            .handle = switch (preopens.get(name) orelse fatal("preopen not found: {q}", .{name})) {
                .file => fatal("preopen {q} is not a directory", .{name}),
                .dir => |d| d,
            },
        };
    }
    pub fn openUnresolved(
        arena: Allocator,
        io: Io,
        cwd: []const u8,
        unresolved_path: []const u8,
        thing: enum { @"zig lib", @"global cache", @"local cache" },
    ) Cache.Directory {
        const path = resolvePath(arena, cwd, &.{unresolved_path}) catch |err| {
            fatal("unable to resolve {t} directory: {t}", .{ thing, err });
        };
        const nonempty_path = if (path.len == 0) "." else path;
        const handle_or_err = switch (thing) {
            .@"zig lib" => Dir.cwd().openDir(io, nonempty_path, .{}),
            .@"global cache", .@"local cache" => Dir.cwd().createDirPathOpen(io, nonempty_path, .{}),
        };
        return .{
            .path = if (path.len == 0) null else path,
            .handle = handle_or_err catch |err| {
                const extra_str: []const u8 = e: {
                    if (thing == .@"global cache") switch (err) {
                        error.AccessDenied, error.ReadOnlyFileSystem => break :e "\n" ++
                            "If this location is not writable then consider specifying an alternative with " ++
                            "the ZIG_GLOBAL_CACHE_DIR environment variable or the --global-cache-dir option.",
                        else => {},
                    };
                    break :e "";
                };
                fatal("unable to open {t} directory {q}: {t}{s}", .{ thing, nonempty_path, err, extra_str });
            },
        };
    }
}