mirror of
https://github.com/neovim/neovim.git
synced 2025-09-18 09:18:19 +00:00
build(ci): bump zig to 0.15.1 and add more platforms
- Bump zig version to 0.15.1 and workaround zig fetch hang (ziglang/zig#24916) - add mac os zig build (currently without luajit, linker failure) - Add windows zig build, currently with very limited testing
This commit is contained in:
48
.github/workflows/test.yml
vendored
48
.github/workflows/test.yml
vendored
@@ -204,7 +204,8 @@ jobs:
|
|||||||
name: Show logs
|
name: Show logs
|
||||||
run: cat $(find "$LOG_DIR" -type f)
|
run: cat $(find "$LOG_DIR" -type f)
|
||||||
|
|
||||||
zig-build:
|
# TODO: matrixify
|
||||||
|
zig-build-linux:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
timeout-minutes: 45
|
timeout-minutes: 45
|
||||||
name: build using zig build (linux)
|
name: build using zig build (linux)
|
||||||
@@ -212,8 +213,15 @@ jobs:
|
|||||||
- uses: actions/checkout@v5
|
- uses: actions/checkout@v5
|
||||||
- uses: mlugg/setup-zig@v2
|
- uses: mlugg/setup-zig@v2
|
||||||
with:
|
with:
|
||||||
version: 0.14.1
|
version: 0.15.1
|
||||||
- run: sudo apt-get install -y inotify-tools
|
- run: sudo apt-get install -y inotify-tools
|
||||||
|
|
||||||
|
# This is a workaround for "zig fetch" being unable to decompress lua-dev-deps.tar.gz
|
||||||
|
# As the hash in build.zig.zon is calculated after decompression, we can preload the cache instead.
|
||||||
|
# This is hopefully fixed for zig 0.15.2, see https://github.com/ziglang/zig/issues/24916
|
||||||
|
- run: curl -L https://github.com/neovim/deps/raw/06ef2b58b0876f8de1a3f5a710473dcd7afff251/opt/lua-dev-deps.tar.gz | zcat > lua-dev-deps.tar
|
||||||
|
- run: zig fetch lua-dev-deps.tar
|
||||||
|
|
||||||
- run: zig build test_nlua0
|
- run: zig build test_nlua0
|
||||||
- run: zig build nvim && ./zig-out/bin/nvim --version
|
- run: zig build nvim && ./zig-out/bin/nvim --version
|
||||||
- run: zig build unittest
|
- run: zig build unittest
|
||||||
@@ -223,6 +231,42 @@ jobs:
|
|||||||
- run: cd runtime; ../zig-out/bin/nvim -u NONE -i NONE -e --headless -c "helptags ++t doc" -c quit
|
- run: cd runtime; ../zig-out/bin/nvim -u NONE -i NONE -e --headless -c "helptags ++t doc" -c quit
|
||||||
- run: diff -u runtime/doc/tags zig-out/runtime/doc/tags
|
- run: diff -u runtime/doc/tags zig-out/runtime/doc/tags
|
||||||
|
|
||||||
|
zig-build-macos-15:
|
||||||
|
runs-on: macos-15
|
||||||
|
timeout-minutes: 45
|
||||||
|
name: build using zig build (macos 15)
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: mlugg/setup-zig@v2
|
||||||
|
with:
|
||||||
|
version: 0.15.1
|
||||||
|
|
||||||
|
- run: curl -L https://github.com/neovim/deps/raw/06ef2b58b0876f8de1a3f5a710473dcd7afff251/opt/lua-dev-deps.tar.gz | zcat > lua-dev-deps.tar
|
||||||
|
- run: zig fetch lua-dev-deps.tar
|
||||||
|
|
||||||
|
- run: zig build test_nlua0 -Dluajit=false
|
||||||
|
- run: zig build nvim_bin -Dluajit=false && ./zig-out/bin/nvim --version
|
||||||
|
- run: zig build functionaltest -Dluajit=false
|
||||||
|
|
||||||
|
zig-build-windows:
|
||||||
|
runs-on: windows-2022
|
||||||
|
timeout-minutes: 45
|
||||||
|
name: build using zig build (windows)
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: mlugg/setup-zig@v2
|
||||||
|
with:
|
||||||
|
version: 0.15.1
|
||||||
|
|
||||||
|
- run: curl -L https://github.com/neovim/deps/raw/06ef2b58b0876f8de1a3f5a710473dcd7afff251/opt/lua-dev-deps.tar.gz -O
|
||||||
|
- run: 7z x lua-dev-deps.tar.gz
|
||||||
|
- run: zig fetch lua-dev-deps.tar
|
||||||
|
- run: zig build test_nlua0
|
||||||
|
- run: zig build nvim_bin
|
||||||
|
- run: ./zig-out/bin/nvim --version
|
||||||
|
# TODO: support entire test suite
|
||||||
|
- run: zig build functionaltest -- test/functional/api/buffer_spec.lua
|
||||||
|
|
||||||
windows:
|
windows:
|
||||||
uses: ./.github/workflows/test_windows.yml
|
uses: ./.github/workflows/test_windows.yml
|
||||||
|
|
||||||
|
45
build.zig
45
build.zig
@@ -43,7 +43,8 @@ pub fn build(b: *std.Build) !void {
|
|||||||
const cross_compiling = b.option(bool, "cross", "cross compile") orelse false;
|
const cross_compiling = b.option(bool, "cross", "cross compile") orelse false;
|
||||||
// TODO(bfredl): option to set nlua0 target explicitly when cross compiling?
|
// TODO(bfredl): option to set nlua0 target explicitly when cross compiling?
|
||||||
const target_host = if (cross_compiling) b.graph.host else target;
|
const target_host = if (cross_compiling) b.graph.host else target;
|
||||||
const optimize_host = .ReleaseSafe;
|
// without cross_compiling we like to reuse libluv etc at the same optimize level
|
||||||
|
const optimize_host = if (cross_compiling) .ReleaseSafe else optimize;
|
||||||
|
|
||||||
// puc lua 5.1 is not ReleaseSafe "safe"
|
// puc lua 5.1 is not ReleaseSafe "safe"
|
||||||
const optimize_lua = if (optimize == .Debug or optimize == .ReleaseSafe) .ReleaseSmall else optimize;
|
const optimize_lua = if (optimize == .Debug or optimize == .ReleaseSafe) .ReleaseSmall else optimize;
|
||||||
@@ -63,7 +64,7 @@ pub fn build(b: *std.Build) !void {
|
|||||||
|
|
||||||
const ziglua_host = if (cross_compiling) b.dependency("zlua", .{
|
const ziglua_host = if (cross_compiling) b.dependency("zlua", .{
|
||||||
.target = target_host,
|
.target = target_host,
|
||||||
.optimize = optimize_lua,
|
.optimize = .ReleaseSmall,
|
||||||
.lang = if (host_use_luajit) E.luajit else E.lua51,
|
.lang = if (host_use_luajit) E.luajit else E.lua51,
|
||||||
.shared = false,
|
.shared = false,
|
||||||
}) else ziglua;
|
}) else ziglua;
|
||||||
@@ -146,12 +147,12 @@ pub fn build(b: *std.Build) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (std.mem.eql(u8, ".c", entry.name[entry.name.len - 2 ..])) {
|
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 });
|
try nvim_sources.append(b.allocator, .{ .name = b.fmt("{s}{s}", .{ s, entry.name }), .api_export = api_export });
|
||||||
}
|
}
|
||||||
if (std.mem.eql(u8, ".h", entry.name[entry.name.len - 2 ..])) {
|
if (std.mem.eql(u8, ".h", entry.name[entry.name.len - 2 ..])) {
|
||||||
try nvim_headers.append(b.fmt("{s}{s}", .{ s, entry.name }));
|
try nvim_headers.append(b.allocator, b.fmt("{s}{s}", .{ s, entry.name }));
|
||||||
if (api_export and !std.mem.eql(u8, "ui_events.in.h", 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 })));
|
try api_headers.append(b.allocator, b.path(b.fmt("src/nvim/{s}{s}", .{ s, entry.name })));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -296,7 +297,7 @@ pub fn build(b: *std.Build) !void {
|
|||||||
while (try it.next()) |entry| {
|
while (try it.next()) |entry| {
|
||||||
if (entry.name.len < 3) continue;
|
if (entry.name.len < 3) continue;
|
||||||
if (std.mem.eql(u8, ".c", entry.name[entry.name.len - 2 ..])) {
|
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}));
|
try unit_test_sources.append(b.allocator, b.fmt("test/unit/fixtures/{s}", .{entry.name}));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -331,6 +332,10 @@ pub fn build(b: *std.Build) !void {
|
|||||||
"src/cjson/strbuf.c",
|
"src/cjson/strbuf.c",
|
||||||
}, .flags = &flags });
|
}, .flags = &flags });
|
||||||
|
|
||||||
|
if (is_windows) {
|
||||||
|
nvim_exe.addWin32ResourceFile(.{ .file = b.path("src/nvim/os/nvim.rc") });
|
||||||
|
}
|
||||||
|
|
||||||
const nvim_exe_step = b.step("nvim_bin", "only the binary (not a fully working install!)");
|
const nvim_exe_step = b.step("nvim_bin", "only the binary (not a fully working install!)");
|
||||||
const nvim_exe_install = b.addInstallArtifact(nvim_exe, .{});
|
const nvim_exe_install = b.addInstallArtifact(nvim_exe, .{});
|
||||||
|
|
||||||
@@ -350,12 +355,12 @@ pub fn build(b: *std.Build) !void {
|
|||||||
test_deps.dependOn(&nvim_exe_install.step);
|
test_deps.dependOn(&nvim_exe_install.step);
|
||||||
test_deps.dependOn(&runtime_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, "shell-test", null, target, optimize, &flags));
|
||||||
test_deps.dependOn(test_fixture(b, "tty-test", libuv, target, optimize));
|
test_deps.dependOn(test_fixture(b, "tty-test", libuv, target, optimize, &flags));
|
||||||
test_deps.dependOn(test_fixture(b, "pwsh-test", null, target, optimize));
|
test_deps.dependOn(test_fixture(b, "pwsh-test", null, target, optimize, &flags));
|
||||||
test_deps.dependOn(test_fixture(b, "printargs-test", null, target, optimize));
|
test_deps.dependOn(test_fixture(b, "printargs-test", null, target, optimize, &flags));
|
||||||
test_deps.dependOn(test_fixture(b, "printenv-test", null, target, optimize));
|
test_deps.dependOn(test_fixture(b, "printenv-test", null, target, optimize, &flags));
|
||||||
test_deps.dependOn(test_fixture(b, "streams-test", libuv, target, optimize));
|
test_deps.dependOn(test_fixture(b, "streams-test", libuv, target, optimize, &flags));
|
||||||
|
|
||||||
const parser_c = b.dependency("treesitter_c", .{ .target = target, .optimize = 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));
|
test_deps.dependOn(add_ts_parser(b, "c", parser_c.path("."), false, target, optimize));
|
||||||
@@ -382,6 +387,7 @@ pub fn test_fixture(
|
|||||||
libuv: ?*std.Build.Step.Compile,
|
libuv: ?*std.Build.Step.Compile,
|
||||||
target: std.Build.ResolvedTarget,
|
target: std.Build.ResolvedTarget,
|
||||||
optimize: std.builtin.OptimizeMode,
|
optimize: std.builtin.OptimizeMode,
|
||||||
|
flags: []const []const u8,
|
||||||
) *std.Build.Step {
|
) *std.Build.Step {
|
||||||
const fixture = b.addExecutable(.{
|
const fixture = b.addExecutable(.{
|
||||||
.name = name,
|
.name = name,
|
||||||
@@ -391,7 +397,11 @@ pub fn test_fixture(
|
|||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
const source = if (std.mem.eql(u8, name, "pwsh-test")) "shell-test" else name;
|
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})) });
|
if (std.mem.eql(u8, name, "printenv-test")) {
|
||||||
|
fixture.mingw_unicode_entry_point = true; // uses UNICODE on WINDOWS :scream:
|
||||||
|
}
|
||||||
|
|
||||||
|
fixture.addCSourceFile(.{ .file = b.path(b.fmt("./test/functional/fixtures/{s}.c", .{source})), .flags = flags });
|
||||||
fixture.linkLibC();
|
fixture.linkLibC();
|
||||||
if (libuv) |uv| fixture.linkLibrary(uv);
|
if (libuv) |uv| fixture.linkLibrary(uv);
|
||||||
return &b.addInstallArtifact(fixture, .{}).step;
|
return &b.addInstallArtifact(fixture, .{}).step;
|
||||||
@@ -437,6 +447,13 @@ pub fn lua_version_info(b: *std.Build) []u8 {
|
|||||||
, .{ v.major, v.minor, v.patch, v.prerelease.len > 0, v.api_level, v.api_level_compat, v.api_prerelease });
|
, .{ v.major, v.minor, v.patch, v.prerelease.len > 0, v.api_level, v.api_level_compat, v.api_prerelease });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn esc(b: *std.Build, input: []const u8) ![]const u8 {
|
||||||
|
return if (b.graph.host.result.os.tag == .windows)
|
||||||
|
std.mem.replaceOwned(u8, b.graph.arena, input, "\\", "/")
|
||||||
|
else
|
||||||
|
input;
|
||||||
|
}
|
||||||
|
|
||||||
pub fn test_config(b: *std.Build) ![]u8 {
|
pub fn test_config(b: *std.Build) ![]u8 {
|
||||||
var buf: [std.fs.max_path_bytes]u8 = undefined;
|
var buf: [std.fs.max_path_bytes]u8 = undefined;
|
||||||
const src_path = try b.build_root.handle.realpath(".", &buf);
|
const src_path = try b.build_root.handle.realpath(".", &buf);
|
||||||
@@ -458,5 +475,5 @@ pub fn test_config(b: *std.Build) ![]u8 {
|
|||||||
\\M.include_paths = _G.c_include_path or {{}}
|
\\M.include_paths = _G.c_include_path or {{}}
|
||||||
\\
|
\\
|
||||||
\\return M
|
\\return M
|
||||||
, .{ .bin_dir = b.install_path, .src_path = src_path });
|
, .{ .bin_dir = try esc(b, b.install_path), .src_path = try esc(b, src_path) });
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
.name = .neovim,
|
.name = .neovim,
|
||||||
.fingerprint = 0x66eb090879307a38,
|
.fingerprint = 0x66eb090879307a38,
|
||||||
.version = "0.12.0",
|
.version = "0.12.0",
|
||||||
.minimum_zig_version = "0.14.0",
|
.minimum_zig_version = "0.15.0",
|
||||||
|
|
||||||
.dependencies = .{
|
.dependencies = .{
|
||||||
.zlua = .{
|
.zlua = .{
|
||||||
|
@@ -171,7 +171,7 @@ local ui_options_text = nil
|
|||||||
for i = pre_args + 1, #arg do
|
for i = pre_args + 1, #arg do
|
||||||
local full_path = arg[i]
|
local full_path = arg[i]
|
||||||
local parts = {} --- @type string[]
|
local parts = {} --- @type string[]
|
||||||
for part in full_path:gmatch('[^/]+') do
|
for part in full_path:gmatch('[^/\\]+') do
|
||||||
parts[#parts + 1] = part
|
parts[#parts + 1] = part
|
||||||
end
|
end
|
||||||
headers[#headers + 1] = parts[#parts - 1] .. '/' .. parts[#parts]
|
headers[#headers + 1] = parts[#parts - 1] .. '/' .. parts[#parts]
|
||||||
|
@@ -186,7 +186,7 @@ fn generate_header_for(
|
|||||||
} else {
|
} else {
|
||||||
const h_file = gen_header(b, run_step, b.fmt("{s}.h.generated.h", .{basename}), gen_headers);
|
const h_file = gen_header(b, run_step, b.fmt("{s}.h.generated.h", .{basename}), gen_headers);
|
||||||
if (api_export) |api_files| {
|
if (api_export) |api_files| {
|
||||||
try api_files.append(h_file);
|
try api_files.append(b.allocator, h_file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -463,9 +463,9 @@ describe('lua stdlib', function()
|
|||||||
eq(false, fn.luaeval "vim.v['false']")
|
eq(false, fn.luaeval "vim.v['false']")
|
||||||
eq(NIL, fn.luaeval 'vim.v.null')
|
eq(NIL, fn.luaeval 'vim.v.null')
|
||||||
matches([[attempt to index .* nil value]], pcall_err(exec_lua, 'return vim.v[0].progpath'))
|
matches([[attempt to index .* nil value]], pcall_err(exec_lua, 'return vim.v[0].progpath'))
|
||||||
eq('Key is read-only: count', pcall_err(exec_lua, [[vim.v.count = 42]]))
|
matches('Key is read%-only: count$', pcall_err(exec_lua, [[vim.v.count = 42]]))
|
||||||
eq('Dict is locked', pcall_err(exec_lua, [[vim.v.nosuchvar = 42]]))
|
matches('Dict is locked$', pcall_err(exec_lua, [[vim.v.nosuchvar = 42]]))
|
||||||
eq('Key is fixed: errmsg', pcall_err(exec_lua, [[vim.v.errmsg = nil]]))
|
matches('Key is fixed: errmsg$', pcall_err(exec_lua, [[vim.v.errmsg = nil]]))
|
||||||
exec_lua([[vim.v.errmsg = 'set by Lua']])
|
exec_lua([[vim.v.errmsg = 'set by Lua']])
|
||||||
eq('set by Lua', eval('v:errmsg'))
|
eq('set by Lua', eval('v:errmsg'))
|
||||||
exec_lua([[vim.v.errmsg = 42]])
|
exec_lua([[vim.v.errmsg = 42]])
|
||||||
@@ -474,8 +474,8 @@ describe('lua stdlib', function()
|
|||||||
eq({ 'one', 'two' }, eval('v:oldfiles'))
|
eq({ 'one', 'two' }, eval('v:oldfiles'))
|
||||||
exec_lua([[vim.v.oldfiles = {}]])
|
exec_lua([[vim.v.oldfiles = {}]])
|
||||||
eq({}, eval('v:oldfiles'))
|
eq({}, eval('v:oldfiles'))
|
||||||
eq(
|
matches(
|
||||||
'Setting v:oldfiles to value with wrong type',
|
'Setting v:oldfiles to value with wrong type$',
|
||||||
pcall_err(exec_lua, [[vim.v.oldfiles = 'a']])
|
pcall_err(exec_lua, [[vim.v.oldfiles = 'a']])
|
||||||
)
|
)
|
||||||
eq({}, eval('v:oldfiles'))
|
eq({}, eval('v:oldfiles'))
|
||||||
|
@@ -4,6 +4,7 @@ local n = require('test.functional.testnvim')()
|
|||||||
local clear = n.clear
|
local clear = n.clear
|
||||||
local exec_lua = n.exec_lua
|
local exec_lua = n.exec_lua
|
||||||
local eq = t.eq
|
local eq = t.eq
|
||||||
|
local matches = t.matches
|
||||||
local pcall_err = t.pcall_err
|
local pcall_err = t.pcall_err
|
||||||
|
|
||||||
describe('xdiff bindings', function()
|
describe('xdiff bindings', function()
|
||||||
@@ -169,25 +170,25 @@ describe('xdiff bindings', function()
|
|||||||
end)
|
end)
|
||||||
|
|
||||||
it('can handle bad args', function()
|
it('can handle bad args', function()
|
||||||
eq([[Expected at least 2 arguments]], pcall_err(exec_lua, [[vim.text.diff('a')]]))
|
matches([[Expected at least 2 arguments$]], pcall_err(exec_lua, [[vim.text.diff('a')]]))
|
||||||
|
|
||||||
t.matches(
|
matches(
|
||||||
[[bad argument %#1 to '_?diff' %(expected string%)]],
|
[[bad argument %#1 to '_?diff' %(expected string%)]],
|
||||||
pcall_err(exec_lua, [[vim.text.diff(1, 2)]])
|
pcall_err(exec_lua, [[vim.text.diff(1, 2)]])
|
||||||
)
|
)
|
||||||
|
|
||||||
t.matches(
|
matches(
|
||||||
[[bad argument %#3 to '_?diff' %(expected table%)]],
|
[[bad argument %#3 to '_?diff' %(expected table%)]],
|
||||||
pcall_err(exec_lua, [[vim.text.diff('a', 'b', true)]])
|
pcall_err(exec_lua, [[vim.text.diff('a', 'b', true)]])
|
||||||
)
|
)
|
||||||
|
|
||||||
eq(
|
matches(
|
||||||
[[invalid key: bad_key]],
|
[[invalid key: bad_key$]],
|
||||||
pcall_err(exec_lua, [[vim.text.diff('a', 'b', { bad_key = true })]])
|
pcall_err(exec_lua, [[vim.text.diff('a', 'b', { bad_key = true })]])
|
||||||
)
|
)
|
||||||
|
|
||||||
eq(
|
matches(
|
||||||
[[on_hunk is not a function]],
|
[[on_hunk is not a function$]],
|
||||||
pcall_err(exec_lua, [[vim.text.diff('a', 'b', { on_hunk = true })]])
|
pcall_err(exec_lua, [[vim.text.diff('a', 'b', { on_hunk = true })]])
|
||||||
)
|
)
|
||||||
end)
|
end)
|
||||||
|
@@ -4,8 +4,8 @@
|
|||||||
local t = require('test.testutil')
|
local t = require('test.testutil')
|
||||||
require('test.functional.ui.screen')
|
require('test.functional.ui.screen')
|
||||||
|
|
||||||
if t.is_os('win') then
|
local has_ffi, ffi = pcall(require, 'ffi')
|
||||||
local ffi = require('ffi')
|
if t.is_os('win') and has_ffi then
|
||||||
ffi.cdef [[
|
ffi.cdef [[
|
||||||
typedef int errno_t;
|
typedef int errno_t;
|
||||||
errno_t _set_fmode(int mode);
|
errno_t _set_fmode(int mode);
|
||||||
|
Reference in New Issue
Block a user