aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lix-doc/meson.build52
-rw-r--r--lix-doc/package.nix8
-rw-r--r--meson.build19
-rwxr-xr-xmeson/cargo-lock-to-wraps.py43
-rwxr-xr-xmeson/clang-tidy/clean_compdb.py9
-rw-r--r--package.nix22
-rw-r--r--src/libcmd/meson.build2
-rw-r--r--subprojects/.gitignore2
-rw-r--r--subprojects/autocfg-rs.wrap6
-rw-r--r--subprojects/countme-rs.wrap6
-rw-r--r--subprojects/dissimilar-rs.wrap6
-rw-r--r--subprojects/expect-test-rs.wrap6
-rw-r--r--subprojects/hashbrown-rs.wrap6
-rw-r--r--subprojects/memoffset-rs.wrap6
-rw-r--r--subprojects/once_cell-rs.wrap6
-rw-r--r--subprojects/rnix-rs.wrap6
-rw-r--r--subprojects/rowan-rs.wrap6
-rw-r--r--subprojects/rustc-hash-rs.wrap6
-rw-r--r--subprojects/text-size-rs.wrap6
19 files changed, 200 insertions, 23 deletions
diff --git a/lix-doc/meson.build b/lix-doc/meson.build
new file mode 100644
index 000000000..36a5d8ba4
--- /dev/null
+++ b/lix-doc/meson.build
@@ -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,
+)
diff --git a/lix-doc/package.nix b/lix-doc/package.nix
deleted file mode 100644
index d3896e726..000000000
--- a/lix-doc/package.nix
+++ /dev/null
@@ -1,8 +0,0 @@
-{ rustPlatform, lib }:
-
-rustPlatform.buildRustPackage {
- name = "lix-doc";
-
- cargoLock.lockFile = ./Cargo.lock;
- src = lib.cleanSource ./.;
-}
diff --git a/meson.build b/meson.build
index cf1b877f9..4711e0087 100644
--- a/meson.build
+++ b/meson.build
@@ -30,6 +30,14 @@
# FIXME: This hack should be removed when https://git.lix.systems/lix-project/lix/issues/359
# 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".
#
# 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
# 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(),
default_options : [
'cpp_std=c++2a',
+ 'rust_std=2021',
# TODO(Qyriad): increase the warning level
'warning_level=1',
'debug=true',
@@ -322,13 +331,6 @@ pegtl = dependency(
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
libprocstat = declare_dependency(link_args : [ '-lprocstat' ])
endif
@@ -552,6 +554,7 @@ if is_darwin
)
endif
+subdir('lix-doc')
subdir('src')
subdir('scripts')
subdir('misc')
diff --git a/meson/cargo-lock-to-wraps.py b/meson/cargo-lock-to-wraps.py
new file mode 100755
index 000000000..811d7a219
--- /dev/null
+++ b/meson/cargo-lock-to-wraps.py
@@ -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)
diff --git a/meson/clang-tidy/clean_compdb.py b/meson/clang-tidy/clean_compdb.py
index 6736fe63a..a3fc77204 100755
--- a/meson/clang-tidy/clean_compdb.py
+++ b/meson/clang-tidy/clean_compdb.py
@@ -30,7 +30,14 @@ def process_compdb(compdb: list[dict]) -> list[dict]:
item['command'] = shlex.join(munch_command(shlex.split(item['command'])))
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():
diff --git a/package.nix b/package.nix
index 295e9139f..af542cdf5 100644
--- a/package.nix
+++ b/package.nix
@@ -41,6 +41,8 @@
pkg-config,
python3,
rapidcheck,
+ rustPlatform,
+ rustc,
sqlite,
toml11,
util-linuxMinimal ? utillinuxMinimal,
@@ -49,9 +51,6 @@
busybox-sandbox-shell,
- # internal fork of nix-doc providing :doc in the repl
- lix-doc ? __forDefaults.lix-doc,
-
pname ? "lix",
versionSuffix ? "",
officialRelease ? __forDefaults.versionJson.official_release,
@@ -83,7 +82,6 @@
configureFlags = prev.configureFlags or [ ] ++ [ (lib.enableFeature true "sigstop") ];
});
- lix-doc = callPackage ./lix-doc/package.nix { };
build-release-notes = callPackage ./maintainers/build-release-notes.nix { };
},
}:
@@ -137,6 +135,7 @@ let
./meson.build
./meson.options
./meson
+ ./lix-doc
./scripts/meson.build
./subprojects
]);
@@ -219,6 +218,7 @@ stdenv.mkDerivation (finalAttrs: {
meson
ninja
cmake
+ rustc
]
++ [
(lib.getBin lowdown)
@@ -258,7 +258,6 @@ stdenv.mkDerivation (finalAttrs: {
lowdown
libsodium
toml11
- lix-doc
pegtl
]
++ lib.optionals hostPlatform.isLinux [
@@ -290,6 +289,8 @@ stdenv.mkDerivation (finalAttrs: {
BOOST_LIBRARYDIR = "${lib.getLib boost}/lib";
};
+ cargoDeps = rustPlatform.importCargoLock { lockFile = ./lix-doc/Cargo.lock; };
+
preConfigure =
lib.optionalString (!finalAttrs.dontBuild && !hostPlatform.isStatic) ''
# 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
''
+ ''
+ # 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
patchShebangs --build tests/ doc/manual/
'';
diff --git a/src/libcmd/meson.build b/src/libcmd/meson.build
index 73deb035c..0a3ff8620 100644
--- a/src/libcmd/meson.build
+++ b/src/libcmd/meson.build
@@ -50,7 +50,7 @@ libcmd = library(
editline,
lowdown,
nlohmann_json,
- lix_doc
+ liblix_doc,
],
cpp_pch : cpp_pch,
install : true,
diff --git a/subprojects/.gitignore b/subprojects/.gitignore
new file mode 100644
index 000000000..e1e3c3239
--- /dev/null
+++ b/subprojects/.gitignore
@@ -0,0 +1,2 @@
+# Downloaded wrapped Rust projects
+*-*.*.*
diff --git a/subprojects/autocfg-rs.wrap b/subprojects/autocfg-rs.wrap
new file mode 100644
index 000000000..8e988f41e
--- /dev/null
+++ b/subprojects/autocfg-rs.wrap
@@ -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
diff --git a/subprojects/countme-rs.wrap b/subprojects/countme-rs.wrap
new file mode 100644
index 000000000..e160e34c0
--- /dev/null
+++ b/subprojects/countme-rs.wrap
@@ -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
diff --git a/subprojects/dissimilar-rs.wrap b/subprojects/dissimilar-rs.wrap
new file mode 100644
index 000000000..a51407482
--- /dev/null
+++ b/subprojects/dissimilar-rs.wrap
@@ -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
diff --git a/subprojects/expect-test-rs.wrap b/subprojects/expect-test-rs.wrap
new file mode 100644
index 000000000..1e2a4a3b9
--- /dev/null
+++ b/subprojects/expect-test-rs.wrap
@@ -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
diff --git a/subprojects/hashbrown-rs.wrap b/subprojects/hashbrown-rs.wrap
new file mode 100644
index 000000000..d2876225a
--- /dev/null
+++ b/subprojects/hashbrown-rs.wrap
@@ -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
diff --git a/subprojects/memoffset-rs.wrap b/subprojects/memoffset-rs.wrap
new file mode 100644
index 000000000..e9cc37422
--- /dev/null
+++ b/subprojects/memoffset-rs.wrap
@@ -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
diff --git a/subprojects/once_cell-rs.wrap b/subprojects/once_cell-rs.wrap
new file mode 100644
index 000000000..03345d388
--- /dev/null
+++ b/subprojects/once_cell-rs.wrap
@@ -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
diff --git a/subprojects/rnix-rs.wrap b/subprojects/rnix-rs.wrap
new file mode 100644
index 000000000..b06f72336
--- /dev/null
+++ b/subprojects/rnix-rs.wrap
@@ -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
diff --git a/subprojects/rowan-rs.wrap b/subprojects/rowan-rs.wrap
new file mode 100644
index 000000000..f6ab76d69
--- /dev/null
+++ b/subprojects/rowan-rs.wrap
@@ -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
diff --git a/subprojects/rustc-hash-rs.wrap b/subprojects/rustc-hash-rs.wrap
new file mode 100644
index 000000000..105234788
--- /dev/null
+++ b/subprojects/rustc-hash-rs.wrap
@@ -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
diff --git a/subprojects/text-size-rs.wrap b/subprojects/text-size-rs.wrap
new file mode 100644
index 000000000..8c7f1f4fe
--- /dev/null
+++ b/subprojects/text-size-rs.wrap
@@ -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