5 Star 26 Fork 0

Gitee 极速下载/neovim

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
此仓库是为了提升国内下载速度的镜像仓库,每日同步一次。 原始仓库: https://github.com/neovim/neovim
克隆/下载
build.zig 18.95 KB
一键复制 编辑 原始数据 按行查看 历史
const std = @import("std");
const LazyPath = std.Build.LazyPath;
const build_lua = @import("src/build_lua.zig");
const gen = @import("src/gen/gen_steps.zig");
const runtime = @import("runtime/gen_runtime.zig");
const tests = @import("test/run_tests.zig");
const version = struct {
const major = 0;
const minor = 12;
const patch = 0;
const prerelease = "-dev";
const api_level = 14;
const api_level_compat = 0;
const api_prerelease = true;
};
// TODO(bfredl): this is for an upstream issue
pub fn lazyArtifact(d: *std.Build.Dependency, name: []const u8) ?*std.Build.Step.Compile {
var found: ?*std.Build.Step.Compile = null;
for (d.builder.install_tls.step.dependencies.items) |dep_step| {
const inst = dep_step.cast(std.Build.Step.InstallArtifact) orelse continue;
if (std.mem.eql(u8, inst.artifact.name, name)) {
if (found != null) std.debug.panic("artifact name '{s}' is ambiguous", .{name});
found = inst.artifact;
}
}
return found;
}
pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const t = target.result;
const os_tag = t.os.tag;
const is_windows = (os_tag == .windows);
const is_linux = (os_tag == .linux);
const is_darwin = os_tag.isDarwin();
const modern_unix = is_darwin or os_tag.isBSD() or is_linux;
const cross_compiling = b.option(bool, "cross", "cross compile") orelse false;
// TODO(bfredl): option to set nlua0 target explicitly when cross compiling?
const target_host = if (cross_compiling) b.graph.host else target;
const optimize_host = .ReleaseSafe;
// puc lua 5.1 is not ReleaseSafe "safe"
const optimize_lua = if (optimize == .Debug or optimize == .ReleaseSafe) .ReleaseSmall else optimize;
const arch = t.cpu.arch;
const default_luajit = (is_linux and arch == .x86_64) or (is_darwin and arch == .aarch64);
const use_luajit = b.option(bool, "luajit", "use luajit") orelse default_luajit;
const host_use_luajit = if (cross_compiling) false else use_luajit;
const E = enum { luajit, lua51 };
const ziglua = b.dependency("lua_wrapper", .{
.target = target,
.optimize = optimize_lua,
.lang = if (use_luajit) E.luajit else E.lua51,
.shared = false,
});
const ziglua_host = if (cross_compiling) b.dependency("lua_wrapper", .{
.target = target_host,
.optimize = optimize_lua,
.lang = if (host_use_luajit) E.luajit else E.lua51,
.shared = false,
}) else ziglua;
const lpeg = b.dependency("lpeg", .{});
const iconv_apple = if (cross_compiling and is_darwin) b.lazyDependency("iconv_apple", .{ .target = target, .optimize = optimize }) else null;
// this is currently not necessary, as ziglua currently doesn't use lazy dependencies
// to circumvent ziglua.artifact() failing in a bad way.
// const lua = lazyArtifact(ziglua, "lua") orelse return;
const lua = ziglua.artifact("lua");
const libuv_dep = b.dependency("libuv", .{ .target = target, .optimize = optimize });
const libuv = libuv_dep.artifact("uv");
const libluv = try build_lua.build_libluv(b, target, optimize, lua, libuv);
const utf8proc = b.dependency("utf8proc", .{ .target = target, .optimize = optimize });
const unibilium = b.dependency("unibilium", .{ .target = target, .optimize = optimize });
// TODO(bfredl): fix upstream bugs with UBSAN
const treesitter = b.dependency("treesitter", .{ .target = target, .optimize = .ReleaseFast });
const nlua0 = build_lua.build_nlua0(b, target_host, optimize_host, host_use_luajit, ziglua_host, lpeg);
// usual caveat emptor: might need to force a rebuild if the only change is
// addition of new .c files, as those are not seen by any hash
const subdirs = [_][]const u8{
"", // src/nvim itself
"os/",
"api/",
"api/private/",
"msgpack_rpc/",
"tui/",
"tui/termkey/",
"event/",
"eval/",
"lib/",
"lua/",
"viml/",
"viml/parser/",
"vterm/",
};
// source names _relative_ src/nvim/, not including other src/ subdircs
var nvim_sources = try std.ArrayList(gen.SourceItem).initCapacity(b.allocator, 100);
var nvim_headers = try std.ArrayList([]u8).initCapacity(b.allocator, 100);
// both source headers and the {module}.h.generated.h files
var api_headers = try std.ArrayList(std.Build.LazyPath).initCapacity(b.allocator, 10);
// TODO(bfredl): these should just become subdirs..
const windows_only = [_][]const u8{ "pty_proc_win.c", "pty_proc_win.h", "pty_conpty_win.c", "pty_conpty_win.h", "os_win_console.c", "win_defs.h" };
const unix_only = [_][]const u8{ "unix_defs.h", "pty_proc_unix.c", "pty_proc_unix.h" };
const exclude_list = if (is_windows) &unix_only else &windows_only;
const src_dir = b.build_root.handle;
for (subdirs) |s| {
var dir = try src_dir.openDir(b.fmt("src/nvim/{s}", .{s}), .{ .iterate = true });
defer dir.close();
var it = dir.iterateAssumeFirstIteration();
const api_export = std.mem.eql(u8, s, "api/");
const os_check = std.mem.eql(u8, s, "os/");
entries: while (try it.next()) |entry| {
if (entry.name.len < 3) continue;
if (entry.name[0] < 'a' or entry.name[0] > 'z') continue;
if (os_check) {
for (exclude_list) |name| {
if (std.mem.eql(u8, name, entry.name)) {
continue :entries;
}
}
}
if (std.mem.eql(u8, ".c", entry.name[entry.name.len - 2 ..])) {
try nvim_sources.append(.{ .name = b.fmt("{s}{s}", .{ s, entry.name }), .api_export = api_export });
}
if (std.mem.eql(u8, ".h", entry.name[entry.name.len - 2 ..])) {
try nvim_headers.append(b.fmt("{s}{s}", .{ s, entry.name }));
if (api_export and !std.mem.eql(u8, "ui_events.in.h", entry.name)) {
try api_headers.append(b.path(b.fmt("src/nvim/{s}{s}", .{ s, entry.name })));
}
}
}
}
const support_unittests = use_luajit;
const gen_config = b.addWriteFiles();
const version_lua = gen_config.add("nvim_version.lua", lua_version_info(b));
var config_str = b.fmt("zig build -Doptimize={s}", .{@tagName(optimize)});
if (cross_compiling) {
config_str = b.fmt("{s} -Dcross -Dtarget={s} (host: {s})", .{ config_str, try t.linuxTriple(b.allocator), try b.graph.host.result.linuxTriple(b.allocator) });
}
const versiondef_step = b.addConfigHeader(.{ .style = .{ .cmake = b.path("cmake.config/versiondef.h.in") } }, .{
.NVIM_VERSION_MAJOR = version.major,
.NVIM_VERSION_MINOR = version.minor,
.NVIM_VERSION_PATCH = version.patch,
.NVIM_VERSION_PRERELEASE = version.prerelease,
.NVIM_VERSION_MEDIUM = "",
.VERSION_STRING = "TODO", // TODO(bfredl): not sure what to put here. summary already in "config_str"
.CONFIG = config_str,
});
_ = gen_config.addCopyFile(versiondef_step.getOutput(), "auto/versiondef.h"); // run_preprocessor() workaronnd
const ptrwidth = t.ptrBitWidth() / 8;
const sysconfig_step = b.addConfigHeader(.{ .style = .{ .cmake = b.path("cmake.config/config.h.in") } }, .{
.SIZEOF_INT = t.cTypeByteSize(.int),
.SIZEOF_INTMAX_T = t.cTypeByteSize(.longlong), // TODO
.SIZEOF_LONG = t.cTypeByteSize(.long),
.SIZEOF_SIZE_T = ptrwidth,
.SIZEOF_VOID_PTR = ptrwidth,
.PROJECT_NAME = "nvim",
.HAVE__NSGETENVIRON = is_darwin,
.HAVE_FD_CLOEXEC = modern_unix,
.HAVE_FSEEKO = modern_unix,
.HAVE_LANGINFO_H = modern_unix,
.HAVE_NL_LANGINFO_CODESET = modern_unix,
.HAVE_NL_MSG_CAT_CNTR = t.isGnuLibC(),
.HAVE_PWD_FUNCS = modern_unix,
.HAVE_READLINK = modern_unix,
.HAVE_STRNLEN = modern_unix,
.HAVE_STRCASECMP = modern_unix,
.HAVE_STRINGS_H = modern_unix,
.HAVE_STRNCASECMP = modern_unix,
.HAVE_STRPTIME = modern_unix,
.HAVE_XATTR = is_linux,
.HAVE_SYS_SDT_H = false,
.HAVE_SYS_UTSNAME_H = modern_unix,
.HAVE_SYS_WAIT_H = false, // unused
.HAVE_TERMIOS_H = modern_unix,
.HAVE_WORKING_LIBINTL = t.isGnuLibC(),
.UNIX = modern_unix,
.CASE_INSENSITIVE_FILENAME = is_darwin or is_windows,
.HAVE_SYS_UIO_H = modern_unix,
.HAVE_READV = modern_unix,
.HAVE_DIRFD_AND_FLOCK = modern_unix,
.HAVE_FORKPTY = modern_unix and !is_darwin, // also on Darwin but we lack the headers :(
.HAVE_BE64TOH = modern_unix and !is_darwin,
.ORDER_BIG_ENDIAN = t.cpu.arch.endian() == .big,
.ENDIAN_INCLUDE_FILE = "endian.h",
.HAVE_EXECINFO_BACKTRACE = modern_unix and !t.isMuslLibC(),
.HAVE_BUILTIN_ADD_OVERFLOW = true,
.HAVE_WIMPLICIT_FALLTHROUGH_FLAG = true,
.HAVE_BITSCANFORWARD64 = null,
.VTERM_TEST_FILE = "test/vterm_test_output", // TODO(bfredl): revisit when porting libvterm tests
});
_ = gen_config.addCopyFile(sysconfig_step.getOutput(), "auto/config.h"); // run_preprocessor() workaronnd
_ = gen_config.add("auto/pathdef.h", b.fmt(
\\char *default_vim_dir = "/usr/local/share/nvim";
\\char *default_vimruntime_dir = "";
\\char *default_lib_dir = "/usr/local/lib/nvim";
, .{}));
// TODO(bfredl): include git version when available
const medium = b.fmt("v{}.{}.{}{s}+zig", .{ version.major, version.minor, version.patch, version.prerelease });
const versiondef_git = gen_config.add("auto/versiondef_git.h", b.fmt(
\\#define NVIM_VERSION_MEDIUM "{s}"
\\#define NVIM_VERSION_BUILD "???"
\\
, .{medium}));
// TODO(zig): using getEmittedIncludeTree() is ugly af. we want run_preprocessor()
// to use the std.build.Module include_path thing
const include_path = [_]LazyPath{
b.path("src/"),
gen_config.getDirectory(),
lua.getEmittedIncludeTree(),
libuv.getEmittedIncludeTree(),
libluv.getEmittedIncludeTree(),
utf8proc.artifact("utf8proc").getEmittedIncludeTree(),
unibilium.artifact("unibilium").getEmittedIncludeTree(),
treesitter.artifact("tree-sitter").getEmittedIncludeTree(),
};
const gen_headers, const funcs_data = try gen.nvim_gen_sources(b, nlua0, &nvim_sources, &nvim_headers, &api_headers, &include_path, target, versiondef_git, version_lua);
const test_config_step = b.addWriteFiles();
_ = test_config_step.add("test/cmakeconfig/paths.lua", try test_config(b));
const test_gen_step = b.step("gen_headers", "debug: output generated headers");
const config_install = b.addInstallDirectory(.{ .source_dir = gen_config.getDirectory(), .install_dir = .prefix, .install_subdir = "config/" });
test_gen_step.dependOn(&config_install.step);
test_gen_step.dependOn(&b.addInstallDirectory(.{ .source_dir = gen_headers.getDirectory(), .install_dir = .prefix, .install_subdir = "headers/" }).step);
const nvim_exe = b.addExecutable(.{
.name = "nvim",
.target = target,
.optimize = optimize,
});
nvim_exe.rdynamic = true; // -E
nvim_exe.linkLibrary(lua);
nvim_exe.linkLibrary(libuv);
nvim_exe.linkLibrary(libluv);
if (iconv_apple) |iconv| {
nvim_exe.linkLibrary(iconv.artifact("iconv"));
}
nvim_exe.linkLibrary(utf8proc.artifact("utf8proc"));
nvim_exe.linkLibrary(unibilium.artifact("unibilium"));
nvim_exe.linkLibrary(treesitter.artifact("tree-sitter"));
nvim_exe.addIncludePath(b.path("src"));
nvim_exe.addIncludePath(gen_config.getDirectory());
nvim_exe.addIncludePath(gen_headers.getDirectory());
build_lua.add_lua_modules(nvim_exe.root_module, lpeg, use_luajit, false);
var unit_test_sources = try std.ArrayList([]u8).initCapacity(b.allocator, 10);
if (support_unittests) {
var unit_test_fixtures = try src_dir.openDir("test/unit/fixtures/", .{ .iterate = true });
defer unit_test_fixtures.close();
var it = unit_test_fixtures.iterateAssumeFirstIteration();
while (try it.next()) |entry| {
if (entry.name.len < 3) continue;
if (std.mem.eql(u8, ".c", entry.name[entry.name.len - 2 ..])) {
try unit_test_sources.append(b.fmt("test/unit/fixtures/{s}", .{entry.name}));
}
}
}
const src_paths = try b.allocator.alloc([]u8, nvim_sources.items.len + unit_test_sources.items.len);
for (nvim_sources.items, 0..) |s, i| {
src_paths[i] = b.fmt("src/nvim/{s}", .{s.name});
}
@memcpy(src_paths[nvim_sources.items.len..], unit_test_sources.items);
const flags = [_][]const u8{
"-std=gnu99",
"-DINCLUDE_GENERATED_DECLARATIONS",
"-DZIG_BUILD",
"-D_GNU_SOURCE",
if (support_unittests) "-DUNIT_TESTING" else "",
if (use_luajit) "" else "-DNVIM_VENDOR_BIT",
};
nvim_exe.addCSourceFiles(.{ .files = src_paths, .flags = &flags });
nvim_exe.addCSourceFiles(.{ .files = &.{
"src/xdiff/xdiffi.c",
"src/xdiff/xemit.c",
"src/xdiff/xhistogram.c",
"src/xdiff/xpatience.c",
"src/xdiff/xprepare.c",
"src/xdiff/xutils.c",
"src/cjson/lua_cjson.c",
"src/cjson/fpconv.c",
"src/cjson/strbuf.c",
}, .flags = &flags });
const nvim_exe_step = b.step("nvim_bin", "only the binary (not a fully working install!)");
const nvim_exe_install = b.addInstallArtifact(nvim_exe, .{});
nvim_exe_step.dependOn(&nvim_exe_install.step);
const gen_runtime = try runtime.nvim_gen_runtime(b, nlua0, nvim_exe, funcs_data);
const runtime_install = b.addInstallDirectory(.{ .source_dir = gen_runtime.getDirectory(), .install_dir = .prefix, .install_subdir = "runtime/" });
const nvim = b.step("nvim", "build the editor");
nvim.dependOn(&nvim_exe_install.step);
nvim.dependOn(&runtime_install.step);
const lua_dev_deps = b.dependency("lua_dev_deps", .{});
const test_deps = b.step("test_deps", "test prerequisites");
test_deps.dependOn(&nvim_exe_install.step);
test_deps.dependOn(&runtime_install.step);
test_deps.dependOn(test_fixture(b, "shell-test", null, target, optimize));
test_deps.dependOn(test_fixture(b, "tty-test", libuv, target, optimize));
test_deps.dependOn(test_fixture(b, "pwsh-test", null, target, optimize));
test_deps.dependOn(test_fixture(b, "printargs-test", null, target, optimize));
test_deps.dependOn(test_fixture(b, "printenv-test", null, target, optimize));
test_deps.dependOn(test_fixture(b, "streams-test", libuv, target, optimize));
const parser_c = b.dependency("treesitter_c", .{ .target = target, .optimize = optimize });
test_deps.dependOn(add_ts_parser(b, "c", parser_c.path("."), false, target, optimize));
const parser_markdown = b.dependency("treesitter_markdown", .{ .target = target, .optimize = optimize });
test_deps.dependOn(add_ts_parser(b, "markdown", parser_markdown.path("tree-sitter-markdown/"), true, target, optimize));
test_deps.dependOn(add_ts_parser(b, "markdown_inline", parser_markdown.path("tree-sitter-markdown-inline/"), true, target, optimize));
const parser_vim = b.dependency("treesitter_vim", .{ .target = target, .optimize = optimize });
test_deps.dependOn(add_ts_parser(b, "vim", parser_vim.path("."), true, target, optimize));
const parser_vimdoc = b.dependency("treesitter_vimdoc", .{ .target = target, .optimize = optimize });
test_deps.dependOn(add_ts_parser(b, "vimdoc", parser_vimdoc.path("."), false, target, optimize));
const parser_lua = b.dependency("treesitter_lua", .{ .target = target, .optimize = optimize });
test_deps.dependOn(add_ts_parser(b, "lua", parser_lua.path("."), true, target, optimize));
const parser_query = b.dependency("treesitter_query", .{ .target = target, .optimize = optimize });
test_deps.dependOn(add_ts_parser(b, "query", parser_query.path("."), false, target, optimize));
const unit_headers: ?[]const LazyPath = if (support_unittests) &(include_path ++ .{gen_headers.getDirectory()}) else null;
try tests.test_steps(b, nvim_exe, test_deps, lua_dev_deps.path("."), test_config_step.getDirectory(), unit_headers);
}
pub fn test_fixture(
b: *std.Build,
name: []const u8,
libuv: ?*std.Build.Step.Compile,
target: std.Build.ResolvedTarget,
optimize: std.builtin.OptimizeMode,
) *std.Build.Step {
const fixture = b.addExecutable(.{
.name = name,
.target = target,
.optimize = optimize,
});
const source = if (std.mem.eql(u8, name, "pwsh-test")) "shell-test" else name;
fixture.addCSourceFile(.{ .file = b.path(b.fmt("./test/functional/fixtures/{s}.c", .{source})) });
fixture.linkLibC();
if (libuv) |uv| fixture.linkLibrary(uv);
return &b.addInstallArtifact(fixture, .{}).step;
}
pub fn add_ts_parser(
b: *std.Build,
name: []const u8,
parser_dir: LazyPath,
scanner: bool,
target: std.Build.ResolvedTarget,
optimize: std.builtin.OptimizeMode,
) *std.Build.Step {
const parser = b.addLibrary(.{
.name = name,
.root_module = b.createModule(.{
.target = target,
.optimize = optimize,
}),
.linkage = .dynamic,
});
parser.addCSourceFile(.{ .file = parser_dir.path(b, "src/parser.c") });
if (scanner) parser.addCSourceFile(.{ .file = parser_dir.path(b, "src/scanner.c") });
parser.addIncludePath(parser_dir.path(b, "src"));
parser.linkLibC();
const parser_install = b.addInstallArtifact(parser, .{ .dest_sub_path = b.fmt("parser/{s}.so", .{name}) });
return &parser_install.step;
}
pub fn lua_version_info(b: *std.Build) []u8 {
const v = version;
return b.fmt(
\\return {{
\\ {{"major", {}}},
\\ {{"minor", {}}},
\\ {{"patch", {}}},
\\ {{"prerelease", {}}},
\\ {{"api_level", {}}},
\\ {{"api_compatible", {}}},
\\ {{"api_prerelease", {}}},
\\}}
, .{ v.major, v.minor, v.patch, v.prerelease.len > 0, v.api_level, v.api_level_compat, v.api_prerelease });
}
pub fn test_config(b: *std.Build) ![]u8 {
var buf: [std.fs.max_path_bytes]u8 = undefined;
const src_path = try b.build_root.handle.realpath(".", &buf);
// we don't use test/cmakeconfig/paths.lua.in because it contains cmake specific logic
return b.fmt(
\\local M = {{}}
\\
\\M.apple_sysroot = ""
\\M.translations_enabled = "$ENABLE_TRANSLATIONS" == "ON"
\\M.is_asan = "$ENABLE_ASAN_UBSAN" == "ON"
\\M.is_zig_build = true
\\M.vterm_test_file = "test/vterm_test_output"
\\M.test_build_dir = "{[bin_dir]s}" -- bull
\\M.test_source_path = "{[src_path]s}"
\\M.test_lua_prg = ""
\\M.test_luajit_prg = ""
\\ -- include path passed on the cmdline, see test/lua_runner.lua
\\M.include_paths = _G.c_include_path or {{}}
\\
\\return M
, .{ .bin_dir = b.install_path, .src_path = src_path });
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/mirrors/neovim.git
git@gitee.com:mirrors/neovim.git
mirrors
neovim
neovim
master

搜索帮助