forked from lix-project/lix
build: build lix-doc with Meson! 🎉
lix-doc is now built with Meson, with lix-doc's dependencies built as
Meson subprojects, either fetched on demand with .wrap files, or fetched
in advance by Nix with importCargoLock. It even builds statically.
Fixes #256.
Co-authored-by: Lunaphied <lunaphied@lunaphied.me>
Co-authored-by: Jade Lovelace <lix@jade.fyi>
Change-Id: I3a4731ff13278e7117e0316bc0d7169e85f5eb0c
This commit is contained in:
parent
f1533160aa
commit
95863b258b
52
lix-doc/meson.build
Normal file
52
lix-doc/meson.build
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
# Until Meson 1.5¹, we can't just give Meson a Cargo.lock file and be done with it.
|
||||||
|
# Meson will *detect* what dependencies are needed from Cargo files; it just won't
|
||||||
|
# fetch them. The Meson 1.5 feature essentially internally translates Cargo.lock entries
|
||||||
|
# to .wrap files, and that translation is incredibly straightforward, so let's just
|
||||||
|
# use a simple Python script to generate the .wrap files ourselves while we wait for
|
||||||
|
# Meson 1.5. Weirdly, it seems Meson will only detect dependencies from other
|
||||||
|
# dependency() calls, so we have to specify lix-doc's two top-level dependencies,
|
||||||
|
# rnix and rowan, manually, and then their dependencies will be recursively translated
|
||||||
|
# into more dependency() calls.
|
||||||
|
#
|
||||||
|
# When Meson translates a Cargo dependency, the string passed to `dependency()` follows
|
||||||
|
# a fixed format, which is important as the .wrap files' basenames must match the string
|
||||||
|
# passed to `dependency()` exactly.
|
||||||
|
# In Meson 1.4, this format is `$packageName-rs`. Meson 1.5 changes this to
|
||||||
|
# `$packageName-$shortenedVersionString-rs`, because of course it does, but we'll cross
|
||||||
|
# that bridge when we get there...
|
||||||
|
#
|
||||||
|
# [1]: https://github.com/mesonbuild/meson/commit/9b8378985dbdc0112d11893dd42b33b7bc8d1e62
|
||||||
|
|
||||||
|
run_command(
|
||||||
|
python,
|
||||||
|
meson.project_source_root() / 'meson/cargo-lock-to-wraps.py',
|
||||||
|
meson.current_source_dir() / 'Cargo.lock',
|
||||||
|
meson.project_source_root() / 'subprojects',
|
||||||
|
check : true,
|
||||||
|
)
|
||||||
|
|
||||||
|
# The external crate rowan has an ambiguous pointer comparison warning, which
|
||||||
|
# we don't want to fail our whole build if werror is on.
|
||||||
|
subproject('rowan-rs', default_options : ['werror=false'])
|
||||||
|
|
||||||
|
rnix = dependency('rnix-rs')
|
||||||
|
rowan = dependency('rowan-rs')
|
||||||
|
|
||||||
|
lix_doc = static_library(
|
||||||
|
'lix_doc',
|
||||||
|
sources : files('src/lib.rs'),
|
||||||
|
rust_abi : 'c',
|
||||||
|
dependencies : [
|
||||||
|
rowan,
|
||||||
|
rnix,
|
||||||
|
],
|
||||||
|
# If an installed static library depends on this target, then Meson will force
|
||||||
|
# that to link with `-Wl,--whole-archive`, unless we also install this target.
|
||||||
|
# `-Wl,--whole-archive` can cause some Problems when linking multiple nested
|
||||||
|
# static libraries, so let's just install the damn thing.
|
||||||
|
install : true,
|
||||||
|
)
|
||||||
|
|
||||||
|
liblix_doc = declare_dependency(
|
||||||
|
link_with : lix_doc,
|
||||||
|
)
|
|
@ -1,8 +0,0 @@
|
||||||
{ rustPlatform, lib }:
|
|
||||||
|
|
||||||
rustPlatform.buildRustPackage {
|
|
||||||
name = "lix-doc";
|
|
||||||
|
|
||||||
cargoLock.lockFile = ./Cargo.lock;
|
|
||||||
src = lib.cleanSource ./.;
|
|
||||||
}
|
|
19
meson.build
19
meson.build
|
@ -30,6 +30,14 @@
|
||||||
# FIXME: This hack should be removed when https://git.lix.systems/lix-project/lix/issues/359
|
# FIXME: This hack should be removed when https://git.lix.systems/lix-project/lix/issues/359
|
||||||
# is fixed.
|
# is fixed.
|
||||||
#
|
#
|
||||||
|
# lix-doc is built with Meson in lix-doc/meson.build, and linked into libcmd in
|
||||||
|
# src/libcmd/meson.build. When building outside the Nix sandbox, Meson will use the .wrap
|
||||||
|
# files in subprojects/ to download and extract the dependency crates into subprojects/.
|
||||||
|
# When building inside the Nix sandbox, Lix's derivation in package.nix uses a
|
||||||
|
# fixed-output derivation to fetch those crates in advance instead, and then symlinks
|
||||||
|
# them into subprojects/ with the same names that Meson uses when downloading them
|
||||||
|
# itself -- perfect for --wrap-mode=nodownload, which mesonConfigurePhase uses.
|
||||||
|
#
|
||||||
# Unit tests are setup in tests/unit/meson.build, under the test suite "check".
|
# Unit tests are setup in tests/unit/meson.build, under the test suite "check".
|
||||||
#
|
#
|
||||||
# Functional tests are a bit more complicated. Generally they're defined in
|
# Functional tests are a bit more complicated. Generally they're defined in
|
||||||
|
@ -38,10 +46,11 @@
|
||||||
# be placed in specific directories' meson.build files to create the right directory tree
|
# be placed in specific directories' meson.build files to create the right directory tree
|
||||||
# in the build directory.
|
# in the build directory.
|
||||||
|
|
||||||
project('lix', 'cpp',
|
project('lix', 'cpp', 'rust',
|
||||||
version : run_command('bash', '-c', 'echo -n $(jq -r .version < ./version.json)$VERSION_SUFFIX', check : true).stdout().strip(),
|
version : run_command('bash', '-c', 'echo -n $(jq -r .version < ./version.json)$VERSION_SUFFIX', check : true).stdout().strip(),
|
||||||
default_options : [
|
default_options : [
|
||||||
'cpp_std=c++2a',
|
'cpp_std=c++2a',
|
||||||
|
'rust_std=2021',
|
||||||
# TODO(Qyriad): increase the warning level
|
# TODO(Qyriad): increase the warning level
|
||||||
'warning_level=1',
|
'warning_level=1',
|
||||||
'debug=true',
|
'debug=true',
|
||||||
|
@ -322,13 +331,6 @@ pegtl = dependency(
|
||||||
|
|
||||||
nlohmann_json = dependency('nlohmann_json', required : true, include_type : 'system')
|
nlohmann_json = dependency('nlohmann_json', required : true, include_type : 'system')
|
||||||
|
|
||||||
# lix-doc is a Rust project provided via buildInputs and unfortunately doesn't have any way to be detected.
|
|
||||||
# Just declare it manually to resolve this.
|
|
||||||
#
|
|
||||||
# FIXME: build this with meson in the future after we drop Make (with which we
|
|
||||||
# *absolutely* are not going to make it work)
|
|
||||||
lix_doc = declare_dependency(link_args : [ '-llix_doc' ])
|
|
||||||
|
|
||||||
if is_freebsd
|
if is_freebsd
|
||||||
libprocstat = declare_dependency(link_args : [ '-lprocstat' ])
|
libprocstat = declare_dependency(link_args : [ '-lprocstat' ])
|
||||||
endif
|
endif
|
||||||
|
@ -552,6 +554,7 @@ if is_darwin
|
||||||
)
|
)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
subdir('lix-doc')
|
||||||
subdir('src')
|
subdir('src')
|
||||||
subdir('scripts')
|
subdir('scripts')
|
||||||
subdir('misc')
|
subdir('misc')
|
||||||
|
|
43
meson/cargo-lock-to-wraps.py
Executable file
43
meson/cargo-lock-to-wraps.py
Executable file
|
@ -0,0 +1,43 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import tomllib
|
||||||
|
import sys
|
||||||
|
|
||||||
|
DOWNLOAD_URI_FORMAT = 'https://crates.io/api/v1/crates/{crate}/{version}/download'
|
||||||
|
|
||||||
|
WRAP_TEMPLATE = """
|
||||||
|
[wrap-file]
|
||||||
|
method = cargo
|
||||||
|
directory = {crate}-{version}
|
||||||
|
source_url = {url}
|
||||||
|
source_filename = {crate}-{version}.tar.gz
|
||||||
|
source_hash = {hash}
|
||||||
|
""".lstrip()
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('lockfile', help='path to the Cargo lockfile to generate wraps from')
|
||||||
|
parser.add_argument('outdir', help="the 'subprojects' directory to write .wrap files to")
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
with open(args.lockfile, 'rb') as f:
|
||||||
|
lock_toml = tomllib.load(f)
|
||||||
|
|
||||||
|
for dependency in lock_toml['package']:
|
||||||
|
try:
|
||||||
|
hash = dependency['checksum']
|
||||||
|
except KeyError:
|
||||||
|
# The base package, e.g. lix-doc, won't have a checksum, and conveniently
|
||||||
|
# the base package is also not something we want a wrap file for.
|
||||||
|
# Doesn't that work out nicely?
|
||||||
|
continue
|
||||||
|
|
||||||
|
crate = dependency['name']
|
||||||
|
version = dependency['version']
|
||||||
|
|
||||||
|
url = DOWNLOAD_URI_FORMAT.format(crate=crate, version=version)
|
||||||
|
|
||||||
|
wrap_text = WRAP_TEMPLATE.format(crate=crate, version=version, url=url, hash=hash)
|
||||||
|
with open(f'{args.outdir}/{crate}-rs.wrap', 'w') as f:
|
||||||
|
f.write(wrap_text)
|
|
@ -30,7 +30,14 @@ def process_compdb(compdb: list[dict]) -> list[dict]:
|
||||||
item['command'] = shlex.join(munch_command(shlex.split(item['command'])))
|
item['command'] = shlex.join(munch_command(shlex.split(item['command'])))
|
||||||
return item
|
return item
|
||||||
|
|
||||||
return [chomp(x) for x in compdb if not x['file'].endswith('precompiled-headers.hh')]
|
def cmdfilter(item: dict) -> bool:
|
||||||
|
file = item['file']
|
||||||
|
return (
|
||||||
|
not file.endswith('precompiled-headers.hh')
|
||||||
|
and not file.endswith('.rs')
|
||||||
|
)
|
||||||
|
|
||||||
|
return [chomp(x) for x in compdb if cmdfilter(x)]
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
|
22
package.nix
22
package.nix
|
@ -41,6 +41,8 @@
|
||||||
pkg-config,
|
pkg-config,
|
||||||
python3,
|
python3,
|
||||||
rapidcheck,
|
rapidcheck,
|
||||||
|
rustPlatform,
|
||||||
|
rustc,
|
||||||
sqlite,
|
sqlite,
|
||||||
toml11,
|
toml11,
|
||||||
util-linuxMinimal ? utillinuxMinimal,
|
util-linuxMinimal ? utillinuxMinimal,
|
||||||
|
@ -49,9 +51,6 @@
|
||||||
|
|
||||||
busybox-sandbox-shell,
|
busybox-sandbox-shell,
|
||||||
|
|
||||||
# internal fork of nix-doc providing :doc in the repl
|
|
||||||
lix-doc ? __forDefaults.lix-doc,
|
|
||||||
|
|
||||||
pname ? "lix",
|
pname ? "lix",
|
||||||
versionSuffix ? "",
|
versionSuffix ? "",
|
||||||
officialRelease ? __forDefaults.versionJson.official_release,
|
officialRelease ? __forDefaults.versionJson.official_release,
|
||||||
|
@ -83,7 +82,6 @@
|
||||||
configureFlags = prev.configureFlags or [ ] ++ [ (lib.enableFeature true "sigstop") ];
|
configureFlags = prev.configureFlags or [ ] ++ [ (lib.enableFeature true "sigstop") ];
|
||||||
});
|
});
|
||||||
|
|
||||||
lix-doc = callPackage ./lix-doc/package.nix { };
|
|
||||||
build-release-notes = callPackage ./maintainers/build-release-notes.nix { };
|
build-release-notes = callPackage ./maintainers/build-release-notes.nix { };
|
||||||
},
|
},
|
||||||
}:
|
}:
|
||||||
|
@ -137,6 +135,7 @@ let
|
||||||
./meson.build
|
./meson.build
|
||||||
./meson.options
|
./meson.options
|
||||||
./meson
|
./meson
|
||||||
|
./lix-doc
|
||||||
./scripts/meson.build
|
./scripts/meson.build
|
||||||
./subprojects
|
./subprojects
|
||||||
]);
|
]);
|
||||||
|
@ -219,6 +218,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||||
meson
|
meson
|
||||||
ninja
|
ninja
|
||||||
cmake
|
cmake
|
||||||
|
rustc
|
||||||
]
|
]
|
||||||
++ [
|
++ [
|
||||||
(lib.getBin lowdown)
|
(lib.getBin lowdown)
|
||||||
|
@ -258,7 +258,6 @@ stdenv.mkDerivation (finalAttrs: {
|
||||||
lowdown
|
lowdown
|
||||||
libsodium
|
libsodium
|
||||||
toml11
|
toml11
|
||||||
lix-doc
|
|
||||||
pegtl
|
pegtl
|
||||||
]
|
]
|
||||||
++ lib.optionals hostPlatform.isLinux [
|
++ lib.optionals hostPlatform.isLinux [
|
||||||
|
@ -290,6 +289,8 @@ stdenv.mkDerivation (finalAttrs: {
|
||||||
BOOST_LIBRARYDIR = "${lib.getLib boost}/lib";
|
BOOST_LIBRARYDIR = "${lib.getLib boost}/lib";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
cargoDeps = rustPlatform.importCargoLock { lockFile = ./lix-doc/Cargo.lock; };
|
||||||
|
|
||||||
preConfigure =
|
preConfigure =
|
||||||
lib.optionalString (!finalAttrs.dontBuild && !hostPlatform.isStatic) ''
|
lib.optionalString (!finalAttrs.dontBuild && !hostPlatform.isStatic) ''
|
||||||
# Copy libboost_context so we don't get all of Boost in our closure.
|
# Copy libboost_context so we don't get all of Boost in our closure.
|
||||||
|
@ -311,6 +312,17 @@ stdenv.mkDerivation (finalAttrs: {
|
||||||
install_name_tool -change ${boost}/lib/libboost_system.dylib $out/lib/libboost_system.dylib $out/lib/libboost_thread.dylib
|
install_name_tool -change ${boost}/lib/libboost_system.dylib $out/lib/libboost_system.dylib $out/lib/libboost_thread.dylib
|
||||||
''
|
''
|
||||||
+ ''
|
+ ''
|
||||||
|
# Copy the Cargo dependencies to where Meson expects them to be, so we
|
||||||
|
# can seamlessly use Meson's subproject wraps, but just do the download
|
||||||
|
# ahead of time. Luckily for us, importCargoLock-downloaded crates use
|
||||||
|
# the exact naming scheme Meson expects!
|
||||||
|
# The directory from importCargoLock does contain a lockfile, which we
|
||||||
|
# don't need, but all the crate directories start with a word character,
|
||||||
|
# then have a hyphen, and then a sequence of digits or periods for the
|
||||||
|
# version.
|
||||||
|
find "$cargoDeps" -type l -regex '.*/\w.+-[0-9.]+$' -exec \
|
||||||
|
ln -sv "{}" "$PWD/subprojects/" ";"
|
||||||
|
|
||||||
# Fix up /usr/bin/env shebangs relied on by the build
|
# Fix up /usr/bin/env shebangs relied on by the build
|
||||||
patchShebangs --build tests/ doc/manual/
|
patchShebangs --build tests/ doc/manual/
|
||||||
'';
|
'';
|
||||||
|
|
|
@ -50,7 +50,7 @@ libcmd = library(
|
||||||
editline,
|
editline,
|
||||||
lowdown,
|
lowdown,
|
||||||
nlohmann_json,
|
nlohmann_json,
|
||||||
lix_doc
|
liblix_doc,
|
||||||
],
|
],
|
||||||
cpp_pch : cpp_pch,
|
cpp_pch : cpp_pch,
|
||||||
install : true,
|
install : true,
|
||||||
|
|
2
subprojects/.gitignore
vendored
Normal file
2
subprojects/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
# Downloaded wrapped Rust projects
|
||||||
|
*-*.*.*
|
6
subprojects/autocfg-rs.wrap
Normal file
6
subprojects/autocfg-rs.wrap
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[wrap-file]
|
||||||
|
method = cargo
|
||||||
|
directory = autocfg-1.1.0
|
||||||
|
source_url = https://crates.io/api/v1/crates/autocfg/1.1.0/download
|
||||||
|
source_filename = autocfg-1.1.0.tar.gz
|
||||||
|
source_hash = d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa
|
6
subprojects/countme-rs.wrap
Normal file
6
subprojects/countme-rs.wrap
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[wrap-file]
|
||||||
|
method = cargo
|
||||||
|
directory = countme-3.0.1
|
||||||
|
source_url = https://crates.io/api/v1/crates/countme/3.0.1/download
|
||||||
|
source_filename = countme-3.0.1.tar.gz
|
||||||
|
source_hash = 7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636
|
6
subprojects/dissimilar-rs.wrap
Normal file
6
subprojects/dissimilar-rs.wrap
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[wrap-file]
|
||||||
|
method = cargo
|
||||||
|
directory = dissimilar-1.0.7
|
||||||
|
source_url = https://crates.io/api/v1/crates/dissimilar/1.0.7/download
|
||||||
|
source_filename = dissimilar-1.0.7.tar.gz
|
||||||
|
source_hash = 86e3bdc80eee6e16b2b6b0f87fbc98c04bee3455e35174c0de1a125d0688c632
|
6
subprojects/expect-test-rs.wrap
Normal file
6
subprojects/expect-test-rs.wrap
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[wrap-file]
|
||||||
|
method = cargo
|
||||||
|
directory = expect-test-1.4.1
|
||||||
|
source_url = https://crates.io/api/v1/crates/expect-test/1.4.1/download
|
||||||
|
source_filename = expect-test-1.4.1.tar.gz
|
||||||
|
source_hash = 30d9eafeadd538e68fb28016364c9732d78e420b9ff8853fa5e4058861e9f8d3
|
6
subprojects/hashbrown-rs.wrap
Normal file
6
subprojects/hashbrown-rs.wrap
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[wrap-file]
|
||||||
|
method = cargo
|
||||||
|
directory = hashbrown-0.14.5
|
||||||
|
source_url = https://crates.io/api/v1/crates/hashbrown/0.14.5/download
|
||||||
|
source_filename = hashbrown-0.14.5.tar.gz
|
||||||
|
source_hash = e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1
|
6
subprojects/memoffset-rs.wrap
Normal file
6
subprojects/memoffset-rs.wrap
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[wrap-file]
|
||||||
|
method = cargo
|
||||||
|
directory = memoffset-0.9.1
|
||||||
|
source_url = https://crates.io/api/v1/crates/memoffset/0.9.1/download
|
||||||
|
source_filename = memoffset-0.9.1.tar.gz
|
||||||
|
source_hash = 488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a
|
6
subprojects/once_cell-rs.wrap
Normal file
6
subprojects/once_cell-rs.wrap
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[wrap-file]
|
||||||
|
method = cargo
|
||||||
|
directory = once_cell-1.19.0
|
||||||
|
source_url = https://crates.io/api/v1/crates/once_cell/1.19.0/download
|
||||||
|
source_filename = once_cell-1.19.0.tar.gz
|
||||||
|
source_hash = 3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92
|
6
subprojects/rnix-rs.wrap
Normal file
6
subprojects/rnix-rs.wrap
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[wrap-file]
|
||||||
|
method = cargo
|
||||||
|
directory = rnix-0.11.0
|
||||||
|
source_url = https://crates.io/api/v1/crates/rnix/0.11.0/download
|
||||||
|
source_filename = rnix-0.11.0.tar.gz
|
||||||
|
source_hash = bb35cedbeb70e0ccabef2a31bcff0aebd114f19566086300b8f42c725fc2cb5f
|
6
subprojects/rowan-rs.wrap
Normal file
6
subprojects/rowan-rs.wrap
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[wrap-file]
|
||||||
|
method = cargo
|
||||||
|
directory = rowan-0.15.15
|
||||||
|
source_url = https://crates.io/api/v1/crates/rowan/0.15.15/download
|
||||||
|
source_filename = rowan-0.15.15.tar.gz
|
||||||
|
source_hash = 32a58fa8a7ccff2aec4f39cc45bf5f985cec7125ab271cf681c279fd00192b49
|
6
subprojects/rustc-hash-rs.wrap
Normal file
6
subprojects/rustc-hash-rs.wrap
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[wrap-file]
|
||||||
|
method = cargo
|
||||||
|
directory = rustc-hash-1.1.0
|
||||||
|
source_url = https://crates.io/api/v1/crates/rustc-hash/1.1.0/download
|
||||||
|
source_filename = rustc-hash-1.1.0.tar.gz
|
||||||
|
source_hash = 08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2
|
6
subprojects/text-size-rs.wrap
Normal file
6
subprojects/text-size-rs.wrap
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
[wrap-file]
|
||||||
|
method = cargo
|
||||||
|
directory = text-size-1.1.1
|
||||||
|
source_url = https://crates.io/api/v1/crates/text-size/1.1.1/download
|
||||||
|
source_filename = text-size-1.1.1.tar.gz
|
||||||
|
source_hash = f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233
|
Loading…
Reference in a new issue