Merge pull request #38546 from dchinmay2/push-pozrrzptmvnv

build(zig): add formatc and lintc steps
This commit is contained in:
bfredl
2026-07-10 11:18:43 +02:00
committed by GitHub
8 changed files with 219 additions and 14 deletions

View File

@@ -28,6 +28,7 @@ Checks: >
-cert-err34-c,
-concurrency-mt-unsafe,
-cppcoreguidelines-narrowing-conversions,
-clang-diagnostic-unused-command-line-argument,
Warnings that may be useful, but are too inconsistent to enable by default
May yield useful results with some manual triaging,

View File

@@ -1,5 +1,3 @@
CompileFlags:
CompilationDatabase: build/ # Search build/ directory for compile_commands.json
Diagnostics:
UnusedIncludes: None
Documentation:

View File

@@ -30,6 +30,40 @@ env:
# TEST_FILTER: foo
jobs:
lintc:
runs-on: ubuntu-24.04
timeout-minutes: 20
env:
NVIM_LOG_FILE: ${{ github.workspace }}/zig-out/nvim.log
OPTS: -Doptimize=ReleaseFast -Dci-build
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- uses: ./.github/actions/setup
- uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2.2.1
with:
version: 0.16.0
- run: sudo apt-get install -y inotify-tools
- name: nvim_bin
id: nvim_bin
run: zig build nvim_bin $OPTS
- if: success() || failure() && steps.nvim_bin.outcome == 'success'
name: clint.lua
run: zig build lintc-clint $OPTS
- if: success() || failure() && steps.nvim_bin.outcome == 'success'
name: clang-tidy
run: zig build lintc-clang-tidy $OPTS
- if: success() || failure() && steps.nvim_bin.outcome == 'success'
name: uncrustify
run: zig build lintc-uncrustify $OPTS
lint:
runs-on: ubuntu-24.04-arm
timeout-minutes: 10
@@ -82,18 +116,6 @@ jobs:
name: lintquery
run: cmake --build build --target lintquery
- if: success() || failure() && steps.abort_job.outputs.status == 'success'
name: clint.lua
run: cmake --build build --target lintc-clint
- if: success() || failure() && steps.abort_job.outputs.status == 'success'
name: clang-tidy
run: cmake --build build --target lintc-clang-tidy
- if: success() || failure() && steps.abort_job.outputs.status == 'success'
name: uncrustify
run: cmake --build build --target lintc-uncrustify
clang-analyzer:
runs-on: ubuntu-24.04-arm
timeout-minutes: 20

View File

@@ -140,6 +140,8 @@ Some can be auto-bumped by `scripts/bump_deps.lua`.
* (Deprecated) [unibilium](https://github.com/neovim/unibilium)
* The original project [was abandoned](https://github.com/neovim/neovim/issues/10302), so the [neovim/unibilium](https://github.com/neovim/unibilium) fork is considered "upstream" and is maintained on the `master` branch.
* **Note:** unibilium is NOT required. See [BUILD.md](./BUILD.md#build-without-unibilium) to build Nvim without unibilium.
* [uncrustify](https://github.com/uncrustify/uncrustify)
* Requires a PR to update the update the [Zig build files](https://github.com/neovim/neovim/tree/master/deps/uncrustify) first.
### Vendored dependencies

View File

@@ -5,6 +5,8 @@ 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 zcc = @import("compile_commands");
const lint = @import("src/lint.zig");
const version = struct {
const major = 0;
@@ -103,6 +105,7 @@ pub fn build(b: *std.Build) !void {
.utf8proc = b.systemIntegrationOption("utf8proc", .{}),
.uv = b.systemIntegrationOption("uv", .{}),
};
const ci_build = b.option(bool, "ci-build", "CI build") orelse false;
const ziglua = b.dependency("zlua", .{
.target = target,
@@ -756,6 +759,16 @@ pub fn build(b: *std.Build) !void {
test_config_step.getDirectory(),
unit_headers,
);
// compile_commands.json
var cdb_targets: std.ArrayListUnmanaged(*std.Build.Step.Compile) = try .initCapacity(b.allocator, 0);
try cdb_targets.append(b.allocator, nvim_exe);
try cdb_targets.append(b.allocator, tee_exe);
try cdb_targets.append(b.allocator, xxd_exe);
const cdb_step = zcc.createStep(b, "cdb", cdb_targets.items);
for (cdb_targets.items) |ct| cdb_step.dependOn(&ct.step);
try lint.addSteps(b, target, cdb_step, nvim_exe_install, nvim_sources, nvim_headers, ci_build);
}
pub fn test_fixture(

View File

@@ -36,6 +36,10 @@
},
.utf8proc = .{ .path = "./deps/utf8proc/", .lazy = true },
.unibilium = .{ .path = "./deps/unibilium/", .lazy = true },
.uncrustify = .{
.url = "git+https://codeberg.org/allyourcodebase/uncrustify#2cdf880e4ffbe438a7946368cd45fca2df9f0f7a",
.hash = "uncrustify-0.83.0-qkVd7cVCAADAg1kS3ctVBhY2gkxEIs-W8wgurLadbgC-",
},
.libiconv = .{
.url = "git+https://github.com/allyourcodebase/libiconv#9def4c8a1743380e85bcedb80f2c15b455e236f3",
.hash = "libiconv-1.18.0-p9sJwWnqAACzVYeWgXB5r5lOQ74XwTPlptixV0JPRO28",
@@ -65,6 +69,10 @@
.url = "git+https://github.com/tree-sitter-grammars/tree-sitter-query?ref=v0.8.0#a225e21d81201be77da58de614e2b7851735677a",
.hash = "N-V-__8AAMR5AwAzZ5_8S2p2COTEf5usBeeT4ORzh-lBGkWy",
},
.compile_commands = .{
.url = "https://github.com/the-argus/zig-compile-commands/archive/9400cd1963ea6bb58fe47ba7d9700075b808cdd2.tar.gz",
.hash = "zig_compile_commands-0.0.1-OZg5-e_JAAAGg1WHAePtq4l4Uvjs34BexnFFCZk63EaG",
},
},
.paths = .{
// TODO(bfredl): explicitly list the subdirs which actually are used

View File

@@ -23,6 +23,7 @@ pub fn build_nlua0(
.optimize = optimize,
.link_libc = true,
}),
.use_llvm = true,
});
const nlua0_mod = nlua0_exe.root_module;

160
src/lint.zig Normal file
View File

@@ -0,0 +1,160 @@
const std = @import("std");
const gen = @import("gen/gen_steps.zig");
pub fn lintSources(
b: *std.Build,
nvim_sources: std.ArrayList(gen.SourceItem),
nvim_headers: std.ArrayList([]u8),
) !std.ArrayList([]const u8) {
var lint_sources: std.ArrayList([]const u8) = try .initCapacity(b.allocator, 0);
for (nvim_sources.items) |source| {
try lint_sources.append(b.allocator, b.fmt("src/nvim/{s}", .{source.name}));
}
for (nvim_headers.items) |header| {
try lint_sources.append(b.allocator, b.fmt("src/nvim/{s}", .{header}));
}
try lint_sources.append(b.allocator, "src/tee/tee.c");
try lint_sources.append(b.allocator, "src/xxd/xxd.c");
return lint_sources;
}
pub fn addSteps(
b: *std.Build,
target: std.Build.ResolvedTarget,
cdb_step: *std.Build.Step,
nvim_exe_install: *std.Build.Step.InstallArtifact,
nvim_sources: std.ArrayList(gen.SourceItem),
nvim_headers: std.ArrayList([]u8),
ci_build: bool,
) !void {
const lintc = b.step("lintc", "Lint C source");
var lint_sources = try lintSources(b, nvim_sources, nvim_headers);
defer lint_sources.deinit(b.allocator);
const lintc_uncrustify = addLintcUncrustifyStep(b, lint_sources);
lintc.dependOn(lintc_uncrustify);
const lintc_clint = addLintcClintStep(b, nvim_exe_install, lint_sources, ci_build);
lintc.dependOn(lintc_clint);
const lintc_clang_tidy = try addLintcClangtidyStep(b, cdb_step, nvim_exe_install, target, lint_sources);
lintc.dependOn(lintc_clang_tidy);
try addFormatcStep(b, lint_sources);
}
fn addLintcUncrustifyStep(
b: *std.Build,
lint_sources: std.ArrayList([]const u8),
) *std.Build.Step {
const lintc_uncrustify = b.step("lintc-uncrustify", "Check formatting of C source with uncrustify");
const uncrustify = b.dependency("uncrustify", .{
.target = b.graph.host,
.optimize = .ReleaseFast,
});
const uncrustify_exe = uncrustify.artifact("uncrustify");
for (lint_sources.items) |file| {
const run = b.addRunArtifact(uncrustify_exe);
run.addArgs(&.{ "-c", "src/uncrustify.cfg", "-q", "--check" });
run.addFileArg(b.path(file));
run.expectExitCode(0);
lintc_uncrustify.dependOn(&run.step);
}
return lintc_uncrustify;
}
fn addLintcClangtidyStep(
b: *std.Build,
cdb_step: *std.Build.Step,
nvim_exe_install: *std.Build.Step.InstallArtifact,
target: std.Build.ResolvedTarget,
lint_sources: std.ArrayList([]const u8),
) !*std.Build.Step {
const lintc_clang_tidy = b.step("lintc-clang-tidy", "Lint C source with clang-tidy");
var exclusions: std.ArrayList([]const u8) = try .initCapacity(b.allocator, 0);
defer exclusions.deinit(b.allocator);
try exclusions.appendSlice(b.allocator, &.{
"src/nvim/eval/typval_encode.c.h",
"src/nvim/api/ui_events.in.h",
"src/xxd/xxd.c",
});
if (target.result.os.tag == .windows) {
try exclusions.appendSlice(b.allocator, &.{
"src/nvim/os/pty_proc_unix.h",
"src/nvim/os/unix_defs.h",
});
} else {
try exclusions.appendSlice(b.allocator, &.{
"src/nvim/os/win_defs.h",
"src/nvim/os/pty_proc_win.h",
"src/nvim/os/pty_conpty_win.h",
"src/nvim/os/os_win_console.h",
});
}
outer: for (lint_sources.items) |file| {
for (exclusions.items) |exclusion| {
if (std.mem.eql(u8, exclusion, file)) continue :outer;
}
const run = b.addSystemCommand(&.{"clang-tidy"});
run.step.dependOn(cdb_step);
run.step.dependOn(&nvim_exe_install.step);
run.addFileArg(b.path(file));
run.addArg("--quiet");
run.expectStdOutEqual("");
lintc_clang_tidy.dependOn(&run.step);
}
return lintc_clang_tidy;
}
fn addLintcClintStep(
b: *std.Build,
// use InstallArtifact instead of nvim_exe so that cache is not busted
// for every file to be linted
nvim_exe_install: *std.Build.Step.InstallArtifact,
lint_sources: std.ArrayList([]const u8),
ci_build: bool,
) *std.Build.Step {
const lintc_clint = b.step("lintc-clint", "Lint C source with clint");
const exclusions = [_][]const u8{ "src/nvim/tui/terminfo_defs.h", "src/xxd/xxd.c" };
const nvim_path = b.getInstallPath(.bin, nvim_exe_install.artifact.out_filename);
outer: for (lint_sources.items) |file| {
for (exclusions) |exclusion| {
if (std.mem.endsWith(u8, file, exclusion)) continue :outer;
}
const run = b.addSystemCommand(&.{nvim_path});
run.step.dependOn(&nvim_exe_install.step);
run.addArgs(&.{ "-u", "NONE", "-l" });
run.addFileArg(b.path("src/clint.lua"));
if (ci_build) {
run.addArg("--output=gh_action");
} else {
run.addArg("--output=vs7");
}
run.addFileArg(b.path(file));
run.expectStdOutEqual("");
lintc_clint.dependOn(&run.step);
}
return lintc_clint;
}
fn addFormatcStep(
b: *std.Build,
lint_sources: std.ArrayList([]const u8),
) !void {
const formatc = b.step("formatc", "Format C source with uncrustify");
const uncrustify = b.dependency("uncrustify", .{
.target = b.graph.host,
.optimize = .ReleaseFast,
});
const uncrustify_exe = uncrustify.artifact("uncrustify");
const update = b.addUpdateSourceFiles();
for (lint_sources.items) |file| {
const run = b.addRunArtifact(uncrustify_exe);
run.addArgs(&.{ "-c", "src/uncrustify.cfg", "-f" });
run.addFileArg(b.path(file));
run.addArg("-o");
const output_name = try std.mem.replaceOwned(u8, b.allocator, file, "/", "-");
const output = run.addOutputFileArg(output_name);
update.addCopyFileToSource(output, file);
}
formatc.dependOn(&update.step);
}