From ae2b3b1a6c8cbc90e28a9cab452d7ce06099d922 Mon Sep 17 00:00:00 2001 From: Tristan Ross Date: Thu, 20 Feb 2025 19:46:25 -0800 Subject: [PATCH] feat(libutil-c): add zig build --- src/libutil-c/build.zig | 88 +++++++++++++++++++++++++++++++++++ src/libutil-c/build.zig.zon | 10 ++++ src/libutil-c/meson.build | 78 ++++++------------------------- src/libutil-c/nix_api_util.cc | 1 + src/libutil-c/package.nix | 10 ++-- 5 files changed, 119 insertions(+), 68 deletions(-) create mode 100644 src/libutil-c/build.zig create mode 100644 src/libutil-c/build.zig.zon diff --git a/src/libutil-c/build.zig b/src/libutil-c/build.zig new file mode 100644 index 0000000000..678b7476a4 --- /dev/null +++ b/src/libutil-c/build.zig @@ -0,0 +1,88 @@ +const std = @import("std"); + +fn readFile(b: *std.Build, path: []const u8) []const u8 { + var file = b.build_root.handle.openFile(path, .{}) catch |err| std.debug.panic("Failed to open {s}: {}", .{ path, err }); + defer file.close(); + + const meta = file.metadata() catch |err| std.debug.panic("Failed to get metadata for {s}: {}", .{ path, err }); + + return file.readToEndAlloc(b.allocator, meta.size()) catch @panic("OOM"); +} + +pub fn build(b: *std.Build) void { + const optimize = b.standardOptimizeOption(.{}); + const target = b.standardTargetOptions(.{}); + const linkage = b.option(std.builtin.LinkMode, "linkage", "The link mode of binaries"); + const fsys_libutil = b.systemIntegrationOption("nix-util", .{}); + + const config = b.addConfigHeader(.{ + .include_path = "config-util.h", + }, .{ + .PACKAGE_VERSION_NIX = std.mem.trimRight(u8, readFile(b, ".version"), "\n"), + .PACKAGE_VERSION_ZIX = std.mem.trimRight(u8, readFile(b, ".zix-version"), "\n"), + }); + + const libutilc = std.Build.Step.Compile.create(b, .{ + .name = "nixutilc", + .kind = .lib, + .linkage = linkage, + .root_module = b.createModule(.{ + .target = target, + .optimize = optimize, + .link_libc = true, + .link_libcpp = true, + }), + }); + + libutilc.addConfigHeader(config); + + libutilc.addIncludePath(b.path(".")); + + libutilc.addCSourceFiles(.{ + .files = &.{ + "nix_api_util.cc", + }, + .flags = &.{ + "--std=c++2a", + }, + }); + + libutilc.installHeader(config.getOutput(), "nix/config-util.h"); + + if (fsys_libutil) { + libutilc.linkSystemLibrary("nix-util"); + } else { + const libutil = b.dependency("nix-util", .{ + .target = target, + .optimize = optimize, + .linkage = linkage orelse .static, + }); + + libutilc.linkLibrary(libutil.artifact("nixutil")); + } + + inline for (&.{ + "nix_api_util.h", + "nix_api_util_internal.h", + }) |hdr| { + libutilc.installHeader(b.path(hdr), "nix/" ++ hdr); + } + + b.installArtifact(libutilc); + + b.getInstallStep().dependOn(&b.addInstallFileWithDir(b.addWriteFile("nix-util-c.pc", b.fmt( + \\prefix={s} + \\libdir={s} + \\includedir={s} + \\ + \\Name: Nix + \\Description: Nix Package Manager + \\Version: 0.1.0 + \\Cflags: -I${{includedir}}/nix -std=c++2a + \\Libs: -L${{libdir}} -lnixutil -lnixutilc + , .{ + b.getInstallPath(.prefix, ""), + b.getInstallPath(.lib, ""), + b.getInstallPath(.header, ""), + })).getDirectory().path(b, "nix-util-c.pc"), .lib, "pkgconfig/nix-util-c.pc").step); +} diff --git a/src/libutil-c/build.zig.zon b/src/libutil-c/build.zig.zon new file mode 100644 index 0000000000..f59f2c5297 --- /dev/null +++ b/src/libutil-c/build.zig.zon @@ -0,0 +1,10 @@ +.{ + .name = "nix-util-c", + .version = "0.1.0", + .paths = .{"."}, + .dependencies = .{ + .@"nix-util" = .{ + .path = "../libutil", + }, + }, +} diff --git a/src/libutil-c/meson.build b/src/libutil-c/meson.build index 5e0b8fc345..df109669d6 100644 --- a/src/libutil-c/meson.build +++ b/src/libutil-c/meson.build @@ -1,7 +1,6 @@ -project('nix-util-c', 'cpp', +project('nix-util-c', version : files('.zix-version'), default_options : [ - 'cpp_std=c++2a', # TODO(Qyriad): increase the warning level 'warning_level=1', 'errorlogs=true', # Please print logs for tests that fail @@ -10,72 +9,21 @@ project('nix-util-c', 'cpp', license : 'LGPL-2.1-or-later', ) -fs = import('fs') -cxx = meson.get_compiler('cpp') +subdir('nix-meson-build-support/zig') -subdir('nix-meson-build-support/deps-lists') - -configdata = configuration_data() - -deps_private_maybe_subproject = [ - dependency('nix-util'), -] -deps_public_maybe_subproject = [ -] -subdir('nix-meson-build-support/subprojects') - -# TODO rename, because it will conflict with downstream projects -configdata.set_quoted('PACKAGE_VERSION_ZIX', meson.project_version()) -configdata.set_quoted('PACKAGE_VERSION_NIX', fs.read('.version').strip().split('\n')[0]) - -config_h = configure_file( - configuration : configdata, - output : 'config-util.h', -) - -add_project_arguments( - # TODO(Qyriad): Yes this is how the autoconf+Make system did it. - # It would be nice for our headers to be idempotent instead. - - # From C++ libraries, only for internals - '-include', 'config-util.hh', - - # From C libraries, for our public, installed headers too - '-include', 'config-util.h', - language : 'cpp', -) - -subdir('nix-meson-build-support/common') - -sources = files( - 'nix_api_util.cc', -) - -include_dirs = [include_directories('.')] - -headers = [config_h] + files( - 'nix_api_util.h', -) - -# TODO don't install this once tests don't use it. -headers += files('nix_api_util_internal.h') - -subdir('nix-meson-build-support/export-all-symbols') -subdir('nix-meson-build-support/windows-version') - -this_library = library( - 'nixutilc', - sources, - dependencies : deps_public + deps_private + deps_other, - include_directories : include_dirs, - link_args: linker_export_flags, - prelink : true, # For C++ static initializers - install : true, +zig_target = custom_target('zig build', + output: ['zig-out'], + command: [zig, 'build', zig_build_args, '--prefix', meson.current_build_dir() / 'zig-out', '--build-file', meson.project_source_root() / 'build.zig'], ) -install_headers(headers, subdir : 'nix', preserve_path : true) +include_dirs = ['zig-out' / 'include' / 'nix'] -libraries_private = [] +install_subdir(meson.current_build_dir() / 'zig-out' / 'lib', install_dir: get_option('libdir'), strip_directory: true) +install_subdir(meson.current_build_dir() / 'zig-out' / 'include', install_dir: get_option('includedir'), strip_directory: true) -subdir('nix-meson-build-support/export') +meson.override_dependency('nix-util-c', declare_dependency( + include_directories: include_dirs, + link_args: ['-L' + meson.current_build_dir() / 'zig-out' / 'lib', '-lnixutilc'], + sources: [zig_target], +)) diff --git a/src/libutil-c/nix_api_util.cc b/src/libutil-c/nix_api_util.cc index 9bb338cba8..b5cf166d90 100644 --- a/src/libutil-c/nix_api_util.cc +++ b/src/libutil-c/nix_api_util.cc @@ -1,5 +1,6 @@ #include "nix_api_util.h" #include "config-global.hh" +#include "config-util.h" #include "error.hh" #include "nix_api_util_internal.h" #include "util.hh" diff --git a/src/libutil-c/package.nix b/src/libutil-c/package.nix index 253881100f..1c3d83f104 100644 --- a/src/libutil-c/package.nix +++ b/src/libutil-c/package.nix @@ -1,6 +1,6 @@ { lib, - mkMesonLibrary, + mkZigLibrary, nix-util, @@ -14,12 +14,13 @@ let inherit (lib) fileset; in -mkMesonLibrary (finalAttrs: { +mkZigLibrary (finalAttrs: { pname = "zix-util-c"; inherit version nixVersion; workDir = ./.; fileset = fileset.unions [ + ../libutil ../../nix-meson-build-support ./nix-meson-build-support ../../.version @@ -31,13 +32,16 @@ mkMesonLibrary (finalAttrs: { (fileset.fileFilter (file: file.hasExt "cc") ./.) (fileset.fileFilter (file: file.hasExt "hh") ./.) (fileset.fileFilter (file: file.hasExt "h") ./.) + (fileset.fileFilter (file: file.hasExt "zig") ./.) + (fileset.fileFilter (file: file.hasExt "zon") ./.) ]; propagatedBuildInputs = [ nix-util ]; - mesonFlags = [ + zigBuildFlags = [ + "-fsys=nix-util" ]; meta = {