neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

commit dc6cf3add95ac80ad4cb31942972f01b31b8998d
parent 22d90217c6774c7b8c5ee79366f03b8ab41bd029
Author: bfredl <bjorn.linse@gmail.com>
Date:   Thu, 17 Jul 2025 10:55:43 +0200

feat(build): build.zig windows support

Tested using cross-compiling from linux:

    zig build -Dcross=true -Dtarget=x86_64-windows nvim_bin

Note: not fully functional without a runtime, which still has to be
fuddled with manually

Macos and windows builds require a recent zig 0.15+dev version
As this zig master branch is currently too much in flux, we can't make
our CI depend on zig master.

Revisit CI after zig 0.15 release or at least feature freeze.

Diffstat:
M.github/workflows/test.yml | 2+-
Mbuild.zig | 20++++++++++++++------
Mbuild.zig.zon | 11+++++++++--
Ddeps/iconv_apple/build.zig | 93-------------------------------------------------------------------------------
Ddeps/iconv_apple/build.zig.zon | 12------------
Ddeps/iconv_apple/include/os/variant_private.h | 1-
Ddeps/libuv/build.zig | 128-------------------------------------------------------------------------------
Ddeps/libuv/build.zig.zon | 12------------
Mdeps/utf8proc/build.zig | 2+-
9 files changed, 25 insertions(+), 256 deletions(-)

diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml @@ -209,7 +209,7 @@ jobs: zig-build: runs-on: ubuntu-24.04 timeout-minutes: 45 - name: build using zig build + name: build using zig build (linux) steps: - uses: actions/checkout@v4 - uses: mlugg/setup-zig@v2 diff --git a/build.zig b/build.zig @@ -70,11 +70,14 @@ pub fn build(b: *std.Build) !void { const lpeg = b.dependency("lpeg", .{}); - const iconv_apple = if (cross_compiling and is_darwin) b.lazyDependency("iconv_apple", .{ .target = target, .optimize = optimize }) else null; + const iconv = if (is_windows or is_darwin) b.lazyDependency("libiconv", .{ .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; + if (cross_compiling) { + _ = lazyArtifact(ziglua_host, "lua") orelse return; + } // const lua = ziglua.artifact("lua"); const libuv_dep = b.dependency("libuv", .{ .target = target, .optimize = optimize }); @@ -234,7 +237,7 @@ pub fn build(b: *std.Build) !void { // TODO(zig): using getEmittedIncludeTree() is ugly af. we want unittests // to reuse the std.build.Module include_path thing - const include_path = [_]LazyPath{ + const unittest_include_path = [_]LazyPath{ b.path("src/"), gen_config.getDirectory(), lua.getEmittedIncludeTree(), @@ -243,6 +246,7 @@ pub fn build(b: *std.Build) !void { utf8proc.artifact("utf8proc").getEmittedIncludeTree(), unibilium.artifact("unibilium").getEmittedIncludeTree(), treesitter.artifact("tree-sitter").getEmittedIncludeTree(), + if (iconv) |dep| dep.artifact("iconv").getEmittedIncludeTree() else b.path("UNUSED_PATH/"), }; const gen_headers, const funcs_data = try gen.nvim_gen_sources(b, nlua0, &nvim_sources, &nvim_headers, &api_headers, versiondef_git, version_lua); @@ -267,12 +271,13 @@ pub fn build(b: *std.Build) !void { nvim_exe.linkLibrary(lua); nvim_exe.linkLibrary(libuv); nvim_exe.linkLibrary(libluv); - if (iconv_apple) |iconv| { - nvim_exe.linkLibrary(iconv.artifact("iconv")); - } + if (iconv) |dep| nvim_exe.linkLibrary(dep.artifact("iconv")); nvim_exe.linkLibrary(utf8proc.artifact("utf8proc")); nvim_exe.linkLibrary(unibilium.artifact("unibilium")); nvim_exe.linkLibrary(treesitter.artifact("tree-sitter")); + if (is_windows) { + nvim_exe.linkSystemLibrary("netapi32"); + } nvim_exe.addIncludePath(b.path("src")); nvim_exe.addIncludePath(gen_config.getDirectory()); nvim_exe.addIncludePath(gen_headers.getDirectory()); @@ -304,6 +309,9 @@ pub fn build(b: *std.Build) !void { "-D_GNU_SOURCE", if (support_unittests) "-DUNIT_TESTING" else "", if (use_luajit) "" else "-DNVIM_VENDOR_BIT", + if (is_windows) "-DMSWIN" else "", + if (is_windows) "-DWIN32_LEAN_AND_MEAN" else "", + if (is_windows) "-DUTF8PROC_STATIC" else "", }; nvim_exe.addCSourceFiles(.{ .files = src_paths, .flags = &flags }); @@ -359,7 +367,7 @@ pub fn build(b: *std.Build) !void { 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; + const unit_headers: ?[]const LazyPath = if (support_unittests) &(unittest_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); } diff --git a/build.zig.zon b/build.zig.zon @@ -25,10 +25,17 @@ .url = "git+https://github.com/tree-sitter/tree-sitter#d87921bb9c39b0b06c811f2082f9a9991cdca027", .hash = "tree_sitter-0.26.0-Tw2sRxO7CwC0NyDrSygSi7UXRHMNUFEF8GRq6dK81lRF", }, - .libuv = .{ .path = "./deps/libuv" }, + .libuv = .{ + .url = "git+https://github.com/allyourcodebase/libuv#a2dfd385bd2a00d6d290fda85a40a55a9d6cffc5", + .hash = "libuv-1.51.0-htqqv6liAADxBLIBCZT-qUh_3nRRwtNYsOFQOUmrd_sx", + }, .utf8proc = .{ .path = "./deps/utf8proc/" }, .unibilium = .{ .path = "./deps/unibilium/" }, - .iconv_apple = .{ .path = "./deps/iconv_apple/", .lazy = true }, + .libiconv = .{ + .url = "git+https://github.com/allyourcodebase/libiconv#9def4c8a1743380e85bcedb80f2c15b455e236f3", + .hash = "libiconv-1.18.0-p9sJwWnqAACzVYeWgXB5r5lOQ74XwTPlptixV0JPRO28", + .lazy = true, + }, .lua_dev_deps = .{ .url = "https://github.com/neovim/deps/raw/06ef2b58b0876f8de1a3f5a710473dcd7afff251/opt/lua-dev-deps.tar.gz", .hash = "N-V-__8AAGevEQCHAkCozca5AIdN9DFc3Luf3g3r2AcbyOrm", diff --git a/deps/iconv_apple/build.zig b/deps/iconv_apple/build.zig @@ -1,93 +0,0 @@ -const std = @import("std"); - -pub fn build(b: *std.Build) !void { - const target = b.standardTargetOptions(.{}); - const optimize = b.standardOptimizeOption(.{}); - - const upstream = b.dependency("libiconv", .{}); - const lib = b.addLibrary(.{ - .name = "iconv", - .linkage = .static, - .root_module = b.createModule(.{ - .target = target, - .optimize = optimize, - }), - }); - - lib.addIncludePath(b.path("include/")); - lib.addIncludePath(upstream.path("")); - lib.addIncludePath(upstream.path("citrus/")); - lib.addIncludePath(upstream.path("libcharset/")); - lib.addIncludePath(upstream.path("libiconv_modules/UTF8/")); - // zig any-macos-any headers already includes iconv, it just cannot link without a SDK - // lib.installHeader(upstream.path("iconv.h"), "iconv.h"); - - lib.linkLibC(); - - lib.addCSourceFiles(.{ .root = upstream.path(""), .files = &.{ - "citrus/bsd_iconv.c", - "citrus/citrus_bcs.c", - "citrus/citrus_bcs_strtol.c", - "citrus/citrus_bcs_strtoul.c", - "citrus/citrus_csmapper.c", - "citrus/citrus_db.c", - "citrus/citrus_db_factory.c", - "citrus/citrus_db_hash.c", - "citrus/citrus_esdb.c", - "citrus/citrus_hash.c", - "citrus/citrus_iconv.c", - "citrus/citrus_lookup.c", - "citrus/citrus_lookup_factory.c", - "citrus/citrus_mapper.c", - "citrus/citrus_memstream.c", - "citrus/citrus_mmap.c", - "citrus/citrus_module.c", - "citrus/citrus_none.c", - "citrus/citrus_pivot_factory.c", - "citrus/citrus_prop.c", - "citrus/citrus_stdenc.c", - "citrus/__iconv.c", - "citrus/iconv.c", - "citrus/iconv_canonicalize.c", - "citrus/iconv_close.c", - "citrus/iconv_compat.c", - "citrus/iconvctl.c", - "citrus/__iconv_free_list.c", - "citrus/__iconv_get_list.c", - "citrus/iconvlist.c", - "citrus/iconv_open.c", - "citrus/iconv_open_into.c", - "citrus/iconv_set_relocation_prefix.c", - "libcharset/libcharset.c", - "libiconv_modules/BIG5/citrus_big5.c", - "libiconv_modules/DECHanyu/citrus_dechanyu.c", - "libiconv_modules/DECKanji/citrus_deckanji.c", - "libiconv_modules/EUC/citrus_euc.c", - "libiconv_modules/EUCTW/citrus_euctw.c", - "libiconv_modules/GBK2K/citrus_gbk2k.c", - "libiconv_modules/HZ/citrus_hz.c", - "libiconv_modules/iconv_none/citrus_iconv_none.c", - "libiconv_modules/iconv_std/citrus_iconv_std.c", - "libiconv_modules/ISO2022/citrus_iso2022.c", - "libiconv_modules/JOHAB/citrus_johab.c", - "libiconv_modules/mapper_646/citrus_mapper_646.c", - "libiconv_modules/mapper_none/citrus_mapper_none.c", - "libiconv_modules/mapper_serial/citrus_mapper_serial.c", - "libiconv_modules/mapper_std/citrus_mapper_std.c", - "libiconv_modules/mapper_zone/citrus_mapper_zone.c", - "libiconv_modules/MSKanji/citrus_mskanji.c", - "libiconv_modules/UES/citrus_ues.c", - "libiconv_modules/UTF1632/citrus_utf1632.c", - "libiconv_modules/UTF7/citrus_utf7.c", - "libiconv_modules/UTF8/citrus_utf8.c", - "libiconv_modules/UTF8MAC/citrus_utf8mac.c", - "libiconv_modules/VIQR/citrus_viqr.c", - "libiconv_modules/ZW/citrus_zw.c", - }, .flags = &.{ - "-D_PATH_I18NMODULE=\"/usr/lib/i18n\"", - "-D_PATH_ESDB=\"/usr/share/i18n/esdb\"", - "-D_PATH_CSMAPPER=\"/usr/share/i18n/csmapper\"", - } }); - - b.installArtifact(lib); -} diff --git a/deps/iconv_apple/build.zig.zon b/deps/iconv_apple/build.zig.zon @@ -1,12 +0,0 @@ -.{ - .name = "libiconv", - .version = "107.0.0", - .paths = .{""}, - - .dependencies = .{ - .libiconv = .{ - .url = "git+https://github.com/apple-oss-distributions/libiconv?ref=libiconv-107#a3f3b2c76dbf8ba11881debc6bcb4e309958d252", - .hash = "N-V-__8AAKce8wQq3Mp26YIvUGtazS8KPihcFS4vSGgzQf1x", - }, - }, -} diff --git a/deps/iconv_apple/include/os/variant_private.h b/deps/iconv_apple/include/os/variant_private.h @@ -1 +0,0 @@ -#define os_variant_has_internal_content(sys) false diff --git a/deps/libuv/build.zig b/deps/libuv/build.zig @@ -1,128 +0,0 @@ -const std = @import("std"); - -// Based on mitchellh/zig-libuv, with changes. -pub fn build(b: *std.Build) !void { - const target = b.standardTargetOptions(.{}); - const optimize = b.standardOptimizeOption(.{}); - - const upstream = b.dependency("libuv", .{}); - const lib = b.addLibrary(.{ - .name = "uv", - .linkage = .static, - .root_module = b.createModule(.{ - .target = target, - .optimize = optimize, - }), - }); - - lib.addIncludePath(upstream.path("include")); - lib.addIncludePath(upstream.path("src")); - - lib.installHeadersDirectory(upstream.path("include"), ".", .{}); - - if (target.result.os.tag == .windows) { - lib.linkSystemLibrary("psapi"); - lib.linkSystemLibrary("user32"); - lib.linkSystemLibrary("advapi32"); - lib.linkSystemLibrary("iphlpapi"); - lib.linkSystemLibrary("userenv"); - lib.linkSystemLibrary("ws2_32"); - } - if (target.result.os.tag == .linux) { - lib.linkSystemLibrary("pthread"); - } - lib.linkLibC(); - - if (target.result.os.tag != .windows) { - lib.root_module.addCMacro("FILE_OFFSET_BITS", "64"); - lib.root_module.addCMacro("_LARGEFILE_SOURCE", ""); - } - - if (target.result.os.tag == .linux) { - lib.root_module.addCMacro("_GNU_SOURCE", ""); - lib.root_module.addCMacro("_POSIX_C_SOURCE", "200112"); - } - - if (target.result.os.tag.isDarwin()) { - lib.root_module.addCMacro("_DARWIN_UNLIMITED_SELECT", "1"); - lib.root_module.addCMacro("_DARWIN_USE_64_BIT_INODE", "1"); - } - - const root = upstream.path(""); - - // C files common to all platforms - lib.addCSourceFiles(.{ .root = root, .files = &.{ - "src/fs-poll.c", - "src/idna.c", - "src/inet.c", - "src/random.c", - "src/strscpy.c", - "src/strtok.c", - "src/threadpool.c", - "src/timer.c", - "src/uv-common.c", - "src/uv-data-getter-setters.c", - "src/version.c", - } }); - - if (target.result.os.tag != .windows) { - lib.addCSourceFiles(.{ .root = root, .files = &.{ - "src/unix/async.c", - "src/unix/core.c", - "src/unix/dl.c", - "src/unix/fs.c", - "src/unix/getaddrinfo.c", - "src/unix/getnameinfo.c", - "src/unix/loop-watcher.c", - "src/unix/loop.c", - "src/unix/pipe.c", - "src/unix/poll.c", - "src/unix/process.c", - "src/unix/random-devurandom.c", - "src/unix/signal.c", - "src/unix/stream.c", - "src/unix/tcp.c", - "src/unix/thread.c", - "src/unix/tty.c", - "src/unix/udp.c", - } }); - } - - if (target.result.os.tag == .linux or target.result.os.tag.isDarwin()) { - lib.addCSourceFiles(.{ .root = root, .files = &.{ - "src/unix/proctitle.c", - } }); - } - - if (target.result.os.tag == .linux) { - lib.addCSourceFiles(.{ .root = root, .files = &.{ - "src/unix/linux.c", - "src/unix/procfs-exepath.c", - "src/unix/random-getrandom.c", - "src/unix/random-sysctl-linux.c", - } }); - } - - if (target.result.os.tag.isBSD()) { - lib.addCSourceFiles(.{ .root = root, .files = &.{ - "src/unix/bsd-ifaddrs.c", - "src/unix/kqueue.c", - } }); - } - - if (target.result.os.tag.isDarwin() or target.result.os.tag == .openbsd) { - lib.addCSourceFiles(.{ .root = root, .files = &.{ - "src/unix/random-getentropy.c", - } }); - } - - if (target.result.os.tag.isDarwin()) { - lib.addCSourceFiles(.{ .root = root, .files = &.{ - "src/unix/darwin-proctitle.c", - "src/unix/darwin.c", - "src/unix/fsevents.c", - } }); - } - - b.installArtifact(lib); -} diff --git a/deps/libuv/build.zig.zon b/deps/libuv/build.zig.zon @@ -1,12 +0,0 @@ -.{ - .name = "libuv", - .version = "1.51.0", - .paths = .{""}, - - .dependencies = .{ - .libuv = .{ - .url = "git+https://github.com/libuv/libuv?ref=v1.51.0#76fb3b73da3f8ddaeeb87d23fda04b9bda219f5e", - .hash = "N-V-__8AAExNRADXPh6GLMmWlqC2EVkp6hzH9wPuzjh_eSkE", - }, - }, -} diff --git a/deps/utf8proc/build.zig b/deps/utf8proc/build.zig @@ -21,7 +21,7 @@ pub fn build(b: *std.Build) !void { lib.addCSourceFiles(.{ .root = upstream.path(""), .files = &.{ "utf8proc.c", - } }); + }, .flags = &.{"-DUTF8PROC_STATIC"} }); b.installArtifact(lib); }