Document the nix-util Meson build system more extensively

I hope this will make it easier to maintain, and also make it easier for
others to assist with porting the rest of the build system to Meson.

Co-authored-by: Robert Hensing <roberth@users.noreply.github.com>
This commit is contained in:
John Ericson 2024-06-13 10:50:15 -04:00
parent afdd12be5e
commit 56f0b5304f
4 changed files with 71 additions and 23 deletions

View file

@ -243,6 +243,7 @@
changelog-d; changelog-d;
default = self.packages.${system}.nix; default = self.packages.${system}.nix;
} // lib.concatMapAttrs } // lib.concatMapAttrs
# We need to "flatten" packages we care about to pass `flake check`.
(pkgName: {}: { (pkgName: {}: {
"${pkgName}" = nixpkgsFor.${system}.native.${pkgName}; "${pkgName}" = nixpkgsFor.${system}.native.${pkgName};
"${pkgName}-static" = nixpkgsFor.${system}.static.${pkgName}; "${pkgName}-static" = nixpkgsFor.${system}.static.${pkgName};

View file

@ -1,5 +1,5 @@
project('nix-util', 'cpp', project('nix-util', 'cpp',
version : run_command('cat', './.version', check : true).stdout().strip(), version : files('.version'),
default_options : [ default_options : [
'cpp_std=c++2a', 'cpp_std=c++2a',
# TODO(Qyriad): increase the warning level # TODO(Qyriad): increase the warning level
@ -8,25 +8,61 @@ project('nix-util', 'cpp',
'optimization=2', 'optimization=2',
'errorlogs=true', # Please print logs for tests that fail 'errorlogs=true', # Please print logs for tests that fail
], ],
meson_version : '>= 0.64.0', meson_version : '>= 1.1',
license : 'LGPL-2.1-or-later', license : 'LGPL-2.1-or-later',
) )
cxx = meson.get_compiler('cpp') cxx = meson.get_compiler('cpp')
# These are private dependencies with pkg-config files. What private
# means is that the dependencies are used by the library but they are
# *not* used (e.g. `#include`-ed) in any installed header file, and only
# in regular source code (`*.cc`) or private, uninstalled headers. They
# are thus part of the *implementation* of the library, but not its
# *interface*.
#
# See `man pkg-config` for some details.
deps_private = [ ] deps_private = [ ]
# These are public dependencies with pkg-config files. Public is the
# opposite of private: these dependencies are used in installed header
# files. They are part of the interface (and implementation) of the
# library.
#
# N.B. This concept is mostly unrelated to our own concept of a public
# (stable) API, for consumption outside of the Nix repository.
# `libnixutil` is an unstable C++ library, whose public interface is
# likewise unstable. `libutilc` conversely is a hopefully-soon stable
# C library, whose public interface --- including public but not private
# dependencies --- will also likewise soon be stable.
#
# N.B. For distributions that care about "ABI" stablity and not just
# "API" stability, the private dependencies also matter as they can
# potentially affect the public ABI.
deps_public = [ ] deps_public = [ ]
# These are dependencencies without pkg-config files. Ideally they are
# just private, but they may also be public (e.g. boost).
deps_other = [ ] deps_other = [ ]
configdata = configuration_data() configdata = configuration_data()
# Check for each of these functions, and create a define like `#define HAVE_LUTIMES 1`. # Check for each of these functions, and create a define like `#define
# HAVE_LUTIMES 1`. The `#define` is unconditional, 0 for not found and 1
# for found. One therefore uses it with `#if` not `#ifdef`.
check_funcs = [ check_funcs = [
# Optionally used for changing the mtime of symlinks. # Optionally used for changing the mtime of symlinks.
'lutimes', 'lutimes',
# Optionally used for creating pipes on Unix
'pipe2', 'pipe2',
# Optionally used to preallocate files to be large enough before
# writing to them.
'posix_fallocate', 'posix_fallocate',
# Optionally used to get more information about processes failing due
# to a signal on Unix.
'strsignal', 'strsignal',
# Optionally used to try to close more file descriptors (e.g. before
# forking) on Unix.
'sysconf', 'sysconf',
] ]
foreach funcspec : check_funcs foreach funcspec : check_funcs
@ -35,8 +71,10 @@ foreach funcspec : check_funcs
configdata.set(define_name, define_value) configdata.set(define_name, define_value)
endforeach endforeach
# Conditional to work around https://github.com/mesonbuild/meson/issues/13293 # This is only conditional to work around
if host_machine.system() != 'windows' and cxx.get_id() == 'gcc' # https://github.com/mesonbuild/meson/issues/13293. It should be
# unconditional.
if not (host_machine.system() == 'windows' and cxx.get_id() == 'gcc')
deps_private += dependency('threads') deps_private += dependency('threads')
endif endif
@ -53,7 +91,8 @@ boost = dependency(
'boost', 'boost',
modules : ['context', 'coroutine'], modules : ['context', 'coroutine'],
) )
# Actually public, but wrong type of dep for pkg config # boost is a public dependency, but not a pkg-config dependency unfortunately, so we
# put in `deps_other`.
deps_other += boost deps_other += boost
openssl = dependency( openssl = dependency(
@ -80,8 +119,10 @@ brotli = [
] ]
deps_private += brotli deps_private += brotli
# cpuid only makes sense on x86_64 cpuid_required = get_option('cpuid')
cpuid_required = host_machine.cpu_family() == 'x86_64' ? get_option('cpuid') : false if host_machine.cpu_family() != 'x86_64' and cpuid_required.enabled()
warning('Force-enabling seccomp on non-x86_64 does not make sense')
endif
cpuid = dependency('libcpuid', 'cpuid', required : cpuid_required) cpuid = dependency('libcpuid', 'cpuid', required : cpuid_required)
configdata.set('HAVE_LIBCPUID', cpuid.found().to_int()) configdata.set('HAVE_LIBCPUID', cpuid.found().to_int())
deps_private += cpuid deps_private += cpuid
@ -89,7 +130,7 @@ deps_private += cpuid
nlohmann_json = dependency('nlohmann_json', version : '>= 3.9') nlohmann_json = dependency('nlohmann_json', version : '>= 3.9')
deps_public += nlohmann_json deps_public += nlohmann_json
config_util_h = configure_file( config_h = configure_file(
configuration : configdata, configuration : configdata,
output : 'config-util.h', output : 'config-util.h',
) )
@ -157,7 +198,7 @@ sources = files(
include_dirs = [include_directories('.')] include_dirs = [include_directories('.')]
headers = [config_util_h] + files( headers = [config_h] + files(
'abstract-setting-to-json.hh', 'abstract-setting-to-json.hh',
'ansicolor.hh', 'ansicolor.hh',
'archive.hh', 'archive.hh',
@ -248,7 +289,7 @@ else
linker_export_flags = [] linker_export_flags = []
endif endif
libutil = library( this_library = library(
'nixutil', 'nixutil',
sources, sources,
dependencies : deps_public + deps_private + deps_other, dependencies : deps_public + deps_private + deps_other,
@ -259,6 +300,11 @@ libutil = library(
install_headers(headers, subdir : 'nix', preserve_path : true) install_headers(headers, subdir : 'nix', preserve_path : true)
# Part of how we copy boost libraries to a separate installation to
# reduce closure size. These libraries will be copied to our `$out/bin`,
# and these `-l` flags will pick them up there.
#
# https://github.com/NixOS/nixpkgs/issues/45462
libraries_private = ['-lboost_context', '-lboost_coroutine'] libraries_private = ['-lboost_context', '-lboost_coroutine']
if host_machine.system() == 'windows' if host_machine.system() == 'windows'
# `libraries_private` cannot contain ad-hoc dependencies (from # `libraries_private` cannot contain ad-hoc dependencies (from
@ -267,22 +313,20 @@ if host_machine.system() == 'windows'
endif endif
import('pkgconfig').generate( import('pkgconfig').generate(
libutil, this_library,
filebase : 'nix-util', filebase : meson.project_name(),
name : 'Nix', name : 'Nix',
description : 'Nix Package Manager', description : 'Nix Package Manager',
subdirs : ['nix'], subdirs : ['nix'],
extra_cflags : ['-std=c++2a'], extra_cflags : ['-std=c++2a'],
requires : deps_public, requires : deps_public,
requires_private : deps_private, requires_private : deps_private,
# avoid absolute paths, use vendored ones
libraries_private : libraries_private, libraries_private : libraries_private,
) )
nix_util = declare_dependency( meson.override_dependency(meson.project_name(), declare_dependency(
include_directories : include_dirs, include_directories : include_dirs,
link_with : libutil, link_with : this_library,
compile_args : ['-std=c++2a'], compile_args : ['-std=c++2a'],
dependencies : [], dependencies : [],
) ))
meson.override_dependency('nix-util', nix_util)

View file

@ -83,9 +83,8 @@ mkDerivation (finalAttrs: {
'' ''
echo ${version} > .version echo ${version} > .version
'' ''
# Copy libboost_context so we don't get all of Boost in our closure. # Copy some boost libraries so we don't get all of Boost in our
# closure. https://github.com/NixOS/nixpkgs/issues/45462
# https://github.com/NixOS/nixpkgs/issues/45462
+ lib.optionalString (!stdenv.hostPlatform.isStatic) ('' + lib.optionalString (!stdenv.hostPlatform.isStatic) (''
mkdir -p $out/lib mkdir -p $out/lib
cp -pd ${boost}/lib/{libboost_context*,libboost_thread*,libboost_system*} $out/lib cp -pd ${boost}/lib/{libboost_context*,libboost_thread*,libboost_system*} $out/lib
@ -115,7 +114,9 @@ mkDerivation (finalAttrs: {
enableParallelBuilding = true; enableParallelBuilding = true;
postInstall = postInstall =
# Remove absolute path to boost libs # Remove absolute path to boost libs that ends up in `Libs.private`
# by default, and would clash with out `disallowedReferences`. Part
# of the https://github.com/NixOS/nixpkgs/issues/45462 workaround.
'' ''
sed -i "$out/lib/pkgconfig/nix-util.pc" -e 's, ${lib.getLib boost}[^ ]*,,g' sed -i "$out/lib/pkgconfig/nix-util.pc" -e 's, ${lib.getLib boost}[^ ]*,,g'
'' ''

View file

@ -139,7 +139,9 @@ void closeMostFDs(const std::set<int> & exceptions)
#endif #endif
int maxFD = 0; int maxFD = 0;
#if HAVE_SYSCONF
maxFD = sysconf(_SC_OPEN_MAX); maxFD = sysconf(_SC_OPEN_MAX);
#endif
for (int fd = 0; fd < maxFD; ++fd) for (int fd = 0; fd < maxFD; ++fd)
if (!exceptions.count(fd)) if (!exceptions.count(fd))
close(fd); /* ignore result */ close(fd); /* ignore result */