124 lines
4.4 KiB
Zig
124 lines
4.4 KiB
Zig
|
|
/// Custom ZLS launcher.
|
||
|
|
///
|
||
|
|
/// Sets up paths to ZLS dependencies with Bazel runfiles.
|
||
|
|
///
|
||
|
|
/// This file is used as a template by `zls_write_runner_zig_src.bzl`.
|
||
|
|
const std = @import("std");
|
||
|
|
const runfiles = @import("runfiles");
|
||
|
|
const bazel_builtin = @import("bazel_builtin");
|
||
|
|
|
||
|
|
fn getRandomFilename(buf: *[std.fs.max_name_bytes]u8, extension: []const u8) ![]const u8 {
|
||
|
|
const random_bytes_count = 12;
|
||
|
|
const sub_path_len = comptime std.fs.base64_encoder.calcSize(random_bytes_count);
|
||
|
|
|
||
|
|
var random_bytes: [random_bytes_count]u8 = undefined;
|
||
|
|
std.crypto.random.bytes(&random_bytes);
|
||
|
|
var random_name: [sub_path_len]u8 = undefined;
|
||
|
|
_ = std.fs.base64_encoder.encode(&random_name, &random_bytes);
|
||
|
|
|
||
|
|
const fmt_template = "/tmp/{s}{s}";
|
||
|
|
const fmt_args = .{
|
||
|
|
@as([]const u8, &random_name),
|
||
|
|
extension,
|
||
|
|
};
|
||
|
|
return std.fmt.bufPrint(buf, fmt_template, fmt_args) catch @panic("OOM");
|
||
|
|
}
|
||
|
|
|
||
|
|
const Config = struct {
|
||
|
|
/// Override the Zig library path. Will be automatically resolved using the 'zig_exe_path'.
|
||
|
|
zig_lib_path: ?[]const u8 = null,
|
||
|
|
|
||
|
|
/// Specify the path to the Zig executable (not the directory). If unset, zig is looked up in `PATH`. e.g. `/path/to/zig-templeos-armless-1.0.0/zig`.
|
||
|
|
zig_exe_path: ?[]const u8 = null,
|
||
|
|
|
||
|
|
/// Specify a custom build runner to resolve build system information.
|
||
|
|
build_runner_path: ?[]const u8 = null,
|
||
|
|
|
||
|
|
/// Path to a directory that will be used as zig's cache. Will default to `${KnownFolders.Cache}/zls`.
|
||
|
|
global_cache_path: ?[]const u8 = null,
|
||
|
|
};
|
||
|
|
|
||
|
|
pub fn main() !void {
|
||
|
|
const gpa = std.heap.page_allocator;
|
||
|
|
var arena = std.heap.ArenaAllocator.init(gpa);
|
||
|
|
const allocator = arena.allocator();
|
||
|
|
|
||
|
|
var r_ = try runfiles.Runfiles.create(.{ .allocator = allocator }) orelse
|
||
|
|
return error.RunfilesNotFound;
|
||
|
|
defer r_.deinit(allocator);
|
||
|
|
|
||
|
|
const r = r_.withSourceRepo(bazel_builtin.current_repository);
|
||
|
|
|
||
|
|
const zls_bin_rpath = "@@__ZLS_BIN_RPATH__@@";
|
||
|
|
var zls_bin_path_buf: [std.fs.max_path_bytes]u8 = undefined;
|
||
|
|
const zls_bin_path = try r.rlocation(zls_bin_rpath, &zls_bin_path_buf) orelse
|
||
|
|
return error.RLocationNotFound;
|
||
|
|
|
||
|
|
const zig_exe_rpath = "@@__ZIG_EXE_RPATH__@@";
|
||
|
|
var zig_exe_path_buf: [std.fs.max_path_bytes]u8 = undefined;
|
||
|
|
const zig_exe_path = blk2: {
|
||
|
|
if (zig_exe_rpath[0] == '/') {
|
||
|
|
break :blk2 zig_exe_rpath;
|
||
|
|
} else {
|
||
|
|
break :blk2 try r.rlocation(zig_exe_rpath, &zig_exe_path_buf) orelse
|
||
|
|
return error.RLocationNotFound;
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
const zig_lib_path = "@@__ZIG_LIB_PATH__@@";
|
||
|
|
const zig_lib_computed_path = blk: {
|
||
|
|
if (zig_lib_path[0] == '/') {
|
||
|
|
break :blk zig_lib_path;
|
||
|
|
} else {
|
||
|
|
break :blk null;
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
const zls_build_runner_rpath = "@@__ZLS_BUILD_RUNNER_RPATH__@@";
|
||
|
|
var zls_build_runner_path_buf: [std.fs.max_path_bytes]u8 = undefined;
|
||
|
|
const zls_build_runner_path = try r.rlocation(zls_build_runner_rpath, &zls_build_runner_path_buf) orelse
|
||
|
|
return error.RLocationNotFound;
|
||
|
|
|
||
|
|
const global_cache_path = "@@__GLOBAL_CACHE_PATH__@@";
|
||
|
|
|
||
|
|
const config: Config = .{
|
||
|
|
.zig_exe_path = zig_exe_path,
|
||
|
|
.zig_lib_path = zig_lib_computed_path,
|
||
|
|
.build_runner_path = zls_build_runner_path,
|
||
|
|
.global_cache_path = global_cache_path,
|
||
|
|
};
|
||
|
|
|
||
|
|
var buf: [std.fs.max_name_bytes]u8 = undefined;
|
||
|
|
const tmp_file_path = try getRandomFilename(&buf, ".json");
|
||
|
|
|
||
|
|
{
|
||
|
|
var tmp_file = try std.fs.createFileAbsolute(tmp_file_path, .{});
|
||
|
|
defer tmp_file.close();
|
||
|
|
|
||
|
|
var out_buf: [4096]u8 = undefined;
|
||
|
|
var tmp_file_writer = tmp_file.writer(&out_buf);
|
||
|
|
|
||
|
|
const formatter = std.json.fmt(config, .{ .whitespace = .indent_2 });
|
||
|
|
|
||
|
|
try tmp_file_writer.interface.print("{f}", .{formatter});
|
||
|
|
try tmp_file_writer.interface.flush();
|
||
|
|
}
|
||
|
|
|
||
|
|
const args = std.process.argsAlloc(allocator) catch return error.ArgsAllocFailed;
|
||
|
|
defer std.process.argsFree(allocator, args);
|
||
|
|
|
||
|
|
const exec_args_len = args.len - 1 + 3; // Skip args[0] and add "zls" + --config-path + tmp_file_path
|
||
|
|
var exec_args = try allocator.alloc([]const u8, exec_args_len);
|
||
|
|
|
||
|
|
exec_args[0] = zls_bin_path; // "zls"
|
||
|
|
|
||
|
|
// ${@}
|
||
|
|
for (args[1..], 0..) |arg, i| {
|
||
|
|
exec_args[1 + i] = arg;
|
||
|
|
}
|
||
|
|
exec_args[exec_args.len - 2] = "--config-path";
|
||
|
|
exec_args[exec_args.len - 1] = tmp_file_path;
|
||
|
|
|
||
|
|
return std.process.execv(arena.allocator(), exec_args);
|
||
|
|
}
|