Compare commits

..

45 Commits

Author SHA1 Message Date
Gaétan Lepage
575fbaf778 ty: 0.0.95 -> 0.0.96 (#582783) 2026-11-04 11:38:00 +00:00
nixpkgs-ci[bot]
1b0661cb8e Merge master into staging-nixos 2026-11-04 06:11:11 +00:00
Ihar Hrachyshka
a43b7eab39 nixos/tests/x11: add -noreset flag to nspawn X11 tests (#582707) 2026-11-04 01:43:25 +00:00
nixpkgs-ci[bot]
f43d13a970 Merge master into staging-nixos 2026-11-04 00:16:26 +00:00
Will Fancher
43be3d4cfb nixos/systemd/tpm2: ensure systemd-pcrextend.socket is pulled in (#582268) 2026-11-03 20:52:06 +00:00
Naxdy
abae798b6c nixosTests/systemd-initrd-luks-tpm2: test for ability to measure LUKS volume keys 2026-11-03 21:41:56 +01:00
Naxdy
cf9a0df709 nixos/systemd/tpm2: ensure systemd-pcrextend.socket is pulled in
Assisted-By: omp/DeepSeek-V4.1-Flash-1017
2026-11-03 21:41:56 +01:00
Jörg Thalheim
4d7096f6c6 nixos-firewall-tool: run shellcheck as a passthru test (#582676) 2026-11-03 19:45:13 +00:00
Jörg Thalheim
fadbd12b88 nixos-firewall-tool: run shellcheck as a passthru test
Checking whether shellcheck can be built forces the whole Haskell
package set while evaluating any NixOS system with a firewall. The
check now runs in passthru.tests instead.
2026-11-03 20:33:30 +01:00
Jost Alemann
12214b623a ty: 0.0.95 -> 0.0.96
Changelog: https://github.com/astral-sh/ty/releases/tag/0.0.96
Diff: https://github.com/astral-sh/ty/compare/0.0.95...0.0.96
2026-11-03 19:32:53 +01:00
nixpkgs-ci[bot]
3328cd18b2 Merge master into staging-nixos 2026-11-03 18:09:45 +00:00
Maximilian Bosch
0fa2336746 nixos/tests/x11: add -noreset flag to nspawn X11 tests
Works around X resetting itself when the only connection (from
wait_for_x()) disconnects[1].

With this change, `nixosTests.nixos-test-driver.nspawn-interactive`
seems way less flaky, I couldn't trigger the hanging test scenario
within 50 runs.

[1] More context: https://github.com/NixOS/nixpkgs/pull/578540#issuecomment-6593586095

Co-authored-by: Ihar Hrachyshka <ihar.hrachyshka@gmail.com>
2026-11-03 15:51:07 +01:00
nixpkgs-ci[bot]
3b574a194d Merge master into staging-nixos 2026-11-03 12:09:08 +00:00
nixpkgs-ci[bot]
573530121c Merge master into staging-nixos 2026-11-03 06:10:58 +00:00
nixpkgs-ci[bot]
7de48641a5 Merge master into staging-nixos 2026-11-03 00:14:51 +00:00
nixpkgs-ci[bot]
0032afe410 Merge master into staging-nixos 2026-11-02 18:08:38 +00:00
Philip Taron
ea33e2134e make-initrd-ng: handle dlopen SONAME alternatives (#578841) 2026-11-02 17:24:12 +00:00
Philip Taron
0835e2960f make-initrd-ng: format with rustfmt
Assisted-by: Claude Code (claude-opus-5-5)
2026-11-02 08:22:08 -08:00
Philip Taron
7732580291 make-initrd-ng: tune is_glibc_runtime
Assisted-by: Claude Code (claude-opus-5-5)
2026-11-02 08:20:11 -08:00
Philip Taron
70cffbcf42 make-initrd-ng: inline find_library
Assisted-by: Claude Code (claude-opus-5-5)
2026-11-02 08:19:56 -08:00
Jacek Galowicz
2c4e5922cf Test driver doctests (#581841) 2026-11-02 16:19:11 +00:00
nixpkgs-ci[bot]
964de0a0cf Merge master into staging-nixos 2026-11-02 13:55:22 +00:00
Ryan Lahfa
f4b42644cb nixos/test-driver: fix VM startup in large tests, port to selectors, improve logging (#578536) 2026-11-02 12:52:34 +00:00
nixpkgs-ci[bot]
2d5423b857 Merge master into staging-nixos 2026-11-02 12:10:31 +00:00
Jacek Galowicz
ad8d8b2dd6 test-driver: outsource some code to pure functions for doctests 2026-11-02 09:28:00 +01:00
Jacek Galowicz
fdc0faecfb test-driver: doctest some pure functions 2026-11-02 09:28:00 +01:00
Maximilian Bosch
addb72b9dc nixos/test-driver: dim log timer (#581943) 2026-11-02 07:56:01 +00:00
zowoq
48b13a3d84 linux: enable strictDeps (#581314) 2026-11-02 07:06:09 +00:00
nixpkgs-ci[bot]
957f263e78 Merge master into staging-nixos 2026-11-02 06:13:58 +00:00
Sandro
e9035336b3 nixos-enter: unset HOSTNAME and NIX_REMOTE to not confuse system or u… (#522097) 2026-11-02 01:05:36 +00:00
nixpkgs-ci[bot]
74801e0478 Merge master into staging-nixos 2026-11-02 00:17:37 +00:00
Maximilian Bosch
045ca2d4ec nixos/test-driver: dim log timer
Since 509e09e6 we have a prefix like `[2.00s]` that shows the elapsed
seconds of a test for each log-message.

While it's arguably useful information, for me it's noise that I only
care about in some specific cases which is why I'd prefer to have this
dimmed as all the serial output.
2026-11-01 22:23:14 +01:00
Yueh-Shun Li
f8e3bf8a2e brltty: add polkit support (#544333) 2026-11-01 19:47:31 +00:00
nixpkgs-ci[bot]
1de0066f4b Merge master into staging-nixos 2026-11-01 18:06:55 +00:00
Jacek Galowicz
7d47ee0895 test-driver: add doctesting in checkphase 2026-11-01 15:13:25 +01:00
nixpkgs-ci[bot]
55a9de48ba Merge master into staging-nixos 2026-11-01 12:08:42 +00:00
nixpkgs-ci[bot]
c3c3cb0a91 Merge master into staging-nixos 2026-11-01 10:06:58 +00:00
eljamm
4f64ec7425 linux: enable strictDeps 2026-10-31 10:24:38 +01:00
Maximilian Bosch
0d3c836963 nixos/qemu-vm: fix startup issues, port virtiofs job-control to Python
The issue we were chasing was an number of QEMU VMs being started up in
large tests[1], introduced by the migration from 9pfs to virtiofs[2]. What
happened here was

* When having a large number of VMs (and at least 3x the amount of
  virtiofsd procs), some processes aren't ready for operation leading
  QEMU to fail because the sockets it exposes aren't ready yet.

* The tests hang indefinitely now since the process is dead, but the
  stdout fd is still open as it's used by the virtiofsd processes.

* As a result, the startup logic for a VM in the test-driver assumes the
  VM to be dead and tries to fully read its stdout which hangs since it's
  still used by the virtiofsd procs.

I tried to fix this in pure Bash, but decided to give up since Bash's
job control logic is a hot mess. Also, a naive implementation would
notably slow down the startup of tests since we need a loop for
virtiofsd having set up all sockets before starting QEMU and with
asyncio we can wait on all of them rather than doing all of this
sequentially.

The virtiofsd configuration is passed to the Python script via CLI args
on purpose to still evaluate Bash variables that are sadly part of the
interface.

I think it'd make sense to move more of the start script into this
Python package, but my main goal is to have something ready where we can
be confident that the original bug got fixed. This refactoring can be
done iteratively in follow-ups.

[1] e.g. https://hydra.nixos.org/build/350180953/step/3/log/tail
[2] https://github.com/NixOS/nixpkgs/pull/552774
2026-10-29 09:38:50 +01:00
K900
f65c491441 lib/test-driver: port to selectors
This seems to bypass whatever nonsense we've been hitting with select.select,
somehow.
2026-10-29 09:38:48 +01:00
K900
fa391feabe lib/test-driver: also add machine name to the other errors 2026-10-29 09:37:10 +01:00
K900
e5d47c704e lib/test-driver: add a timeout for waiting for QEMU to connect
We still don't know _why_ it's not connecting, but at least
now we will fail (reasonably) fast if it doesn't instead of
hogging a build slot forever.
2026-10-29 09:37:10 +01:00
Aliaksandr
45e574d8f1 make-initrd-ng: handle dlopen SONAME alternatives
Assisted-by: codex with gpt-5.6-sol-high
2026-10-25 17:02:24 +02:00
Bram Duvigneau
43e45601c1 brltty: add polkit support
BRLTTY enables Polkit support by default (--enable-polkit), but detects it
solely via `pkg-config --exists polkit-gobject-1`. Since polkit was not in
buildInputs, detection silently failed and BRLTTY was built without it, while
still installing its Polkit policy (org.a11y.brlapi.policy).

Without Polkit support, BrlAPI clients such as Orca cannot authorize against
BRLTTY, so a braille display is unusable from the desktop.

Polkit is Linux-only, so this follows the existing alsaSupport/systemdSupport
pattern and gates on lib.meta.availableOn. The configure flag is passed
explicitly rather than relying on pkg-config detection, so the feature can no
longer be dropped silently.

Fixes #540757

Assisted-by: Claude Code (Claude Opus 4.8, claude-opus-4-8)
2026-09-15 14:05:15 +02:00
Sandro Jäckel
5563d930fa nixos-enter: unset HOSTNAME and NIX_REMOTE to not confuse system or use the ISOs nix daemon
This is necessary when executing nixos-enter from the root user.
2026-05-20 00:58:41 +02:00
2501 changed files with 8889 additions and 11273 deletions

View File

@@ -31,7 +31,7 @@ pkgs.mkShell {
## Packaging guide {#sec-language-ocaml-packaging}
OCaml libraries are installed in `$out/lib/ocaml/${ocaml.version}/site-lib/`, or in the same directory of the `dev` output (see `buildDunePackage` below). Such directories are automatically added to the `$OCAMLPATH` environment variable when building another package that depends on them or when opening a `nix-shell`.
OCaml libraries should be installed in `$(out)/lib/ocaml/${ocaml.version}/site-lib/`. Such directories are automatically added to the `$OCAMLPATH` environment variable when building another package that depends on them or when opening a `nix-shell`.
Given that most of the OCaml ecosystem is now built with dune, nixpkgs includes a convenience build support function called `buildDunePackage` that will build an OCaml package using dune, OCaml and findlib and any additional dependencies provided as `buildInputs` or `propagatedBuildInputs`.
@@ -139,29 +139,6 @@ buildDunePackage (finalAttrs: {
})
```
Unless the package sets `outputs`, `buildDunePackage` builds separate outputs,
and points `$OCAMLFIND_DESTDIR` to `dev`:
- `out` contains what the package produces for use at runtime, such as
executables.
- `dev` contains the OCaml libraries and the propagated dependencies needed to
build other packages against them. It is selected automatically when the
package is used as a build input.
- `man` contains the man pages. Like `out`, it is installed by default.
- `doc` contains the documentation, such as the README and license files.
This keeps build-time only OCaml dependencies out of the runtime closure of
executables. Code that refers to the library directory of such a package must
use its `dev` output, for example `${lib.getDev menhirLib}/lib/ocaml` or
`lib.makeSearchPathOutput "dev" "lib/ocaml/${ocaml.version}/site-lib"`.
Likewise, installing the library into a profile or environment requires its
`dev` output, e.g. `ocamlPackages.menhirLib.dev`.
Toplevels and programs that load plugins need their own OCaml library at
runtime, and the two outputs would refer to each other. Set
`outputs = [ "out" ];` for such packages, and for packages whose custom
`installPhase` installs everything into `$out`.
The build will automatically fail if two distinct versions of the same library
are added to `buildInputs` (which usually happens transitively because of
`propagatedBuildInputs`). Set `dontDetectOcamlConflicts` to true to disable this

View File

@@ -246,46 +246,6 @@ To disable the SwiftPM install phase, include the following in your derivation:
{ dontUseSwiftpmInstall = true; }
```
## Swift Macros {#ssec-swift-macros}
Nixpkgs includes the stdlib macros (ObservationMacros and SwiftMacros) and FoundationMacros in the toolchain.
Packages that need macros for Apple frameworks on Darwin have two options:
- `open-apple-macros` provides open-source implementations of FoundationModelsMacros and SwiftUIMacros; or
- `darwin.xcode-macros` provides macro libraries from Xcode not otherwise included in the toolchain, but they are unfree.
Add the appropriate package to `depsBuildBuild` (because they are compiler plugins that run on the build platform).
If you need to manually specify the path for a package because it or its build system invokes `swiftc` directly:
### `open-apple-macros` {#ssec-swift-macros-open-apple-macros}
```nix
{
buildPhase = ''
runHook preBuild
swiftc \
-external-plugin-path ${open-apple-macros}/lib/swift/host/plugins#${open-apple-macros}/libexec/swift/plugins/OpenAppleMacrosServer \
-disable-sandbox \
*.swift \
-o the_binary
runHook postBuild
'';
}
```
### `darwin.xcode-macros` {#ssec-swift-macros-xcode-macros}
```nix
{
# For `darwin.xcode-macros`
buildPhase = ''
runHook preBuild
swiftc \
-plugin-path ${darwin.xcode-macros}/lib/swift/host/plugins \
*.swift \
-o the_binary
runHook postBuild
'';
}
```
## Hooks {#ssec-swift-hooks}
Swift provides the following hooks to automate builds and unpack dependencies:

View File

@@ -4660,15 +4660,6 @@
"ssec-swiftpm-install-phase": [
"index.html#ssec-swiftpm-install-phase"
],
"ssec-swift-macros": [
"index.html#ssec-swift-macros"
],
"ssec-swift-macros-open-apple-macros": [
"index.html#ssec-swift-macros-open-apple-macros"
],
"ssec-swift-macros-xcode-macros": [
"index.html#ssec-swift-macros-xcode-macros"
],
"ssec-swift-hooks": [
"index.html#ssec-swift-hooks"
],

View File

@@ -59,11 +59,6 @@
- `paperless-manage` now uses `runuser` instead of automatically calling `sudo` to set user/group before running. Invoke the script with `sudo paperless-manage` or an equivalent elevation tool of your choice
- OpenSSL now prefers the system CA bundle at `/etc/ssl/certs/ca-certificates.crt` on both Linux and Darwin, falling back to `/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt` only when the system bundle is absent.
Previously, Darwin used the default Nix profile bundle directly.
An existing but unreadable or invalid system bundle does not trigger the fallback.
Explicit `NIX_SSL_CERT_FILE` and `SSL_CERT_FILE` overrides still take precedence.
- `hyperfine` has been updated from 1.21.0 to 2.0.0, which contains several breaking changes:
- Benchmarked commands are now executed directly instead of through an intermediate shell. Pass `-S`/`--shell=default` to restore the previous behavior.
- The `--export-json` format has changed (schema version 2); tools consuming the exported JSON must be updated.
@@ -106,13 +101,6 @@
By the time of this release, Homebrew will offer only limited [Tier 3](https://docs.brew.sh/Support-Tiers#tier-3) support for the platform, but MacPorts will likely continue to support it for a long time.
We also recommend users consider installing NixOS, which should continue to run on essentially all Intel Macs, especially after Apple stops security support for macOS 26 in 2028.
- `ocamlPackages.buildDunePackage` now builds packages with `out`, `dev`, `man` and `doc` outputs by default, unless they set `outputs`.
The OCaml libraries are installed into `dev`, man pages into `man`, documentation into `doc`, and `out` only contains what is needed at runtime, such as executables. This removes build-time only OCaml dependencies from the closure of tools like `patdiff`.
Code that refers to `${ocamlPackages.foo}/lib/ocaml` must use `${lib.getDev ocamlPackages.foo}/lib/ocaml` instead.
Installing such a library into a profile or environment (for example with `home.packages`, `environment.systemPackages` or `nix profile add`) no longer provides its `lib/ocaml` directory; install `ocamlPackages.foo.dev` instead.
- The `bin` and `lib` outputs of `ocamlPackages.odoc`, `ocamlPackages.crunch`, `ocamlPackages.mdx` and `ocamlPackages.tw` were removed. Use the package itself for the executables, and its `dev` output for the OCaml library.
- `bundlerApp` now sets `__structuredAttrs = true` for its result package.
Out-of-tree packages passing `postBuild` to `bundlerApp` should examine if their `postBuild` commands are compatible with structured attributes.
@@ -216,10 +204,6 @@
- `zerofs` has been updated from `1.x` to `2.x` which is a breaking change. Volumes created by earlier releases are refused at open with a clear error. There is no migration tool; older volumes remain readable and writable by the release that created them.
- `python3Packages.buildPythonPackage` and `python3Packages.buildPythonApplication` now warn in the presence of `unittestFlagsArray`.
Please use [`unittestFlags`](#using-unittestcheckhook) instead.
If modifying the Nix expression is not feasible, users can remediate the warning by overriding `unittestFlagsArray` with `null` or `[ ]`.
- `keycloak.plugins.keycloak-metrics-spi` has been removed. Keycloak exposes Prometheus metrics natively on its management interface; enable them with the `metrics-enabled` setting (and `event-metrics-user-enabled` for login and event counters). See [Gaining insights with metrics](https://www.keycloak.org/observability/configuration-metrics).
- `alps` has been rewritten upstream, see [upstream repository](https://github.com/migadu/alps) for documentation.
@@ -281,8 +265,6 @@
- `tcl.mkTclDerivation` now enables `strictDeps` and `__structuredAttrs`.
- `rustPlatform.cargoSetupHook` now forces several common C libraries to be linked to the Nixpkgs library rather than the vendored library. These include: aws-lc, openssl, libz, libsqlite3, zstd, libgit2, sodium, rustonig, libssh2, nginx, duckdb, and jemalloc. Set `dontCargoUseSystemLibs = true;` to opt out.
- `rssguard` 5.x uses a new database layer. Regenerate your database after upgrading, following the [RSS Guard migration notes](https://rssguard.readthedocs.io/en/stable/contrib/migrate.html).
- `pdns` has been updated from `5.0.x` to `5.1.x`. Please be sure to review the [Upgrade Notes](https://doc.powerdns.com/authoritative/upgrading.html#to-5-1-0) before upgrading. Namely LUA record updates are no longer allowed by default, and the embedded webserver no longer includes a `access-control-allow-origin: *` header by default.
@@ -497,7 +479,7 @@
SingularityCE 4.6.0 was the last release.
Use Apptainer (`apptainer`) instead.
- Swift has been upgraded to Swift 6.4.0 from Swift 5.10.1.
- Swift has been upgraded to Swift 6.3.3 from Swift 5.10.1.
The Swift packaging has been rewritten.
## Nixpkgs Library {#sec-nixpkgs-release-26.11-lib}

View File

@@ -1198,9 +1198,6 @@ They cannot be overridden without rebuilding the package.
If dependencies should be resolved at runtime, use `--suffix` to append fallback values to `PATH`.
`makeBinaryWrapper` refuses a `--prefix` or `--suffix` value that would introduce an empty segment (an empty value, or a leading, trailing or doubled separator), because many `PATH`-like variables interpret an empty segment as the current directory.
For variables where an empty segment is useful and safe, such as `LUA_PATH` where `;;` stands for the default search path, use `--prefix-unchecked` or `--suffix-unchecked` instead.
There’s many more kinds of arguments, they are documented in `nixpkgs/pkgs/build-support/setup-hooks/make-wrapper.sh` for the `makeWrapper` implementation and in `nixpkgs/pkgs/by-name/ma/makeBinaryWrapper/make-binary-wrapper.sh` for the `makeBinaryWrapper` implementation.
`wrapProgram` is a convenience function you probably want to use most of the time, implemented by both `makeWrapper` and `makeBinaryWrapper`.

View File

@@ -18,8 +18,6 @@
+nixpkgs.url = "https://channels.nixos.org/nixos-26.05/nixexprs.tar.zst";
```
- GNOME has been updated to version 51. Refer to the [GNOME release notes](https://release.gnome.org/51/) for more details.
- `sing-box` now supports NaïveProxy outbounds.
## New Modules {#sec-release-26.11-new-modules}

View File

@@ -41,8 +41,7 @@ mkdir -p $out/tarball
rm env-vars
# Store optimization can change hardlink topology without changing input NARs.
time tar --hard-dereference --sort=name --mtime='@1' --owner=0 --group=0 --numeric-owner -c * $extraArgs | $compressCommand > $out/tarball/$fileName.tar${extension}
time tar --sort=name --mtime='@1' --owner=0 --group=0 --numeric-owner -c * $extraArgs | $compressCommand > $out/tarball/$fileName.tar${extension}
mkdir -p $out/nix-support
echo $system > $out/nix-support/system

View File

@@ -10,6 +10,7 @@
junit-xml,
ptpython,
pydantic,
pytest,
python,
ovmfvartool,
remote-pdb,
@@ -80,11 +81,14 @@ buildPythonApplication {
doCheck = true;
nativeCheckInputs = [
pytest
ruff
ty
];
checkPhase = ''
echo -e "\x1b[32m## run doctests\x1b[0m"
pytest --doctest-modules -p no:cacheprovider test_driver
echo -e "\x1b[32m## run ty\x1b[0m"
# Installation adds the driver to PYTHONPATH; keep ty imports in the source tree.
PYTHONPATH=".:$PYTHONPATH" ty check --error-on-warning test_driver extract-docstrings.py

View File

@@ -87,6 +87,30 @@ def get_tmp_dir() -> Path:
def pythonize_name(name: str) -> str:
"""Turn a machine name into a valid Python identifier.
Names that already are valid identifiers stay the same:
>>> pythonize_name("node_1")
'node_1'
Every character that is not allowed in an identifier becomes "_":
>>> pythonize_name("my-vm")
'my_vm'
>>> pythonize_name("web.example.org")
'web_example_org'
>>> pythonize_name("münchen")
'm_nchen'
A leading digit is replaced rather than prefixed, so it gets lost, while
digits later in the name are kept:
>>> pythonize_name("1node")
'_node'
>>> pythonize_name("12node")
'_2node'
"""
return re.sub(r"^[^A-Za-z_]|[^A-Za-z0-9_]", "_", name)

View File

@@ -14,6 +14,22 @@ def as_timedelta(duration: Duration) -> dt.timedelta:
Bare numbers are interpreted as seconds. This keeps existing test scripts
that pass plain integers working while `datetime.timedelta` becomes the preferred
way to express durations.
>>> as_timedelta(dt.timedelta(minutes=1))
datetime.timedelta(seconds=60)
>>> as_timedelta(90)
datetime.timedelta(seconds=90)
>>> as_timedelta(1.5)
datetime.timedelta(seconds=1, microseconds=500000)
A `bool` is an `int` in Python, but it is never a valid duration:
>>> as_timedelta(True)
Traceback (most recent call last):
TypeError: expected a duration, got bool: True
>>> as_timedelta("1")
Traceback (most recent call last):
TypeError: expected a timedelta, int, or float duration, got str
"""
if isinstance(duration, dt.timedelta):
return duration
@@ -27,7 +43,13 @@ def as_timedelta(duration: Duration) -> dt.timedelta:
def as_seconds(duration: Duration) -> float:
"""Coerce a `Duration` into a floating-point number of seconds."""
"""Coerce a `Duration` into a floating-point number of seconds.
>>> as_seconds(90)
90.0
>>> as_seconds(dt.timedelta(minutes=1, milliseconds=500))
60.5
"""
return as_timedelta(duration).total_seconds()

View File

@@ -242,7 +242,7 @@ class TerminalLogger(AbstractLogger):
elapsed = time.monotonic() - self._start_time
if "machine" in attributes:
message = f"{attributes['machine']}: {message}"
return f"[{elapsed:.2f}s] {message}"
return Style.DIM + f"[{elapsed:.2f}s]" + Style.RESET_ALL + f" {message}" # ty: ignore[unsupported-operator]
@staticmethod
def _eprint(*args: object, **kwargs: Any) -> None:
@@ -322,10 +322,27 @@ class XMLLogger(AbstractLogger):
self.xml.endDocument()
self.logfile_handle.close()
def sanitise(self, message: str) -> str:
@staticmethod
def sanitise(message: str) -> str:
r"""Remove the characters of Unicode's "Other" categories, such as
control characters, from serial output before it is written to XML.
>>> XMLLogger.sanitise("booting\x00...\x07")
'booting...'
>>> XMLLogger.sanitise("Grüße")
'Grüße'
"""
return "".join(ch for ch in message if unicodedata.category(ch)[0] != "C")
def maybe_prefix(self, message: str, attributes: dict[str, str]) -> str:
@staticmethod
def maybe_prefix(message: str, attributes: dict[str, str]) -> str:
"""Prefix the message with the name of the machine, if there is one.
>>> XMLLogger.maybe_prefix("booting", {"machine": "server"})
'server: booting'
>>> XMLLogger.maybe_prefix("booting", {})
'booting'
"""
if "machine" in attributes:
return f"{attributes['machine']}: {message}"
return message

View File

@@ -5,7 +5,7 @@ import os
import platform
import queue
import re
import select
import selectors
import shlex
import shutil
import socket
@@ -139,7 +139,22 @@ XDOTOOL_MODIFIER_ALIASES = {
def xdotool_key_sequence(key: str) -> str:
"""Translate a QEMU-style key chord to xdotool syntax.
For example, "ctrl-alt-ret" becomes "ctrl+alt+Return".
>>> xdotool_key_sequence("ctrl-alt-ret")
'ctrl+alt+Return'
>>> xdotool_key_sequence("meta_l-x")
'super+x'
>>> xdotool_key_sequence("alt-f4")
'alt+F4'
A modifier on its own is a regular key:
>>> xdotool_key_sequence("shift")
'Shift_L'
A "-" that follows a modifier is the key itself, not a separator:
>>> xdotool_key_sequence("ctrl--")
'ctrl+-'
"""
parts = key.split("-")
modifiers = []
@@ -154,9 +169,42 @@ def xdotool_key_sequence(key: str) -> str:
def make_command(args: list) -> str:
"""Join arguments into a shell command, quoting each one as a single word.
>>> make_command(["echo", "a b", 1])
"echo 'a b' 1"
>>> make_command(["ls", "*"])
"ls '*'"
"""
return " ".join(map(shlex.quote, (map(str, args))))
def parse_systemctl_property(line: str) -> tuple[str, str] | None:
"""Split a line of `systemctl show` output into its property and value.
>>> parse_systemctl_property("Id=foo.service")
('Id', 'foo.service')
Only the first "=" separates the two, and values can be empty:
>>> parse_systemctl_property("Environment=A=1 B=2")
('Environment', 'A=1 B=2')
>>> parse_systemctl_property("Description=")
('Description', '')
Lines that aren't properties yield `None`:
>>> parse_systemctl_property("") is None
True
>>> parse_systemctl_property("no property") is None
True
"""
match = re.match(r"^([^=]+)=(.*)$", line)
if match is None:
return None
return match[1], match[2]
def retry(
fn: Callable,
timeout_seconds: int | dt.timedelta | None = None,
@@ -217,6 +265,13 @@ class QemuStartCommand:
These Nix commands have the particular characteristic that the
machine name can be extracted out of them via a regex match.
(Admittedly a _very_ implicit contract, TODO fix this eventually.)
>>> QemuStartCommand("/nix/store/hash-nixos-vm/bin/run-foo-vm").machine_name
'foo'
>>> QemuStartCommand("run-foo-bar-vm").machine_name
'foo-bar'
>>> QemuStartCommand("/some/script").machine_name
'machine'
"""
match = re.search("run-(.+)-vm$", self._cmd)
name = "machine"
@@ -397,6 +452,29 @@ class BaseMachine(ABC):
"""Shutdown the machine gracefully, waiting for it to exit."""
...
@staticmethod
def _systemctl_command(q: str, user: str | None = None) -> str:
r"""Build a `systemctl` command, or a `systemctl --user` one for `user`.
>>> print(BaseMachine._systemctl_command("list-jobs --no-pager"))
systemctl list-jobs --no-pager
>>> print(BaseMachine._systemctl_command("list-jobs --no-pager", "alice"))
su -l alice --shell /bin/sh -c $'XDG_RUNTIME_DIR=/run/user/`id -u` systemctl --user list-jobs --no-pager'
Single quotes survive the surrounding `$'...'`:
>>> print(BaseMachine._systemctl_command("show 'foo bar'", "alice"))
su -l alice --shell /bin/sh -c $'XDG_RUNTIME_DIR=/run/user/`id -u` systemctl --user show \'foo bar\''
"""
if user is None:
return f"systemctl {q}"
escaped = q.replace("'", "\\'")
return (
f"su -l {user} --shell /bin/sh -c "
"$'XDG_RUNTIME_DIR=/run/user/`id -u` "
f"systemctl --user {escaped}'"
)
def systemctl(self, q: str, user: str | None = None) -> tuple[int, str]:
"""
Runs `systemctl` commands with optional support for
@@ -411,14 +489,7 @@ class BaseMachine(ABC):
machine.systemctl("list-jobs --no-pager", "any-user")
```
"""
if user is not None:
q = q.replace("'", "\\'")
return self.execute(
f"su -l {user} --shell /bin/sh -c "
"$'XDG_RUNTIME_DIR=/run/user/`id -u` "
f"systemctl --user {q}'"
)
return self.execute(f"systemctl {q}")
return self.execute(self._systemctl_command(q, user))
def wait_for_unit(
self,
@@ -467,17 +538,10 @@ class BaseMachine(ABC):
+ f" failed with exit code {status}"
)
line_pattern = re.compile(r"^([^=]+)=(.*)$")
def tuple_from_line(line: str) -> tuple[str, str]:
match = line_pattern.match(line)
assert match is not None
return match[1], match[2]
return dict(
tuple_from_line(line)
parsed
for line in lines.split("\n")
if line_pattern.match(line)
if (parsed := parse_systemctl_property(line)) is not None
)
def get_unit_property(
@@ -505,12 +569,12 @@ class BaseMachine(ABC):
f"produced invalid output: {lines}"
)
line_pattern = re.compile(r"^([^=]+)=(.*)$")
match = line_pattern.match(lines)
assert match is not None, invalid_output_message
parsed = parse_systemctl_property(lines)
assert parsed is not None, invalid_output_message
assert match[1] == property, invalid_output_message
return match[2]
name, value = parsed
assert name == property, invalid_output_message
return value
def require_unit_state(self, unit: str, require_state: str = "active") -> None:
"""
@@ -742,7 +806,7 @@ class BaseMachine(ABC):
)
if ret.returncode != 0:
raise MachineError(
f"Cannot convert screenshot (pnmtopng returned code {ret.returncode})"
f"{self.name}: Cannot convert screenshot (pnmtopng returned code {ret.returncode})"
)
def get_screen_text_variants(self) -> list[str]:
@@ -1178,15 +1242,18 @@ class QemuMachine(BaseMachine):
"""Debugging: Dump the contents of the TTY<n>"""
self.execute(f"fold -w 80 /dev/vcs{tty} | systemd-cat")
def _execute(
self,
command: str,
check_return: bool = True,
check_output: bool = True,
timeout: dt.timedelta | None = dt.timedelta(minutes=15),
) -> tuple[int, str]:
self.connect()
@staticmethod
def _shell_command(command: str, timeout: dt.timedelta | None) -> str:
"""Build the line that runs `command` over the shell of the machine.
The command runs with strict shell options, and its output gets
base64-encoded so that it can be read back as a single line:
>>> print(QemuMachine._shell_command("echo 'hi'", dt.timedelta(seconds=10)))
timeout 10.0 bash -c 'set -euo pipefail; echo '"'"'hi'"'"'' | (base64 -w 0; echo)
>>> print(QemuMachine._shell_command("true", None).strip())
bash -c 'set -euo pipefail; true' | (base64 -w 0; echo)
"""
# Always run command with shell opts
command = f"set -euo pipefail; {command}"
@@ -1196,12 +1263,19 @@ class QemuMachine(BaseMachine):
# While sh is bash on NixOS, this is not the case for every distro.
# We explicitly call bash here to allow for the driver to boot other distros as well.
out_command = (
f"{timeout_str} bash -c {shlex.quote(command)} | (base64 -w 0; echo)\n"
)
return f"{timeout_str} bash -c {shlex.quote(command)} | (base64 -w 0; echo)"
def _execute(
self,
command: str,
check_return: bool = True,
check_output: bool = True,
timeout: dt.timedelta | None = dt.timedelta(minutes=15),
) -> tuple[int, str]:
self.connect()
assert self.shell
self.shell.send(out_command.encode())
self.shell.send(f"{self._shell_command(command, timeout)}\n".encode())
if not check_output:
return (-2, "")
@@ -1335,16 +1409,6 @@ class QemuMachine(BaseMachine):
Wait for a connection to the guest root shell
"""
def shell_ready(timeout: dt.timedelta) -> bool:
"""We sent some data from the backdoor service running on the guest
to indicate that the backdoor shell is ready.
As soon as we read some data from the socket here, we assume that
our root shell is operational.
"""
assert self.shell
(ready, _, _) = select.select([self.shell], [], [], timeout.total_seconds())
return bool(ready)
if self.connected:
return
@@ -1354,9 +1418,15 @@ class QemuMachine(BaseMachine):
assert self.shell
tic = time.monotonic()
sel = selectors.DefaultSelector()
sel.register(self.shell, selectors.EVENT_READ)
for _ in range(10):
if shell_ready(timeout=dt.timedelta(seconds=30)):
# We sent some data from the backdoor service running on the guest
# to indicate that the backdoor shell is ready.
# As soon as we read some data from the socket here, we assume that
# our root shell is operational.
if sel.select(timeout=30):
break
self.log("Guest root shell did not produce any data yet...")
self.log(
@@ -1477,6 +1547,7 @@ class QemuMachine(BaseMachine):
s = socket.socket(family=socket.AF_UNIX, type=socket.SOCK_STREAM)
s.bind(str(path))
s.listen(1)
s.setblocking(False)
return s
monitor_socket = create_socket(clear(self.monitor_path))
@@ -1498,8 +1569,10 @@ class QemuMachine(BaseMachine):
would block forever if QEMU exits before connecting.
"""
assert self.process
while True:
readable, _, _ = select.select([sock], [], [], 1.0)
sel = selectors.DefaultSelector()
sel.register(sock, selectors.EVENT_READ)
for _ in range(60):
readable = sel.select(1)
if readable:
conn, _ = sock.accept()
return conn
@@ -1509,8 +1582,11 @@ class QemuMachine(BaseMachine):
if self.process.stdout:
output = self.process.stdout.read().decode(errors="ignore")
raise MachineError(
f"QEMU process exited with code {rc} before connecting to {name} socket.\n{output}"
f"{self.name}: QEMU process exited with code {rc} before connecting to {name} socket.\n{output}"
)
raise MachineError(
f"{self.name}: Timed out waiting for QEMU connection on {name} socket"
)
self.monitor = accept_or_fail(monitor_socket, "monitor")
self.shell = accept_or_fail(shell_socket, "shell")
@@ -1690,7 +1766,19 @@ class NspawnMachine(BaseMachine):
vnc: NspawnVnc | None
@staticmethod
def machine_name_from_start_command(start_command: str) -> str:
def _machine_name_from_start_command(start_command: str) -> str:
"""Extract the machine name from a start script of a container.
>>> NspawnMachine._machine_name_from_start_command(
... "/nix/store/hash-container/bin/run-foo-nspawn"
... )
'foo'
>>> NspawnMachine._machine_name_from_start_command("run-foo-bar-nspawn")
'foo-bar'
>>> NspawnMachine._machine_name_from_start_command("/some/script")
Traceback (most recent call last):
AssertionError: Could not extract node name from /some/script
"""
match = re.search("run-(.+)-nspawn", os.path.basename(start_command))
assert match is not None, f"Could not extract node name from {start_command}"
return match.group(1)
@@ -1710,7 +1798,7 @@ class NspawnMachine(BaseMachine):
# See analogous TODO in `QemuStartCommand::machine_name`.
super().__init__(
out_dir=out_dir,
name=name or self.machine_name_from_start_command(start_command),
name=name or self._machine_name_from_start_command(start_command),
logger=logger,
callbacks=callbacks,
tmp_dir=tmp_dir,
@@ -1743,6 +1831,33 @@ class NspawnMachine(BaseMachine):
with self.nested("waiting for the X11 server"):
retry(check_x, as_timedelta(timeout))
@staticmethod
def _xdotool_command(key: str) -> str:
"""Build the xdotool command that presses a QEMU-style key.
Literal characters get typed to avoid key syntax, e.g. "+" as a chord
separator:
>>> print(NspawnMachine._xdotool_command("a"))
xdotool type --clearmodifiers --delay 0 -- a
>>> print(NspawnMachine._xdotool_command("+"))
xdotool type --clearmodifiers --delay 0 -- +
Everything else is a key chord:
>>> print(NspawnMachine._xdotool_command("ctrl-alt-ret"))
xdotool key --clearmodifiers ctrl+alt+Return
>>> print(NspawnMachine._xdotool_command("\\n"))
xdotool key --clearmodifiers Return
"""
if len(key) == 1 and key.isprintable():
return make_command(
["xdotool", "type", "--clearmodifiers", "--delay", 0, "--", key]
)
return make_command(
["xdotool", "key", "--clearmodifiers", xdotool_key_sequence(key)]
)
def send_key(
self,
key: str,
@@ -1752,25 +1867,7 @@ class NspawnMachine(BaseMachine):
_warn_if_numeric_duration(delay, "send_key")
context = self.nested(f"sending key {repr(key)}") if log else nullcontext()
with context:
# Type literal characters to avoid key syntax, e.g. "+" as a chord separator.
if len(key) == 1 and key.isprintable():
command = [
"xdotool",
"type",
"--clearmodifiers",
"--delay",
0,
"--",
key,
]
else:
command = [
"xdotool",
"key",
"--clearmodifiers",
xdotool_key_sequence(key),
]
self.succeed(make_command(command))
self.succeed(self._xdotool_command(key))
if delay is not None:
time.sleep(as_seconds(delay))
@@ -1799,7 +1896,7 @@ class NspawnMachine(BaseMachine):
ret = subprocess.run(["xwdtopnm", xwd_path], stdout=ppm)
if ret.returncode != 0:
raise MachineError(
f"Cannot convert screenshot (xwdtopnm returned code {ret.returncode})"
f"{self.name}: Cannot convert screenshot (xwdtopnm returned code {ret.returncode})"
)
yield ppm_path
@@ -1836,6 +1933,28 @@ class NspawnMachine(BaseMachine):
def is_up(self) -> bool:
return self.process is not None
@staticmethod
def _parse_sd_notify(data: bytes) -> tuple[bool, int | None]:
"""Extract readiness and the leader PID from an `sd_notify` datagram.
>>> NspawnMachine._parse_sd_notify(b"READY=1\\n")
(True, None)
>>> NspawnMachine._parse_sd_notify(b"X_NSPAWN_LEADER_PID=42\\n")
(False, 42)
>>> NspawnMachine._parse_sd_notify(b"X_NSPAWN_LEADER_PID=42\\nREADY=1\\n")
(True, 42)
>>> NspawnMachine._parse_sd_notify(b"STATUS=Starting up\\n")
(False, None)
"""
ready = False
leader_pid = None
for line in data.decode(errors="replace").splitlines():
if line == "READY=1":
ready = True
if line.startswith("X_NSPAWN_LEADER_PID="):
leader_pid = int(line.split("=")[1])
return ready, leader_pid
def _drain_notify_socket(self) -> None:
"""Continuously drain the container's `sd_notify` socket (NOTIFY_SOCKET)
for the whole lifetime of the container, recording readiness and the
@@ -1866,13 +1985,7 @@ class NspawnMachine(BaseMachine):
continue
except OSError:
break
ready = False
leader_pid = None
for line in data.decode(errors="replace").splitlines():
if line == "READY=1":
ready = True
if line.startswith("X_NSPAWN_LEADER_PID="):
leader_pid = int(line.split("=")[1])
ready, leader_pid = self._parse_sd_notify(data)
if ready or leader_pid is not None:
with self._notify_lock:
if ready:
@@ -1898,7 +2011,9 @@ class NspawnMachine(BaseMachine):
# Poll the socket until we have the container leader PID
while True:
if self.process.poll() is not None:
raise MachineError("systemd-nspawn process exited unexpectedly")
raise MachineError(
f"{self.name}: systemd-nspawn process exited unexpectedly"
)
with self._notify_lock:
is_ready = self._notify_ready

View File

@@ -12,6 +12,23 @@ logger = logging.getLogger(__name__)
class QMPAPIError(RuntimeError):
"""An error response from the QMP API.
>>> error = {"class": "GenericError", "desc": "boom"}
>>> print(QMPAPIError({"error": error, "id": 3}))
<QMP API error related to transaction 3 [GenericError]: boom>
The transaction id is absent from errors that the server hits before it
could read the id:
>>> print(QMPAPIError({"error": error}))
<QMP API error related to transaction None [GenericError]: boom>
>>> QMPAPIError({"error": {"class": "GenericError"}})
Traceback (most recent call last):
RuntimeError: Malformed QMP API error response
"""
def __init__(self, message: dict[str, Any]):
assert "error" in message, "Not an error message!"
error = message["error"]

View File

@@ -13,6 +13,35 @@ class PollingConditionError(Exception):
class PollingCondition:
"""A condition that gets checked periodically while a test runs.
The description comes from the `description` argument. Without one, it
falls back to the docstring of the condition, and then to its name:
>>> from test_driver.logger import CompositeLogger
>>> logger = CompositeLogger([])
>>> def service_runs():
... "The service is running"
>>> def no_docstring():
... pass
>>> PollingCondition(service_runs, logger, description="custom").description
'custom'
>>> PollingCondition(service_runs, logger).description
'The service is running'
>>> PollingCondition(no_docstring, logger).description
'no_docstring'
Log messages include the description:
>>> condition = PollingCondition(service_runs, logger)
>>> condition.nested_message
"Checking polling condition 'The service is running'"
>>> condition.status_message(True)
'Polling condition succeeded: The service is running'
>>> condition.status_message(False)
'Polling condition failed: The service is running'
"""
condition: Callable[[], bool]
interval: dt.timedelta
description: str | None

View File

@@ -461,38 +461,35 @@ in
pkgs.gtk3.out # for gtk-launch program
pkgs.xdg-user-dirs # Update user dirs as described in https://freedesktop.org/wiki/Software/xdg-user-dirs/
pkgs.xdg-user-dirs-gtk # Used to create the default bookmarks
pkgs.gnome-extensions-app
pkgs.gnome-tecla
];
in
mandatoryPackages ++ removeExcluded optionalPackages;
})
# Adapt from https://gitlab.gnome.org/GNOME/gnome-build-meta/-/blob/gnome-51/elements/core/meta-gnome-core-apps.bst
# Adapt from https://gitlab.gnome.org/GNOME/gnome-build-meta/-/blob/gnome-48/elements/core/meta-gnome-core-apps.bst
(lib.mkIf serviceCfg.core-apps.enable {
environment.systemPackages = removeExcluded [
pkgs.baobab
pkgs.decibels
pkgs.epiphany
pkgs.gnome-text-editor
pkgs.gnome-calculator
pkgs.gnome-calendar
pkgs.gnome-characters
pkgs.gnome-clocks
pkgs.gnome-connections
pkgs.gnome-console
pkgs.gnome-contacts
# gnome-disk-utility is controlled below via `programs.gnome-disks`
pkgs.gnome-font-viewer
pkgs.gnome-logs
pkgs.gnome-maps
pkgs.gnome-music
# gnome-software is controlled below via `services.gnome.gnome-software`
pkgs.gnome-system-monitor
pkgs.gnome-text-editor
pkgs.gnome-tecla
pkgs.gnome-weather
pkgs.loupe
pkgs.nautilus
pkgs.papers
pkgs.gnome-connections
pkgs.showtime
pkgs.simple-scan
pkgs.snapshot
@@ -529,7 +526,6 @@ in
];
})
# Note: This is an arbitrary list of packages, there is no "official" list of GNOME games.
(lib.mkIf serviceCfg.games.enable {
environment.systemPackages = removeExcluded [
pkgs.aisleriot
@@ -555,13 +551,18 @@ in
];
})
# Adapt from https://gitlab.gnome.org/GNOME/gnome-build-meta/-/blob/gnome-51/elements/core/meta-gnome-core-developer-tools.bst
# Adapt from https://gitlab.gnome.org/GNOME/gnome-build-meta/-/blob/gnome-48/elements/core/meta-gnome-core-developer-tools.bst
(lib.mkIf serviceCfg.core-developer-tools.enable {
environment.systemPackages = removeExcluded [
pkgs.dconf-editor
pkgs.devhelp
pkgs.d-spy
pkgs.gnome-builder
# boxes would make sense in this option, however
# it doesn't function well enough to be included
# in default configurations.
# https://github.com/NixOS/nixpkgs/issues/60908
# pkgs.gnome-boxes
pkgs.sysprof
];

View File

@@ -353,26 +353,8 @@ in
};
}
]
++ lib.optionals (!config.security.pam.p11.enable) [
{
settings."org/gnome/login-screen" = {
enable-smartcard-authentication = false;
};
}
]
++ [ "${gdm}/share/gdm/greeter-dconf-defaults" ];
programs.dconf.profiles.user.databases = [
{
settings."org/gnome/login-screen" = {
enable-smartcard-authentication = config.security.pam.p11.enable;
# We currently don't provide a `gdm-switchable-auth` PAM service.
enable-switchable-authentication = false;
};
}
];
# Use AutomaticLogin if delay is zero, because it's immediate.
# Otherwise with TimedLogin with zero seconds the prompt is still
# presented and there's a little delay.
@@ -689,85 +671,6 @@ in
];
};
};
# Do not attempt to authenticate via smartcard when the login option
# "Password" is selected (gdm-password).
login.p11Auth = lib.mkIf config.security.pam.p11.enable false;
gdm-smartcard = lib.mkIf config.security.pam.p11.enable {
useDefaultRules = false;
rules = {
auth = utils.pam.autoOrderRules [
{
name = "nologin";
control = "requisite";
modulePath = "${config.security.pam.package}/lib/security/pam_nologin.so";
}
{
name = "faillock";
control = "requisite";
modulePath = "${config.security.pam.package}/lib/security/pam_faillock.so";
settings.preauth = true;
}
{
name = "p11";
control = "required";
modulePath = "${pkgs.pam_p11}/lib/security/pam_p11.so";
args = [
"${pkgs.opensc}/lib/opensc-pkcs11.so"
];
}
{
name = "shells";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_shells.so";
}
{
name = "env";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_env.so";
settings.conffile = "/etc/pam/environment";
settings.readenv = 0;
}
{
name = "gdm";
enable = pamLogin.enable && pamLogin.enableGnomeKeyring;
control = "[success=ok default=1]";
modulePath = "${gdm}/lib/security/pam_gdm.so";
}
{
name = "gnome_keyring";
enable = pamLogin.enable && pamLogin.enableGnomeKeyring;
control = "optional";
modulePath = "${pkgs.gnome-keyring}/lib/security/pam_gnome_keyring.so";
}
];
account = utils.pam.autoOrderRules [
{
name = "login";
control = "include";
modulePath = "login";
}
];
password = utils.pam.autoOrderRules [
{
name = "deny";
control = "required";
modulePath = "${config.security.pam.package}/lib/security/pam_deny.so";
}
];
session = utils.pam.autoOrderRules [
{
name = "login";
control = "include";
modulePath = "login";
}
];
};
};
};
};

View File

@@ -98,7 +98,7 @@ in
- nixpkgs.config.cudaSupport
- nixpkgs.config.rocmSupport
- if stdenv.hostPlatform.isDarwin
- if stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isAarch64
IFF multiple acceleration methods are found to be enabled or if you
haven't set either `cudaSupport or rocmSupport` you will have to

View File

@@ -1,18 +1,5 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Andreas Rammhold <andreas@rammhold.de>
Date: Thu, 9 May 2019 11:15:22 +0200
Subject: [PATCH] add rootprefix to lookup dir paths
systemd does not longer use the UDEVLIBEXEC directory as root for
discovery default udev rules. By adding `$out/lib` to the lookup paths
we should again be able to discover the udev rules amongst other default
files that I might have missed.
---
src/basic/constants.h | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/basic/constants.h b/src/basic/constants.h
index 475d8bf..fa11813 100644
index 475d8bf79a..fa11813911 100644
--- a/src/basic/constants.h
+++ b/src/basic/constants.h
@@ -40,13 +40,15 @@

View File

@@ -260,7 +260,23 @@ in
options.systemd = {
package = mkPackageOption pkgs "systemd" { };
package = mkPackageOption pkgs "systemd" { } // {
# HORRIBLE HACK
# Put back the patch that completely broke most networkd setups.
# This needs to be reverted and either reinstated in the package
# proper, or fixed within the networkd NixOS module, but right now
# we just need things to stop being on fire. -K900
#
# DO NOT remove this without verifying at least
# nixosTests.predictable-interface-names.predictableNetworkdSystemdStage1
apply =
pkg:
pkg.overrideAttrs (prevAttrs: {
patches = prevAttrs.patches or [ ] ++ [
./systemd-search-path.patch
];
});
};
enableStrictShellChecks = mkEnableOption "" // {
description = ''

View File

@@ -60,6 +60,10 @@
# NixOS.
systemd.services."systemd-pcrlogin@".unitConfig.ConditionPathExists =
"/run/systemd/nvpcr/login.auth";
systemd.sockets."systemd-pcrextend" = {
wantedBy = [ "sockets.target" ];
};
}
)
(
@@ -101,6 +105,10 @@
"${cfg.package}/lib/systemd/system-generators/systemd-tpm2-generator"
"${cfg.package}/lib/systemd/systemd-pcrextend"
];
boot.initrd.systemd.sockets."systemd-pcrextend" = {
wantedBy = [ "sockets.target" ];
};
}
)
(

View File

@@ -28,6 +28,8 @@ let
consoles = lib.concatMapStringsSep " " (c: "console=${c}") cfg.qemu.consoles;
runScript = hostPkgs.callPackage ./run-virtiofsd-qemu { };
driveOptions =
{ ... }:
{
@@ -326,33 +328,28 @@ let
''
)}
${lib.optionalString useVirtiofs ''
echo "Starting virtiofs daemons..."
NIX_VIRTIOFS_DIR=$(mktemp -d)
${lib.concatLines (
lib.mapAttrsToList (tag: share: ''
${lib.getExe hostPkgs.virtiofsd} \
--socket-path="$NIX_VIRTIOFS_DIR"/"${tag}" \
--shared-dir="$(readlink -f "${share.source}")" \
${if share.writable then "--writeback" else "--readonly"} \
--sandbox=none \
--seccomp=none \
--cache=${share.cache} \
--no-announce-submounts \
--translate-uid=host:65534:0:1 \
--translate-gid=host:65534:0:1 \
&
'') cfg.sharedDirectories
)}
''}
export NIX_VIRTIOFS_DIR=$(mktemp -d)
# Start QEMU.
exec ${
qemu-common.qemuBinaryWith {
qemuPkg = qemu;
forceAccel = cfg.qemu.forceAccel;
}
} \
exec ${lib.getExe runScript} \
${
lib.optionalString (useVirtiofs && cfg.sharedDirectories != { })
"--virtiofs-paths ${
lib.concatStringsSep " " (
lib.mapAttrsToList (
tag: share:
"${tag}:${share.source}:${share.cache}:${if share.writable then "writeback" else "readonly"}"
) cfg.sharedDirectories
)
}"
} \
-- \
${
qemu-common.qemuBinaryWith {
qemuPkg = qemu;
forceAccel = cfg.qemu.forceAccel;
}
} \
-name ${config.system.name} \
-m ${toString config.virtualisation.memorySize} \
-smp ${toString config.virtualisation.cores} \

View File

@@ -0,0 +1,3 @@
{ python3Packages }:
python3Packages.callPackage ./package.nix { }

View File

@@ -0,0 +1,49 @@
{
lib,
buildPythonApplication,
virtiofsd,
ruff,
setuptools,
ty,
}:
buildPythonApplication {
pname = "run-virtiofsd-qemu";
version = "1.0";
pyproject = true;
src = ./.;
postPatch = ''
substituteInPlace ./run_virtiofsd_qemu/__init__.py \
--replace-fail "@virtiofsd@" "${lib.getExe virtiofsd}"
'';
build-system = [
setuptools
];
propagatedBuildInputs = [
virtiofsd
];
doCheck = true;
nativeCheckInputs = [
ruff
ty
];
checkPhase = ''
echo -e "\x1b[32m## run ty\x1b[0m"
ty check --error-on-warning run_virtiofsd_qemu
echo -e "\x1b[32m## run ruff check\x1b[0m"
ruff check .
echo -e "\x1b[32m## run ruff format\x1b[0m"
ruff format --check --diff .
'';
meta = {
mainProgram = "run-virtiofsd-qemu";
};
}

View File

@@ -0,0 +1,13 @@
[build-system]
requires = ["setuptools"]
build-backend = "setuptools.build_meta"
[project]
name = "run-virtiofsd-qemu"
version = "1.0"
[project.scripts]
run-virtiofsd-qemu = "run_virtiofsd_qemu:main"
[tool.setuptools.packages]
find = {}

View File

@@ -0,0 +1,120 @@
import argparse
import asyncio
import logging
import signal
import subprocess
from contextlib import AsyncExitStack, asynccontextmanager
from os import environ
from pathlib import Path
from sys import exit
logger = logging.getLogger(__name__)
def fatal_error(msg: str):
logger.error(msg)
exit(1)
@asynccontextmanager
async def virtiofsd(virtiofs_dir: Path, tag: str, source: Path, cache: str, flag: str):
socket_path = virtiofs_dir / tag
proc = await asyncio.create_subprocess_exec(
"@virtiofsd@",
f"--socket-path={socket_path}",
f"--shared-dir={source.resolve()}",
f"--{flag}",
"--sandbox=none",
"--seccomp=none",
f"--cache={cache}",
"--no-announce-submounts",
"--translate-uid=host:65534:0:1",
"--translate-gid=host:65534:0:1",
)
loop = asyncio.get_running_loop()
while not await loop.run_in_executor(None, lambda: socket_path.exists()):
if proc.returncode is not None:
fatal_error(f"virtiofsd process for '{tag}' failed to start. Aborting.")
await asyncio.sleep(1)
yield
try:
proc.terminate()
async with asyncio.timeout(2):
await proc.communicate()
except ProcessLookupError:
pass
except subprocess.TimeoutExpired:
logger.warning(
f"virtiofsd process for '{tag}' still running after SIGTERM. Killing."
)
proc.kill()
await proc.communicate()
def extract_arguments() -> tuple[list[tuple[str, Path, str, str]], list[str]]:
parser = argparse.ArgumentParser()
parser.add_argument(
"--virtiofs-paths",
nargs="+",
help="Paths to be exposed with virtiofsd in the format 'tag:source:mode:cache'",
)
args, qemu_args = parser.parse_known_args()
if not qemu_args:
logger.warning("No command to run specified, exiting")
exit(0)
if qemu_args[0] != "--":
fatal_error(
"Usage error: expected command to run separated with '--' from the args pased to this program!"
)
qemu_args.pop(0)
if not qemu_args:
logger.warning("No command to run specified, exiting")
exit(0)
defs = []
for defin in args.virtiofs_paths:
args = defin.split(":")
if len(args) != 4:
fatal_error(
f"--virtio-paths definition '{defin}' doesn't have four params separated by ':'!"
)
defs.append((args[0], Path(args[1]), args[2], args[3]))
return defs, qemu_args
async def amain():
logging.basicConfig(format="%(levelname)s: %(funcName)s: %(message)s")
args, qemu_args = extract_arguments()
try:
virtiofs_dir = Path(environ["NIX_VIRTIOFS_DIR"])
except KeyError:
fatal_error("NIX_VIRTIOFS_DIR is unset!")
async with AsyncExitStack() as virtiofsds:
await asyncio.gather(
*(
virtiofsds.enter_async_context(virtiofsd(virtiofs_dir, *defin))
for defin in args
)
)
proc = await asyncio.create_subprocess_exec(*qemu_args)
loop = asyncio.get_running_loop()
loop.add_signal_handler(signal.SIGTERM, lambda: proc.terminate())
loop.add_signal_handler(signal.SIGINT, lambda: proc.terminate())
await proc.communicate()
def main():
asyncio.run(amain())
if __name__ == "__main__":
asyncio.run(main())

View File

@@ -0,0 +1,4 @@
{
pkgs ? import ../../../.. { },
}:
pkgs.callPackage ./default.nix { }

View File

@@ -31,6 +31,12 @@ in
displayManager.lightdm.extraConfig = ''
logind-check-graphical = false
'';
# `wait_for_x()` establishing a connection that is being teared down
# before having any other connection to X11 causes the X server to reset
# itself. This flag prevents that behavior.
# Context: https://github.com/NixOS/nixpkgs/pull/578540#issuecomment-6593586095
displayManager.xserverArgs = lib.mkAfter [ "-noreset" ];
})
];

View File

@@ -19,15 +19,25 @@
boot.initrd.availableKernelModules = [ "tpm_tis" ];
environment.systemPackages = with pkgs; [ cryptsetup ];
environment.systemPackages = with pkgs; [
cryptsetup
tpm2-tools
];
specialisation.boot-luks.configuration = {
boot.initrd.luks.devices = lib.mkVMOverride {
cryptroot = {
device = "/dev/vdb";
crypttabExtraOpts = [ "tpm2-device=auto" ];
crypttabExtraOpts = [
"tpm2-device=auto"
"tpm2-measure-pcr=yes"
];
};
};
# The volume key measurement is only performed when the OS is explicitly
# marked as measured (or booted through a measuring kernel stub).
boot.kernelParams = [ "systemd.tpm2_measured_os=1" ];
virtualisation.rootDevice = "/dev/mapper/cryptroot";
};
};
@@ -54,5 +64,11 @@
# Boot and decrypt the disk
machine.wait_for_unit("multi-user.target")
assert "/dev/mapper/cryptroot on / type ext4" in machine.succeed("mount")
# The volume key has to be measured into PCR 15 through the
# io.systemd.PCRExtend socket during initrd.
machine.succeed("grep -q volume-key /run/log/systemd/tpm2-measure.log")
pcr = machine.succeed("tpm2_pcrread sha256:15")
assert "15: 0x0000000000000000000000000000000000000000000000000000000000000000" not in pcr, pcr
'';
}

View File

@@ -41,11 +41,6 @@ let
ghostty.pkg = p: p.ghostty;
ghostty.cmd = "ghostty -e $command";
gnome-console.pkg = p: p.gnome-console;
gnome-console.executable = "kgx";
gnome-console.cmd = "kgx -e $command";
gnome-console.kill = true;
gnome-terminal.pkg = p: p.gnome-terminal;
guake.pkg = p: p.guake;
@@ -56,6 +51,10 @@ let
kermit.pkg = p: p.kermit-terminal;
kgx.pkg = p: p.kgx;
kgx.cmd = "kgx -e $command";
kgx.kill = true;
kitty.pkg = p: p.kitty;
kitty.cmd = "kitty $command";

View File

@@ -4,7 +4,7 @@
stdenv,
}:
rec {
version = "9.2.1252";
version = "9.2.1164";
outputs = [
"out"
@@ -15,7 +15,7 @@ rec {
owner = "vim";
repo = "vim";
rev = "v${version}";
hash = "sha256-k5Na69KYXb7kxajpJFv9+vBymApaio7TwHrETudAGrk=";
hash = "sha256-Ymtq7+egq8OydTdzHP/q14MK6p+crKlQwduJ27oDbNU=";
};
enableParallelBuilding = true;

View File

@@ -24,9 +24,9 @@ let
coqPath = lib.makeSearchPath "/lib/coq/${rocq-version}/user-contrib" allPackages;
ocamlPath =
lib.makeSearchPathOutput "dev" "/lib/ocaml/${coq.ocamlPackages.ocaml.version}/site-lib"
([ coq.ocamlPackages.findlib ] ++ allPackages);
ocamlPath = lib.makeSearchPath "/lib/ocaml/${coq.ocamlPackages.ocaml.version}/site-lib" (
[ coq.ocamlPackages.findlib ] ++ allPackages
);
pathEnvVar = if isRocq then "ROCQPATH" else "COQPATH";
in

View File

@@ -64,6 +64,8 @@ let
versionCheckHook,
}:
let
systemdLibs' = systemdLibs.override { withCompression = true; };
docker-meta = {
license = lib.licenses.asl20;
maintainers = with lib.maintainers; [
@@ -190,7 +192,7 @@ let
++ lib.optionals (lib.versionAtLeast version "29.0.0") [ nftables ]
++ lib.optionals withLvm [ lvm2 ]
++ lib.optionals withBtrfs [ btrfs-progs ]
++ lib.optionals withSystemd [ systemdLibs ]
++ lib.optionals withSystemd [ systemdLibs' ]
++ lib.optionals withSeccomp [ libseccomp ];
postPatch = ''

View File

@@ -200,30 +200,37 @@ if [[ "$NIX_DONT_SET_RPATH_@suffixSalt@" != 1 && "$linkType" != static-pie ]]; t
# so, add the directory to the rpath.
# It's important to add the rpath in the order of -L..., so
# the link time chosen objects will be those of runtime linking.
declare -A rpaths seenLibDirs
declare -A rpaths
for dir in ${libDirs+"${libDirs[@]}"}; do
# The same directory is often passed many times, such as from
# NIX_LDFLAGS; it would give the same result each time.
if [ -n "${seenLibDirs[$dir]:-}" ]; then
# If the path is in the store, do not resolve any symlinks and add it to the rpath.
# Resolving symlinks in the store breaks bootstrapping, see issue #454199.
# If it is outside the store, resolve symlinks step by step until it falls
# into the store or it becomes not a symlink.
# Always canonicalize the path before checking it is in the store or not.
if dir2=$(realpath -s "$dir"); then
dir="$dir2"
else
continue
fi
seenLibDirs["$dir"]=1
# Find where the directory is, following symlinks outside the store,
# and in it only where needed; see resolveLibDir. Skip directories
# that do not exist, in which the linker cannot find libraries either.
if ! [ -d "$dir" ] || ! resolveLibDir "$dir"; then
continue
fi
dir="$resolvedPath"
while [ -z "${rpaths[$dir]:-}" ] && [[ "$dir" != "${NIX_STORE:-}"/* ]] && [ -L "$dir" ]; do
if dir2=$(readlink "$dir"); then
dir="dir2"
else
break
fi
if dir2=$(realpath -s "$dir"); then
dir="dir2"
else
break
fi
done
# If the path turns out to be outside the store, we do not add it to rpath.
# This typically happens for libraries in /tmp that are later
# copied to $out/lib. If not, we're screwed.
if [ -n "${rpaths[$dir]:-}" ] || [[ "$dir" != "${NIX_STORE:-}"/* ]]; then
continue
fi
# Every name in libs is that of a shared library, ending in .so or
# containing .so., so the rest of the directory can be skipped.
for path in "$dir"/*.so*; do
for path in "$dir"/*; do
file="${path##*/}"
if [ "${libs[$file]:-}" ]; then
# This library may have been provided by a previous directory,

View File

@@ -129,8 +129,6 @@ lib.makeOverridable (
"pki"
# Custom dconf profiles
"dconf"
# EGL platform definitions (required by nvidia-x11)
"egl"
];
in
map (path: "/etc/${path}") files;

View File

@@ -302,7 +302,7 @@ lib.extendMkDerivation {
if [ "$cmd" = "test" ]; then
flags+=(-vet=off)
concatTo flags checkFlags
flags+=($checkFlags)
fi
local OUT

View File

@@ -109,7 +109,7 @@ fn add_dependencies<P: AsRef<Path> + AsRef<OsStr> + std::fmt::Debug>(
.position(|x| *x == 0)
.unwrap_or(note.desc.len())];
let parsed = serde_json::from_slice::<Vec<DLOpenNote>>(payload)?;
for mut parsed_note in parsed {
for parsed_note in parsed {
if dlopen.use_priority
>= parsed_note.priority.unwrap_or(DLOpenPriority::Recommended)
|| parsed_note
@@ -117,7 +117,9 @@ fn add_dependencies<P: AsRef<Path> + AsRef<OsStr> + std::fmt::Debug>(
.map(|f| dlopen.features.contains(&f))
.unwrap_or(false)
{
dlopen_libraries.append(&mut parsed_note.soname);
// SONAMEs in one note are ordered alternatives, not
// independent dependencies.
dlopen_libraries.push(parsed_note.soname);
}
}
}
@@ -137,39 +139,38 @@ fn add_dependencies<P: AsRef<Path> + AsRef<OsStr> + std::fmt::Debug>(
.map(|p| Box::<Path>::from(Path::new(p)))
.collect::<Vec<_>>();
for line in elf
for sonames in elf
.libraries
.into_iter()
.map(|s| s.to_string())
.map(|s| vec![s.to_string()])
.chain(dlopen_libraries)
{
let mut found = false;
for path in &rpaths_as_path {
let lib = path.join(&line);
if lib.exists() {
// No need to recurse. The queue will bring it back round.
queue.push_back(StorePath {
path: Box::from(lib.as_path()),
dlopen: dlopen.clone(),
});
found = true;
break;
}
}
if !found {
let library = sonames
.iter()
.flat_map(|soname| rpaths_as_path.iter().map(move |path| path.join(soname)))
.find(|lib| lib.exists());
if let Some(lib) = library {
// No need to recurse. The queue will bring it back round.
queue.push_back(StorePath {
path: lib.into_boxed_path(),
dlopen: dlopen.clone(),
});
} else {
// In Nix, glibc's own libraries lack rpath entries pointing to
// themselves, so the dynamic linker (ld-linux-*.so.*) and libc.so.*
// can never be resolved through rpath alone. They are always present
// in the initrd: the linker via elf.interpreter above, and libc via
// at least one binary's rpath. Suppress these known-benign cases.
// See also: the ld*.so.? skip in stage-1.nix findLibs.
let is_glibc_runtime = (line.starts_with("ld-") && line.contains(".so"))
|| line.starts_with("libc.so");
let is_glibc_runtime = matches!(
sonames.as_slice(),
[s] if (s.starts_with("ld-") && s.contains(".so")) || s.starts_with("libc.so")
);
if !is_glibc_runtime {
eprintln!(
"Warning: Couldn't satisfy dependency {} for {:?}",
line,
sonames.join(" or "),
OsStr::new(&source)
);
}
@@ -314,13 +315,10 @@ fn main() -> eyre::Result<()> {
let args: Vec<String> = env::args().collect();
let contents =
fs::read(&args[1]).wrap_err_with(|| format!("failed to open file {:?}", &args[1]))?;
let input = serde_json::from_slice::<Vec<StoreInput>>(&contents)
.wrap_err_with(|| {
let text = String::from_utf8_lossy(&contents);
format!("failed to parse JSON '{}' in {:?}",
text,
&args[1])
})?;
let input = serde_json::from_slice::<Vec<StoreInput>>(&contents).wrap_err_with(|| {
let text = String::from_utf8_lossy(&contents);
format!("failed to parse JSON '{}' in {:?}", text, &args[1])
})?;
let output = &args[2];
let out_path = Path::new(output);

View File

@@ -20,8 +20,6 @@
pname = "prefetch-npm-deps";
version = (lib.importTOML ./Cargo.toml).package.version;
__structuredAttrs = true;
src = lib.cleanSourceWith {
src = ./.;
filter =

View File

@@ -45,26 +45,6 @@ lib.extendMkDerivation {
strictDeps = true;
# OCaml libraries, and the dependencies they propagate, are only needed
# to build other packages. Unless the package chooses its outputs,
# those are installed into "dev", rather than "out", to minimize the
# "out" runtime closure. Man pages and documentation go to "man" and
# "doc".
outputs =
args.outputs or [
"out"
"dev"
"man"
"doc"
];
# The findlib setup hook always points OCAMLFIND_DESTDIR at $out, so
# override it after all setup hooks have run.
postHook = ''
export OCAMLFIND_DESTDIR="''${!outputDev}/lib/ocaml/${ocaml.version}/site-lib/"
''
+ args.postHook or "";
inherit enableParallelBuilding;
dontAddStaticConfigureFlags = true;
configurePlatforms = [ ];
@@ -87,15 +67,12 @@ lib.extendMkDerivation {
args.installPhase or ''
runHook preInstall
dune install --prefix $out --libdir $OCAMLFIND_DESTDIR ${lib.concatStringsSep " " dunePackages} \
${lib.optionalString (lib.versionAtLeast Dune.version "2.9") ''
--docdir "''${!outputDoc}/share/doc" --mandir "''${!outputMan}/share/man" --etcdir "$out/etc" \
''} ${lib.optionalString (lib.versionAtLeast Dune.version "3.0") ''
--bindir "''${!outputBin}/bin" --datadir "$out/share"
''}
# Not every package installs something into each output.
for output in $(getAllOutputNames); do
mkdir -p "''${!output}"
done
${
if lib.versionAtLeast Dune.version "2.9" then
"--docdir $out/share/doc --mandir $out/share/man"
else
""
}
runHook postInstall
'';
@@ -106,22 +83,8 @@ lib.extendMkDerivation {
runHook postCheck
'';
# With several outputs, multiple-outputs.sh passes autoconf-style
# --bindir/--libdir/--mandir/... flags to ./configure. The configure
# scripts shipped by dune packages are hand-written and reject them.
setOutputFlags = args.setOutputFlags or false;
meta =
let
meta = args.meta or { };
# meta is often copied from another package, which may have other
# outputs. Keep the default if none of them are left.
outputsToInstall = lib.intersectLists finalAttrs.outputs (meta.outputsToInstall or [ ]);
in
removeAttrs meta [ "outputsToInstall" ]
// {
platforms = meta.platforms or ocaml.meta.platforms;
}
// lib.optionalAttrs (outputsToInstall != [ ]) { inherit outputsToInstall; };
meta = (args.meta or { }) // {
platforms = args.meta.platforms or ocaml.meta.platforms;
};
};
}

View File

@@ -1,223 +1,57 @@
import functools
import hashlib
import json
import os
import multiprocessing as mp
import re
import shutil
import subprocess
import sys
import tempfile
import threading
import tomllib
from concurrent.futures import FIRST_EXCEPTION, Future, ThreadPoolExecutor, wait
from dataclasses import dataclass, field
from os.path import islink, realpath
from pathlib import Path
from typing import Any, cast
from typing import Any, TypedDict, cast
from urllib.parse import unquote
import requests
import tomli_w
from requests import Session
from requests.adapters import HTTPAdapter, Retry
# Constants for controlling how the crates are downloaded from the registries via `requests`
# These do not affect the fetching of git dependencies
MAX_WORKERS = min(5, os.cpu_count() or 1) # number of workers in the ThreadPoolExecutor
CONNECT_TIMEOUT = 2 # max seconds for establishing initial connection
READ_TIMEOUT = 10 # max seconds between receiving data packets
TIMEOUT = (CONNECT_TIMEOUT, READ_TIMEOUT)
RETRY_COUNT = 3 # number of retries for fetching an url
BACKOFF_FACTOR = 0.5 # seconds to wait between retries (gets multiplied by 2 after every retry)
# If for some reason our custom User-Agent value starts getting rejected, we could
# set the User-Agent to the value that cargo uses, e.g.: "cargo/1.95.0 (f2d3ce0bd 2026-03-21)"
USER_AGENT = "nixpkgs-fetchCargoVendor/2 (https://github.com/NixOS/nixpkgs)"
eprint = functools.partial(print, file=sys.stderr)
@dataclass
class RegistrySource:
raw: str
url: str
is_sparse: bool
ind: int = field(init=False)
def load_toml(path: Path) -> dict[str, Any]:
with open(path, "rb") as f:
return tomllib.load(f)
@dataclass
class RegistryPackage:
name: str
version: str
source: RegistrySource
checksum: str
def get_lockfile_version(cargo_lock_toml: dict[str, Any]) -> int:
# lockfile v1 and v2 don't have the `version` key, so assume v2
version = cargo_lock_toml.get("version", 2)
# TODO: add logic for differentiating between v1 and v2
return version
GIT_SOURCE_REGEX = re.compile(r"git\+(?P<url>[^?]+)(\?(?P<type>rev|tag|branch)=(?P<value>.*))?#(?P<git_sha_rev>.*)")
@dataclass
class GitSource:
raw: str
url: str
type: str | None
value: str | None
git_sha_rev: str
ind: int = field(init=False)
@dataclass
class GitPackage:
name: str
version: str
source: GitSource
Source = RegistrySource | GitSource
Package = RegistryPackage | GitPackage
@dataclass
class Lockfile:
version: int
sources: list[Source]
packages: list[Package]
def parse_git_source(raw_source: str, lockfile_version: int) -> GitSource:
match = GIT_SOURCE_REGEX.match(raw_source)
if match is None:
raise Exception(f"Unable to process git source: {raw_source}.")
parsed_dict = match.groupdict(default=None)
url = cast(str, parsed_dict["url"])
git_sha_rev = cast(str, parsed_dict["git_sha_rev"])
source = GitSource(raw_source, url, parsed_dict["type"], parsed_dict["value"], git_sha_rev)
# the source URL is URL-encoded in lockfile_version >=4
# since we just used regex to parse it we have to manually decode the escaped branch/tag name
if lockfile_version >= 4 and source.value is not None:
source.value = unquote(source.value)
return source
def parse_source(raw_source: str, lockfile_version: int) -> Source:
if raw_source.startswith("git+"):
return parse_git_source(raw_source, lockfile_version)
elif raw_source.startswith("registry+"):
return RegistrySource(raw=raw_source, url=raw_source[9:], is_sparse=False)
elif raw_source.startswith("sparse+"):
return RegistrySource(raw=raw_source, url=raw_source[7:].rstrip("/"), is_sparse=True)
raise Exception(f"Cannot process source: {raw_source}")
def load_lockfile(path: Path) -> Lockfile:
with path.open("rb") as f:
cargo_lock_toml = tomllib.load(f)
# The `version` key missing means either lockfile v1 or v2. We assume v2 for now.
lockfile_version = cargo_lock_toml.get("version", 2)
raw_packages: list[dict[str, str]] = cargo_lock_toml["package"]
sources: list[Source] = []
raw_source_to_source: dict[str, Source] = {}
# we'll mark every source with an index in order of appearance
# both git and registry sources have a different incrementing index
# we reserve registry index 0 for both of the default crates-io registries
for raw_source in ["registry+https://github.com/rust-lang/crates.io-index", "sparse+https://index.crates.io/"]:
source = parse_source(raw_source, lockfile_version)
source.ind = 0
sources.append(source)
raw_source_to_source[source.raw] = source
next_registry_ind = 1
next_git_ind = 0
git_selector_tuple_to_git_ind: dict[tuple[str, str | None, str | None], int] = {}
for raw_pkg in raw_packages:
raw_source = raw_pkg.get("source", None)
if raw_source is None: # Skip local dependencies
continue
if raw_source in raw_source_to_source:
continue
source = parse_source(raw_source, lockfile_version)
match source:
case RegistrySource():
source.ind = next_registry_ind
next_registry_ind += 1
case GitSource():
# git sources may get the same `ind` value if their selectors match
tup = (source.url, source.type, source.value)
if tup not in git_selector_tuple_to_git_ind:
git_selector_tuple_to_git_ind[tup] = next_git_ind
next_git_ind += 1
source.ind = git_selector_tuple_to_git_ind[tup]
sources.append(source)
raw_source_to_source[source.raw] = source
packages: list[Package] = []
for raw_pkg in raw_packages:
name = raw_pkg["name"]
version = raw_pkg["version"]
raw_source = raw_pkg.get("source", None)
if raw_source is None: # Skip local dependencies
continue
source = raw_source_to_source[raw_source]
match source:
case RegistrySource():
checksum = raw_pkg.get("checksum", None)
# lockfile v1 has the checksum values in a separate metadata table
if checksum is None:
lockfile_version = 1
checksum_key = f"checksum {name} {version} ({source.raw})"
checksum = cargo_lock_toml["metadata"][checksum_key]
pkg = RegistryPackage(name, version, source, checksum)
case GitSource():
pkg = GitPackage(name, version, source)
packages.append(pkg)
return Lockfile(lockfile_version, sources, packages)
_local = threading.local()
def get_session() -> Session:
if hasattr(_local, "session"):
return _local.session
def create_http_session() -> requests.Session:
retries = Retry(
total=RETRY_COUNT,
backoff_factor=BACKOFF_FACTOR,
total=5,
backoff_factor=0.5,
status_forcelist=[500, 502, 503, 504]
)
session = Session()
session.headers["User-Agent"] = USER_AGENT
session = requests.Session()
session.headers["User-Agent"] = "nixpkgs-fetchCargoVendor/2 (https://github.com/NixOS/nixpkgs)"
session.mount('http://', HTTPAdapter(max_retries=retries))
session.mount('https://', HTTPAdapter(max_retries=retries))
_local.session = session
return session
def download_file_with_checksum(url: str, destination_path: Path) -> str:
session = get_session()
def download_file_with_checksum(session: requests.Session, url: str, destination_path: Path) -> str:
sha256_hash = hashlib.sha256()
with session.get(url, stream=True, timeout=TIMEOUT) as response:
response.raise_for_status()
with destination_path.open("wb") as file:
with session.get(url, stream=True) as response:
if not response.ok:
raise Exception(f"Failed to fetch file from {url}. Status code: {response.status_code}")
with open(destination_path, "wb") as file:
for chunk in response.iter_content(1024): # Download in chunks
if chunk: # Filter out keep-alive chunks
file.write(chunk)
@@ -228,157 +62,117 @@ def download_file_with_checksum(url: str, destination_path: Path) -> str:
return checksum
# Fetch the config.json file and get the .dl key from it
# See: https://doc.rust-lang.org/cargo/reference/registry-index.html#index-configuration
def fetch_dl_for_registry_source(source: RegistrySource) -> str:
# We hardcode the .dl value for crates-io registries to avoid having to clone the git repo, saving a few seconds
if source.ind == 0:
return "https://static.crates.io/crates"
def get_download_url_for_tarball(pkg: dict[str, Any]) -> str:
# TODO: support other registries
# maybe fetch config.json from the registry root and get the dl key
# See: https://doc.rust-lang.org/cargo/reference/registry-index.html#index-configuration
if pkg["source"] != "registry+https://github.com/rust-lang/crates.io-index":
raise Exception("Only the default crates.io registry is supported.")
eprint(f'Fetching .dl value for registry "{source.url}"')
if source.is_sparse:
url = source.url + "/config.json"
# https://doc.rust-lang.org/cargo/reference/registry-web-api.html#web-api
headers = {
"Content-Type": "application/json",
"Accept": "application/json",
}
session = get_session()
with session.get(url, headers=headers, timeout=TIMEOUT) as response:
response.raise_for_status()
registry_config: dict[str, str] = response.json()
else:
tmp_dir = Path(tempfile.mkdtemp())
# use spare-checkout to only get the config.json file from the registry's git repo
# --quiet is deliberately not used to be able to debug if something goes wrong
cmd = ["nix-prefetch-git", "--builder", "--url", source.url, "--rev", "HEAD", "--sparse-checkout", "config.json", "--out", str(tmp_dir)]
subprocess.check_output(cmd)
with (tmp_dir / "config.json").open("rb") as f:
registry_config: dict[str, str] = json.load(f)
dl = registry_config["dl"]
auth_required = registry_config.get("auth-required", False)
if auth_required:
raise Exception(f'Registry "{source.url}" requires authentication, but it is not yet implemented!')
return dl
# Use static.crates.io (CDN) instead of crates.io/api to avoid the 1 req/sec
# rate limit on the API servers.
return f"https://static.crates.io/crates/{pkg["name"]}/{pkg["version"]}/download"
# See: https://doc.rust-lang.org/cargo/reference/registry-index.html#index-files
def name_to_prefix(name: str) -> str:
nl = len(name)
if nl <= 2:
return str(nl)
if nl == 3:
return "3/" + name[0]
return name[0:2] + "/" + name[2:4]
def download_tarball(session: requests.Session, pkg: dict[str, Any], out_dir: Path) -> None:
url = get_download_url_for_tarball(pkg)
filename = f"{pkg["name"]}-{pkg["version"]}.tar.gz"
# See: https://doc.rust-lang.org/cargo/reference/registry-index.html#index-configuration
def make_download_url_for_tarball(pkg: RegistryPackage, dl: str) -> str:
# Assume default substitutions if no substitutions are specified
url = dl if "}" in dl else dl + "/{crate}/{version}/download"
# TODO: allow legacy checksum specification, see importCargoLock for example
# also, don't forget about the other usage of the checksum
expected_checksum = pkg["checksum"]
prefix = name_to_prefix(pkg.name)
url = url.replace("{crate}", pkg.name)
url = url.replace("{version}", pkg.version)
url = url.replace("{prefix}", prefix)
url = url.replace("{lowerprefix}", prefix.lower())
url = url.replace("{sha256-checksum}", pkg.checksum)
return url
tarball_out_dir = out_dir / "tarballs" / filename
eprint(f"Fetching {url} -> tarballs/{filename}")
def download_crate_tarball(url: str, out_path: Path, expected_checksum: str) -> None:
out_path.parent.mkdir(parents=True, exist_ok=True)
eprint(f"Fetching {url} -> {out_path}")
calculated_checksum = download_file_with_checksum(url, out_path)
calculated_checksum = download_file_with_checksum(session, url, tarball_out_dir)
if calculated_checksum != expected_checksum:
raise Exception(f"Hash mismatch! File fetched from {url} had checksum {calculated_checksum}, expected {expected_checksum}.")
def download_git_tree(url: str, git_sha_rev: str, out_dir: Path) -> None:
tree_out_dir = out_dir / "git" / git_sha_rev
# This could happen if different selectors point to the same git_sha_rev
if tree_out_dir.exists():
eprint(f"Skipping fetching {url}#{git_sha_rev} as it has already been downloaded")
return
tree_out_dir.mkdir(parents=True)
eprint(f"Fetching {url}#{git_sha_rev} -> git/{git_sha_rev}")
cmd = ["nix-prefetch-git", "--builder", "--quiet", "--fetch-submodules", "--url", url, "--rev", git_sha_rev, "--out", str(tree_out_dir)]
subprocess.check_output(cmd)
def make_tarball_relpath(pkg: RegistryPackage) -> Path:
# Instead of .tar.gz we could have used the .crate extension
# But we keep using .tar.gz for backwards compat
filename = f'{pkg.name}-{pkg.version}.tar.gz'
GIT_SOURCE_REGEX = re.compile("git\\+(?P<url>[^?]+)(\\?(?P<type>rev|tag|branch)=(?P<value>.*))?#(?P<git_sha_rev>.*)")
# For backwards compat, all crates.io crates (where source.ind == 0)
# are stored directly in tarballs/
# Crates from other registries are stored in tarballs/registry-{ind}/
if pkg.source.ind == 0:
reldir = Path("tarballs")
else:
reldir = Path("tarballs") / f"registry-{pkg.source.ind}"
return reldir / filename
class GitSourceInfo(TypedDict):
url: str
type: str | None
value: str | None
git_sha_rev: str
def parse_git_source(source: str, lockfile_version: int) -> GitSourceInfo:
match = GIT_SOURCE_REGEX.match(source)
if match is None:
raise Exception(f"Unable to process git source: {source}.")
source_info = cast(GitSourceInfo, match.groupdict(default=None))
# the source URL is URL-encoded in lockfile_version >=4
# since we just used regex to parse it we have to manually decode the escaped branch/tag name
if lockfile_version >= 4 and source_info["value"] is not None:
source_info["value"] = unquote(source_info["value"])
return source_info
def create_vendor_staging(lockfile_path: Path, out_dir: Path) -> None:
lockfile = load_lockfile(lockfile_path)
cargo_lock_toml = load_toml(lockfile_path)
lockfile_version = get_lockfile_version(cargo_lock_toml)
git_packages: list[dict[str, Any]] = []
registry_packages: list[dict[str, Any]] = []
for pkg in cargo_lock_toml["package"]:
# ignore local dependenices
if "source" not in pkg.keys():
eprint(f"Skipping local dependency: {pkg["name"]}")
continue
source = pkg["source"]
if source.startswith("git+"):
git_packages.append(pkg)
elif source.startswith("registry+"):
registry_packages.append(pkg)
else:
raise Exception(f"Can't process source: {source}.")
git_sha_rev_to_url: dict[str, str] = {}
for pkg in git_packages:
source_info = parse_git_source(pkg["source"], lockfile_version)
git_sha_rev_to_url[source_info["git_sha_rev"]] = source_info["url"]
out_dir.mkdir(exist_ok=True)
shutil.copy(lockfile_path, out_dir / "Cargo.lock")
git_sources = [source for source in lockfile.sources if isinstance(source, GitSource)]
registry_sources = [source for source in lockfile.sources if isinstance(source, RegistrySource)]
registry_packages = [pkg for pkg in lockfile.packages if isinstance(pkg, RegistryPackage)]
# fetch git trees sequentially, since fetching concurrently leads to flaky behaviour
if len(git_packages) != 0:
(out_dir / "git").mkdir()
for git_sha_rev, url in git_sha_rev_to_url.items():
download_git_tree(url, git_sha_rev, out_dir)
# We fetch git trees sequentially because fetching concurrently seemed to cause flaky behaviour
for source in git_sources:
download_git_tree(source.url, source.git_sha_rev, out_dir)
raw_registry_source_to_dl: dict[str, str] = {}
for source in registry_sources:
dl = fetch_dl_for_registry_source(source)
eprint(f'Using .dl value of "{dl}" for registry "{source.raw}"')
raw_registry_source_to_dl[source.raw] = dl
eprint(f"Downloading crate tarballs with {MAX_WORKERS} workers...")
with ThreadPoolExecutor(max_workers=MAX_WORKERS) as executor:
futures: list[Future[None]] = []
for pkg in registry_packages:
dl = raw_registry_source_to_dl[pkg.source.raw]
url = make_download_url_for_tarball(pkg, dl)
out_path = out_dir / make_tarball_relpath(pkg)
future = executor.submit(download_crate_tarball, url, out_path, pkg.checksum)
futures.append(future)
# fail early if a worker raises an exception
done, _ = wait(futures, return_when=FIRST_EXCEPTION)
for f in done:
e = f.exception()
if e is None:
continue
executor.shutdown(cancel_futures=True)
raise Exception(f"Failed to download tarball: {e}")
# run tarball download jobs in parallel, with at most 5 concurrent download jobs
with mp.Pool(min(5, mp.cpu_count())) as pool:
if len(registry_packages) != 0:
(out_dir / "tarballs").mkdir()
session = create_http_session()
tarball_args_gen = ((session, pkg, out_dir) for pkg in registry_packages)
pool.starmap(download_tarball, tarball_args_gen)
def get_manifest_metadata(manifest_path: Path) -> dict[str, Any]:
cmd = ["cargo", "metadata", "--format-version", "1", "--no-deps", "--manifest-path", str(manifest_path)]
output = subprocess.check_output(cmd, cwd=manifest_path.parent)
output = subprocess.check_output(cmd)
return json.loads(output)
@@ -450,7 +244,8 @@ def copy_and_patch_git_crate_subtree(git_tree: Path, crate_name: str, crate_out_
shutil.copytree(crate_tree, crate_out_dir, ignore=ignore_func)
crate_out_dir.chmod(0o755)
manifest_data = crate_manifest_path.read_text()
with open(crate_manifest_path, "r") as f:
manifest_data = f.read()
if "workspace" in manifest_data:
crate_manifest_metadata = get_manifest_metadata(crate_manifest_path)
@@ -473,16 +268,16 @@ def extract_crate_tarball_contents(tarball_path: Path, crate_out_dir: Path) -> N
subprocess.check_output(cmd)
def make_git_source_selector(source: GitSource) -> dict[str, str]:
def make_git_source_selector(source_info: GitSourceInfo) -> dict[str, str]:
selector = {}
selector["git"] = source.url
if source.type is not None:
selector[source.type] = source.value
selector["git"] = source_info["url"]
if source_info["type"] is not None:
selector[source_info["type"]] = source_info["value"]
return selector
def make_registry_source_selector(source: RegistrySource) -> dict[str, str]:
registry = source.raw if source.is_sparse else source.url
def make_registry_source_selector(source: str) -> dict[str, str]:
registry = source[9:] if source.startswith("registry+") else source
selector = {}
selector["registry"] = registry
return selector
@@ -493,9 +288,14 @@ def create_vendor(vendor_staging_dir: Path, out_dir: Path) -> None:
out_dir.mkdir(exist_ok=True)
shutil.copy(lockfile_path, out_dir / "Cargo.lock")
lockfile = load_lockfile(lockfile_path)
cargo_lock_toml = load_toml(lockfile_path)
lockfile_version = get_lockfile_version(cargo_lock_toml)
source_to_ind: dict[str, str] = {}
selector_to_ind: dict[tuple, str] = {}
source_config = {}
next_registry_ind = 0
next_git_ind = 0
def add_source_replacement(
orig_key: str,
@@ -508,96 +308,112 @@ def create_vendor(vendor_staging_dir: Path, out_dir: Path) -> None:
source_config[orig_key] = orig_selector
source_config[orig_key]["replace-with"] = vendored_key
# we reserve registry index 0 for crates-io
source_to_ind["registry+https://github.com/rust-lang/crates.io-index"] = "registry-0"
source_to_ind["sparse+https://index.crates.io/"] = "registry-0"
add_source_replacement(
orig_key="crates-io",
orig_selector={}, # there is an internal selector defined for the `crates-io` source
vendored_key="vendored-source-registry-0",
vendored_dir="@vendor@/source-registry-0"
)
next_registry_ind += 1
processed_git_inds = set()
for pkg in cargo_lock_toml["package"]:
# ignore local dependencies
if "source" not in pkg.keys():
continue
source: str = pkg["source"]
if source in source_to_ind:
continue
for source in lockfile.sources:
match source:
case RegistrySource():
if source.ind == 0: # crates-io already handled separately above
continue
if source.startswith("git+"):
source_info = parse_git_source(source, lockfile_version)
selector = make_git_source_selector(source_info)
selector_key = (source_info["url"], source_info["type"], source_info["value"])
if selector_key in selector_to_ind:
ind = selector_to_ind[selector_key]
else:
ind = f"git-{next_git_ind}"
next_git_ind += 1
selector_to_ind[selector_key] = ind
add_source_replacement(
orig_key=f"original-source-registry-{source.ind}",
orig_selector=make_registry_source_selector(source),
vendored_key=f"vendored-source-registry-{source.ind}",
vendored_dir=f"@vendor@/source-registry-{source.ind}"
orig_key=f"original-source-{ind}",
orig_selector=selector,
vendored_key=f"vendored-source-{ind}",
vendored_dir=f"@vendor@/source-{ind}"
)
case GitSource():
# In some cases multiple git sources can have the same selector, thus the same git ind
# but source replacements can't be made for the same selector multiple times
if source.ind in processed_git_inds:
continue
processed_git_inds.add(source.ind)
elif source.startswith("registry+") or source.startswith("sparse+"):
ind = f"registry-{next_registry_ind}"
next_registry_ind += 1
selector = make_registry_source_selector(source)
add_source_replacement(
orig_key=f"original-source-{ind}",
orig_selector=selector,
vendored_key=f"vendored-source-{ind}",
vendored_dir=f"@vendor@/source-{ind}"
)
else:
raise Exception(f"Can't process source: {source}.")
add_source_replacement(
orig_key=f"original-source-git-{source.ind}",
orig_selector=make_git_source_selector(source),
vendored_key=f"vendored-source-git-{source.ind}",
vendored_dir=f"@vendor@/source-git-{source.ind}"
)
source_to_ind[source] = ind
config_path = out_dir / ".cargo" / "config.toml"
config_path.parent.mkdir()
with config_path.open("wb") as config_file:
with open(config_path, "wb") as config_file:
tomli_w.dump({"source": source_config}, config_file)
for pkg in lockfile.packages:
match pkg:
case RegistryPackage():
crate_out_dir = out_dir / f"source-registry-{pkg.source.ind}" / f"{pkg.name}-{pkg.version}"
crate_out_dir.parent.mkdir(exist_ok=True)
for pkg in cargo_lock_toml["package"]:
tarball_path = vendor_staging_dir / make_tarball_relpath(pkg)
# ignore local dependenices
if "source" not in pkg.keys():
continue
extract_crate_tarball_contents(tarball_path, crate_out_dir)
source: str = pkg["source"]
source_ind = source_to_ind[source]
crate_dir_name = f"{pkg["name"]}-{pkg["version"]}"
source_dir_name = f"source-{source_ind}"
crate_out_dir = out_dir / source_dir_name / crate_dir_name
crate_out_dir.parent.mkdir(exist_ok=True)
# non-git based crates need the package checksum at minimum
with (crate_out_dir / ".cargo-checksum.json").open("w") as f:
json.dump({"files": {}, "package": pkg.checksum}, f)
if source.startswith("git+"):
case GitPackage():
crate_out_dir = out_dir / f"source-git-{pkg.source.ind}" / f"{pkg.name}-{pkg.version}"
crate_out_dir.parent.mkdir(exist_ok=True)
source_info = parse_git_source(source, lockfile_version)
if crate_out_dir.exists():
raise Exception(
f"{crate_out_dir} already exists!\n"
"This likely due to multiple packages having the same name, version and git selector, but not the same locked git revision\n"
"As a workaround, change all conflicting packages to have different git selectors\n"
"e.g. specifying an exact rev=<hash> selector for each affected package in both Cargo.toml and Cargo.lock\n"
"If it is not possible or difficult to do so (e.g. it's a transient dependency), as a hack, you could also consider keeping\n"
"the package with the most up-to-date revision and removing all other duplicated entries from Cargo.lock"
)
git_sha_rev = source_info["git_sha_rev"]
git_tree = vendor_staging_dir / "git" / git_sha_rev
git_sha_rev = pkg.source.git_sha_rev
git_tree = vendor_staging_dir / "git" / git_sha_rev
copy_and_patch_git_crate_subtree(git_tree, pkg["name"], crate_out_dir)
copy_and_patch_git_crate_subtree(git_tree, pkg.name, crate_out_dir)
# git based crates allow having no checksum information
with open(crate_out_dir / ".cargo-checksum.json", "w") as f:
json.dump({"files": {}}, f)
# git based crates allow having no checksum information
with (crate_out_dir / ".cargo-checksum.json").open("w") as f:
json.dump({"files": {}}, f)
elif source.startswith("registry+") or source.startswith("sparse+"):
filename = f"{pkg["name"]}-{pkg["version"]}.tar.gz"
# TODO: change this when non-crates-io registries are supported
dir_name = "tarballs"
tarball_path = vendor_staging_dir / dir_name / filename
extract_crate_tarball_contents(tarball_path, crate_out_dir)
# non-git based crates need the package checksum at minimum
with open(crate_out_dir / ".cargo-checksum.json", "w") as f:
json.dump({"files": {}, "package": pkg["checksum"]}, f)
else:
raise Exception(f"Can't process source: {source}.")
def main() -> None:
subcommand = sys.argv[1]
subcommand_func_dict = {
"create-vendor-staging": lambda: create_vendor_staging(
lockfile_path=Path(sys.argv[2]),
out_dir=Path(sys.argv[3])
),
"create-vendor": lambda: create_vendor(
vendor_staging_dir=Path(sys.argv[2]),
out_dir=Path(sys.argv[3])
)
"create-vendor-staging": lambda: create_vendor_staging(lockfile_path=Path(sys.argv[2]), out_dir=Path(sys.argv[3])),
"create-vendor": lambda: create_vendor(vendor_staging_dir=Path(sys.argv[2]), out_dir=Path(sys.argv[3]))
}
subcommand_func = subcommand_func_dict.get(subcommand)

View File

@@ -8,11 +8,6 @@ cargoSetupPostUnpackHook() {
# it writable. If we're using a tarball, the unpackFile hook already handles
# this for us automatically.
if [ -z $cargoVendorDir ]; then
if [ -z "$cargoDeps" ]; then
echo "ERROR: Missing cargoDeps"
exit 1
fi
if [ -d "$cargoDeps" ]; then
local dest=$(stripHash "$cargoDeps")
cp -Lr --reflink=auto -- "$cargoDeps" "$dest"
@@ -91,77 +86,6 @@ cargoSetupPostPatchHook() {
echo "Finished cargoSetupPostPatchHook"
}
cargoUseSystemLibs() {
# Sentinel directory that doesn't exist. For packages
# Where you tell it directories, but can't force it to only
# use system libraries
#
# Note that this isn't perfect, as some have fallbacks if their probing fails.
local -r sentinel_dir="$(mktemp -du nixpkgs.XXXX)/use/system/library"
# https://docs.rs/system-deps/8.0.0/system_deps/#internally-build-system-libraries
export SYSTEM_DEPS_BUILD_INTERNAL="never"
# https://github.com/aws/aws-lc-rs/blob/741dbf573a64b6a1e1e6b7c1131a0f8153a28441/aws-lc-sys/README.md#automatic-detection
export AWS_LC_SYS_USE_SYSTEM="1"
# https://github.com/rust-openssl/rust-openssl/blob/b46d5ec06144795e8f9e118c44bebd392956917a/openssl-sys/build/main.rs#L53
export OPENSSL_NO_VENDOR="1"
# 1 = Links statically to the vendored one
# 0 = Use pkg-config
# https://github.com/rust-lang/libz-sys/blob/2ce3271849d85329b668e0bac9f21427ecf8aef9/build.rs#L256
export LIBZ_SYS_STATIC="0"
# https://github.com/rusqlite/rusqlite/blob/db83b9b08d9cab73f912501eefb8df7b100acd7d/libsqlite3-sys/build.rs#L53
export LIBSQLITE3_SYS_USE_PKG_CONFIG="1"
# https://github.com/gyscos/zstd-rs/blob/ad18ca4e275aed9acc3087d7c1c65d03ab67ad6e/zstd-safe/zstd-sys/build.rs#L279
export ZSTD_SYS_USE_PKG_CONFIG="1"
# https://github.com/rust-lang/git2-rs/blob/a00922bcdf0f78419aa5dd0d3643e73ce01672a8/libgit2-sys/build.rs#L95
export LIBGIT2_NO_VENDOR="1"
# https://github.com/sodiumoxide/sodiumoxide/blob/3057acb1a030ad86ed8892a223d64036ab5e8523/libsodium-sys/build.rs#L34
export SODIUM_USE_PKG_CONFIG="1"
# https://github.com/rust-onig/rust-onig/blob/73e63eb3eea6d93d24a4aadf7fea580287750c7d/onig_sys/build.rs#L250
export RUSTONIG_SYSTEM_LIBONIG="1"
# https://github.com/rust-lang/ssh2-rs/blob/0a11bdd4eecf4525e540c30f14b15ab1c07194b7/libssh2-sys/build.rs#L23
export LIBSSH2_SYS_USE_PKG_CONFIG="1"
# We can only supply the src dir.
# https://github.com/nginx/ngx-rust/tree/main/nginx-sys#input-variables
# Since we don't want to pull it in for every build, we set it to a dummy value
# in all builds, but lets the user set it via `env.NGINX_SOURCE_DIR = nginx.src`
export NGINX_SOURCE_DIR="${NGINX_SOURCE_DIR:-"$sentinel_dir/nginx/src"}"
# We can only supply the lib and include dirs
# https://github.com/duckdb/duckdb-rs/blob/ea700a79534c8e8c22a9ac685135f15c31de91d3/crates/libduckdb-sys/build.rs#L203
# Set to sentinel by default again
# There is also a DUCKDB_LIB_DIR var, but I think only one needs to be set.
export DUCKDB_DOWNLOAD_LIB="0"
export DUCKDB_INCLUDE_DIR="${DUCKDB_INCLUDE_DIR:-"$sentinel_dir/duckdb/include"}"
# https://github.com/tikv/jemallocator/blob/a181911517adff5331e43dfd9804086f7c392a25/jemalloc-sys/build.rs#L132
export JEMALLOC_OVERRIDE="${JEMALLOC_OVERRIDE:-"$sentinel_dir/lib/libjemalloc"}"
}
# Cargo defaults to one job per host CPU. Limit builds that invoke Cargo
# directly (e.g. through Meson or Make) to NIX_BUILD_CORES, like cargoBuildHook.
# This runs in a phase because stdenv normalizes NIX_BUILD_CORES after
# sourcing setup hooks.
cargoSetupBuildJobs() {
export CARGO_BUILD_JOBS="${CARGO_BUILD_JOBS:-$NIX_BUILD_CORES}"
}
postUnpackHooks+=(cargoSetupBuildJobs)
if [[ -z "${dontCargoUseSystemLibs-}" ]]; then
preConfigureHooks+=(cargoUseSystemLibs)
fi
if [ -z "${dontCargoSetupPostUnpack-}" ]; then
postUnpackHooks+=(cargoSetupPostUnpackHook)
fi

View File

@@ -187,18 +187,13 @@ let
let
crateTarball = fetchCrate pkg registries.${registryIndexUrl};
in
runCommand "${pkg.name}-${pkg.version}"
{
strictDeps = true;
__structuredAttrs = true;
}
''
mkdir $out
tar xf "${crateTarball}" -C $out --strip-components=1
runCommand "${pkg.name}-${pkg.version}" { } ''
mkdir $out
tar xf "${crateTarball}" -C $out --strip-components=1
# Cargo is happy with largely empty metadata.
printf '{"files":{},"package":"${crateTarball.outputHash}"}' > "$out/.cargo-checksum.json"
''
# Cargo is happy with largely empty metadata.
printf '{"files":{},"package":"${crateTarball.outputHash}"}' > "$out/.cargo-checksum.json"
''
else if gitParts != null then
let
missingHash = throw ''
@@ -229,71 +224,66 @@ let
else
missingHash;
in
runCommand "${pkg.name}-${pkg.version}"
{
strictDeps = true;
__structuredAttrs = true;
}
''
tree=${tree}
runCommand "${pkg.name}-${pkg.version}" { } ''
tree=${tree}
# If the target package is in a workspace, or if it's the top-level
# crate, we should find the crate path using `cargo metadata`.
# Some packages do not have a Cargo.toml at the top-level,
# but only in nested directories.
# Only check the top-level Cargo.toml, if it actually exists
if [[ -f $tree/Cargo.toml ]]; then
crateCargoTOML=$(cd "$tree" && ${cargo}/bin/cargo metadata --format-version 1 --no-deps --manifest-path $tree/Cargo.toml | \
${jq}/bin/jq -r '.packages[] | select(.name == "${pkg.name}") | .manifest_path')
fi
# If the target package is in a workspace, or if it's the top-level
# crate, we should find the crate path using `cargo metadata`.
# Some packages do not have a Cargo.toml at the top-level,
# but only in nested directories.
# Only check the top-level Cargo.toml, if it actually exists
if [[ -f $tree/Cargo.toml ]]; then
crateCargoTOML=$(${cargo}/bin/cargo metadata --format-version 1 --no-deps --manifest-path $tree/Cargo.toml | \
${jq}/bin/jq -r '.packages[] | select(.name == "${pkg.name}") | .manifest_path')
fi
# If the repository is not a workspace the package might be in a subdirectory.
if [[ -z $crateCargoTOML ]]; then
for manifest in $(find $tree -name "Cargo.toml"); do
echo Looking at $manifest
crateCargoTOML=$(cd "$(dirname "$manifest")" && ${cargo}/bin/cargo metadata --format-version 1 --no-deps --manifest-path "$manifest" | ${jq}/bin/jq -r '.packages[] | select(.name == "${pkg.name}") | .manifest_path' || :)
if [[ ! -z $crateCargoTOML ]]; then
break
fi
done
if [[ -z $crateCargoTOML ]]; then
>&2 echo "Cannot find path for crate '${pkg.name}-${pkg.version}' in the tree in: $tree"
exit 1
# If the repository is not a workspace the package might be in a subdirectory.
if [[ -z $crateCargoTOML ]]; then
for manifest in $(find $tree -name "Cargo.toml"); do
echo Looking at $manifest
crateCargoTOML=$(${cargo}/bin/cargo metadata --format-version 1 --no-deps --manifest-path "$manifest" | ${jq}/bin/jq -r '.packages[] | select(.name == "${pkg.name}") | .manifest_path' || :)
if [[ ! -z $crateCargoTOML ]]; then
break
fi
done
if [[ -z $crateCargoTOML ]]; then
>&2 echo "Cannot find path for crate '${pkg.name}-${pkg.version}' in the tree in: $tree"
exit 1
fi
fi
echo Found crate ${pkg.name} at $crateCargoTOML
tree=$(dirname $crateCargoTOML)
echo Found crate ${pkg.name} at $crateCargoTOML
tree=$(dirname $crateCargoTOML)
cp -prvL "$tree" "$out" || echo "Warning: certain files couldn't be copied!" >&2
chmod u+w $out
cp -prvL "$tree" "$out" || echo "Warning: certain files couldn't be copied!" >&2
chmod u+w $out
if grep -q workspace "$out/Cargo.toml"; then
chmod u+w "$out/Cargo.toml"
${replaceWorkspaceValues} "$out/Cargo.toml" "$(cd "$tree" && ${cargo}/bin/cargo metadata --format-version 1 --no-deps --manifest-path $crateCargoTOML | ${jq}/bin/jq -r .workspace_root)/Cargo.toml"
fi
if grep -q workspace "$out/Cargo.toml"; then
chmod u+w "$out/Cargo.toml"
${replaceWorkspaceValues} "$out/Cargo.toml" "$(${cargo}/bin/cargo metadata --format-version 1 --no-deps --manifest-path $crateCargoTOML | ${jq}/bin/jq -r .workspace_root)/Cargo.toml"
fi
# Cargo is happy with empty metadata.
printf '{"files":{},"package":null}' > "$out/.cargo-checksum.json"
# Cargo is happy with empty metadata.
printf '{"files":{},"package":null}' > "$out/.cargo-checksum.json"
${optionalString (gitParts ? type) ''
gitPartsValue=${escapeShellArg gitParts.value}
# starting with lockfile version v4 the git source url contains encoded query parameters
# our regex parser does not know how to unescape them to get the actual value, so we do it here
${optionalString (lockFileVersion >= 4) ''
gitPartsValue=$(${getExe python3Packages.python} -c "import sys, urllib.parse; print(urllib.parse.unquote(sys.argv[1]))" "$gitPartsValue")
''}
${optionalString (gitParts ? type) ''
gitPartsValue=${escapeShellArg gitParts.value}
# starting with lockfile version v4 the git source url contains encoded query parameters
# our regex parser does not know how to unescape them to get the actual value, so we do it here
${optionalString (lockFileVersion >= 4) ''
gitPartsValue=$(${getExe python3Packages.python} -c "import sys, urllib.parse; print(urllib.parse.unquote(sys.argv[1]))" "$gitPartsValue")
''}
''}
# Set up configuration for the vendor directory.
cat > $out/.cargo-config <<EOF
[source."${pkg.source}"]
git = "${gitParts.url}"
${optionalString (gitParts ? type) "${gitParts.type} = \"$gitPartsValue\""}
replace-with = "vendored-sources"
EOF
''
# Set up configuration for the vendor directory.
cat > $out/.cargo-config <<EOF
[source."${pkg.source}"]
git = "${gitParts.url}"
${optionalString (gitParts ? type) "${gitParts.type} = \"$gitPartsValue\""}
replace-with = "vendored-sources"
EOF
''
else
throw "Cannot handle crate source: ${pkg.source}";
@@ -301,7 +291,6 @@ let
runCommand "cargo-vendor-dir"
(
{
strictDeps = true;
__structuredAttrs = true;
}
// (

View File

@@ -1,4 +0,0 @@
{ callPackage }:
{
gitDependencyCargoConfig = callPackage ./git-dependency-cargo-config { };
}

View File

@@ -1,6 +0,0 @@
{ rustPlatform }:
rustPlatform.fetchCargoVendor {
name = "git-dependency-cargo-config";
src = ../../import-cargo-lock/git-dependency-cargo-config;
hash = "sha256-rUQQ4Xrk+rW5Vgm7GK8xrK9zcwazsmBO6Q6qTCUniWc=";
}

View File

@@ -17,7 +17,6 @@
{ };
gitDependencyTag = callPackage ./git-dependency-tag { };
gitDependencyBranch = callPackage ./git-dependency-branch { };
gitDependencyCargoConfig = callPackage ./git-dependency-cargo-config { };
maturin = maturin.tests.pyo3;
v1 = callPackage ./v1 { };
gitDependencyWorkspaceInheritance = callPackage ./git-dependency-workspace-inheritance {

View File

@@ -1,13 +0,0 @@
version = 3
[[package]]
name = "fixture"
version = "0.1.0"
dependencies = [
"bootloader",
]
[[package]]
name = "bootloader"
version = "0.11.17"
source = "git+https://github.com/rust-osdev/bootloader.git?rev=3d7f72e36d4101ecf78b70cef2475d700bb01721#3d7f72e36d4101ecf78b70cef2475d700bb01721"

View File

@@ -1,8 +0,0 @@
{ rustPlatform }:
rustPlatform.importCargoLock {
lockFile = ./Cargo.lock;
outputHashes = {
# Bootloader's .cargo/config.toml enables bindeps, which are required to parse its manifest.
"bootloader-0.11.17" = "sha256-mLm5M1HLipN1EzS1zbDgMxMOqNySivGsK8+i0uOmoFM=";
};
}

View File

@@ -33,8 +33,6 @@ assertExecutable() {
# --prefix ENV SEP VAL : suffix/prefix ENV with VAL, separated by SEP
# --suffix
# --prefix-unchecked ENV SEP VAL : same as --prefix/--suffix, accepted for compatibility
# --suffix-unchecked with makeBinaryWrapper
# --prefix-each ENV SEP VALS : like --prefix, but VALS is a list
# --suffix-each ENV SEP VALS : like --suffix, but VALS is a list
# --prefix-contents ENV SEP FILES : like --suffix-each, but contents of FILES
@@ -147,7 +145,7 @@ makeShellWrapper() {
command="${params[$((n + 1))]}"
n=$((n + 1))
echo "$command" >> "$wrapper"
elif [[ ("$p" == "--suffix") || ("$p" == "--prefix") || ("$p" == "--suffix-unchecked") || ("$p" == "--prefix-unchecked") ]]; then
elif [[ ("$p" == "--suffix") || ("$p" == "--prefix") ]]; then
varName="${params[$((n + 1))]}"
separator="${params[$((n + 2))]}"
value="${params[$((n + 3))]}"

View File

@@ -150,67 +150,6 @@ expandResponseParams() {
done
}
# Resolve the path $1 of a library directory, which like the linker
# takes a relative path from the working directory, to the directory the
# linker searches, as far as needed to tell whether it is in the store,
# and where. Like the kernel, follow each symlink before going on to the
# next component, so that symlinks in ancestor directories count, and `..`
# applies to the target of a symlink rather than removing it. But in the
# store, keep symlinks that are not followed by `..` as they are, since
# resolving symlinks between store paths would refer to their targets
# instead (see issue #454199). The result is stored in resolvedPath.
# Fails if there are too many symlinks.
resolveLibDir() {
local rest="$1/" component link target links=0
# The common case: a path in the store with no `.`, `..` or empty
# components is already resolved, since it has no symlink to follow.
if [[ "$1" == "${NIX_STORE:-}"/* && "$1/" != */./* && "$1/" != */../* && "$1/" != *//* ]]; then
resolvedPath="$1"
return
fi
if [[ "$rest" != /* ]]; then
rest="$PWD/$rest"
fi
resolvedPath=
while [[ -n "$rest" ]]; do
component="${rest%%/*}"
rest="${rest#*/}"
case "$component" in
"" | .) continue ;;
..)
if [[ -L "$resolvedPath" ]]; then
# Follow it, then apply this `..` to its target.
link="$resolvedPath"
resolvedPath="${resolvedPath%/*}"
rest="../$rest"
else
resolvedPath="${resolvedPath%/*}"
continue
fi
;;
*)
link="$resolvedPath/$component"
# Keep a symlink in the store unless `..` follows it, and
# never resolve the store or its ancestors, which may be
# symlinks (NIX_IGNORE_SYMLINK_STORE).
if [[ "$link" == "${NIX_STORE:-}"/* || "${NIX_STORE:-}/" == "$link"/* || ! -L "$link" ]]; then
resolvedPath="$link"
continue
fi
;;
esac
(( ++links <= 40 )) || return 1
target=$(readlink "$link") || return 1
# A relative target is relative to the directory containing the
# link, which is now resolvedPath.
if [[ "$target" == /* ]]; then
resolvedPath=
fi
rest="$target/$rest"
done
resolvedPath="${resolvedPath:-/}"
}
checkLinkType() {
local arg
type="dynamic"

View File

@@ -66,7 +66,7 @@ gccStdenv.mkDerivation (finalAttrs: {
autoupdate
'';
hardeningDisable = lib.optionals stdenv.hostPlatform.isDarwin [
hardeningDisable = lib.optionals (stdenv.hostPlatform.isAarch64 && stdenv.hostPlatform.isDarwin) [
"stackprotector"
];

View File

@@ -92,6 +92,6 @@ stdenv.mkDerivation {
platforms = lib.platforms.unix;
# needs additional work to support aarch64-darwin
# due to usage of _DARWIN_NO_64_BIT_INODE
broken = stdenv.hostPlatform.isDarwin;
broken = stdenv.hostPlatform.isAarch64 && stdenv.hostPlatform.isDarwin;
};
}

View File

@@ -3,7 +3,6 @@
stdenv,
fetchFromGitHub,
cmake,
fixDarwinDylibNames,
gtest,
static ? stdenv.hostPlatform.isStatic,
cxxStandard ? null,
@@ -23,8 +22,6 @@ stdenv.mkDerivation (finalAttrs: {
outputs = [
"out"
"dev"
# Test helper libraries linking against GoogleTest
"testing"
];
cmakeFlags = [
@@ -38,22 +35,10 @@ stdenv.mkDerivation (finalAttrs: {
strictDeps = true;
nativeBuildInputs = [ cmake ] ++ lib.optionals stdenv.hostPlatform.isDarwin [ fixDarwinDylibNames ];
nativeBuildInputs = [ cmake ];
buildInputs = [ gtest ];
postInstall = ''
for lib in scoped_mock_log status_matchers; do
moveToOutput "lib/libabsl_$lib.*" "$testing"
substituteInPlace $out/lib/cmake/absl/abslTargets-*.cmake \
--replace-fail "$out/lib/libabsl_$lib." "$testing/lib/libabsl_$lib."
substituteInPlace "$out/lib/pkgconfig/absl_$lib.pc" \
--replace-fail "libdir=$out/lib" "libdir=$testing/lib"
done
'';
outputChecks.out.disallowedRequisites = [ gtest ];
__structuredAttrs = true;
meta = {

View File

@@ -17,6 +17,8 @@ python3Packages.buildPythonApplication {
hash = "sha256-s9kegTZOZEgGx0Yj8jOfzAyjyy1EuabOybMDBoodRvo=";
};
__structuredAttrs = true;
build-system = with python3Packages; [
setuptools
];

View File

@@ -45,7 +45,9 @@ stdenv.mkDerivation (finalAttrs: {
# ACPICA emits packed structs that produce unaligned pointers. Apple's
# arm64 linker rejects these under chained fixups; opt back into the
# legacy fixup format so the link succeeds.
NIX_LDFLAGS = lib.optionalString stdenv.hostPlatform.isDarwin "-no_fixup_chains";
NIX_LDFLAGS = lib.optionalString (
stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isAarch64
) "-no_fixup_chains";
# i686 builds fail with hardening enabled (due to -Wformat-overflow). Disable
# -Werror altogether to make this derivation less fragile to toolchain

View File

@@ -2,8 +2,6 @@
lib,
rustPlatform,
fetchFromGitHub,
pkg-config,
aws-lc,
}:
rustPlatform.buildRustPackage (finalAttrs: {
@@ -20,14 +18,6 @@ rustPlatform.buildRustPackage (finalAttrs: {
cargoHash = "sha256-uch2JKnskO5W8EPK877qL0aQQ+iInHJoCrrhZbmoVRs=";
nativeBuildInputs = [
pkg-config
];
buildInputs = [
aws-lc
];
meta = {
description = "Terminal-based, real-time traffic monitoring and statistics for your AdGuard Home instance";
mainProgram = "adguardian";

View File

@@ -10,6 +10,8 @@ python3Packages.buildPythonApplication (finalAttrs: {
version = "1.2.0";
pyproject = true;
__structuredAttrs = true;
src = fetchFromGitHub {
owner = "NetSPI";
repo = "AD-PathFinder";

View File

@@ -10,6 +10,8 @@ python3Packages.buildPythonApplication (finalAttrs: {
version = "13.2.0";
pyproject = true;
__structuredAttrs = true;
src = fetchFromGitHub {
owner = "ADScanPro";
repo = "adscan";

View File

@@ -16,9 +16,9 @@ let
case "$1 $2" in
"config var")
case "$3" in
man) echo "''${man:-$out}/share/man";;
man) echo "$out/share/man";;
etc) echo "$out/etc";;
doc) echo "''${doc:-$out}/share/doc";;
doc) echo "$out/share/doc";;
share) echo "$out/share";;
prefix) echo "$out";;
*) echo "fake-opam does not understand arguments: $@" ; exit 1 ;;
@@ -46,7 +46,7 @@ ocamlPackages.buildDunePackage rec {
postPatch = ''
substituteInPlace ./Makefile \
--replace "\$(DUNE) install \$(DUNEROOT) --display=short" \
"\$(DUNE) install \$(DUNEROOT) --prefix $out --docdir ''${!outputDoc}/share/doc --mandir ''${!outputMan}/share/man"
"\$(DUNE) install \$(DUNEROOT) --prefix $out --docdir $out/share/doc --mandir $out/share/man"
substituteInPlace ./src/discover.sh \
--replace 'gs_path=$(which gs)' 'gs_path=${ghostscriptX}/bin/gs'
'';

View File

@@ -9,11 +9,11 @@
stdenvNoCC.mkDerivation (finalAttrs: {
pname = "adwaita-fonts";
version = "51.0";
version = "50.0";
src = fetchurl {
url = "mirror://gnome/sources/adwaita-fonts/${lib.versions.major finalAttrs.version}/adwaita-fonts-${finalAttrs.version}.tar.xz";
hash = "sha256-+hBK4sG5ZYDTIvVj/+iy38pSlrDspJce/S2AEUBRI9I=";
hash = "sha256-TJJ/v+7BxQOAG6UQwslOAFTILFIs97oNO+XU1B/PXIY=";
};
nativeBuildInputs = [

View File

@@ -14,11 +14,11 @@
stdenv.mkDerivation (finalAttrs: {
pname = "adwaita-icon-theme";
version = "51.0";
version = "50.0";
src = fetchurl {
url = "mirror://gnome/sources/adwaita-icon-theme/${lib.versions.major finalAttrs.version}/adwaita-icon-theme-${finalAttrs.version}.tar.xz";
hash = "sha256-ulYc88ljBaRxefpWBYVq1pXJI46gf3CTrr2bqAxOMjs=";
hash = "sha256-+sbgQB/KcUeAVhoIG49+J8O8HbNOvaTaF1CB8msk1GA=";
};
nativeBuildInputs = [

View File

@@ -25,6 +25,7 @@ python3Packages.buildPythonApplication (finalAttrs: {
python3Packages.sphinxHook
];
sphinxRoot = "docs";
sphinxBuilders = [
"html"
"man"
@@ -58,6 +59,12 @@ python3Packages.buildPythonApplication (finalAttrs: {
"man"
];
# Workaround for upstream packaging paths, can be removed once #573479 is resolved
postInstall = ''
sphinx-build -b man docs docs/build/man
install -Dm644 docs/build/man/*.1 -t $man/share/man/man1/
'';
meta = {
homepage = "https://github.com/afewmail/afew";
description = "Initial tagging script for notmuch mail";

View File

@@ -11,6 +11,8 @@ python3Packages.buildPythonApplication (finalAttrs: {
version = "1.7.0";
pyproject = true;
__structuredAttrs = true;
src = fetchFromGitHub {
owner = "agentsploit";
repo = "agentsploit";
@@ -50,7 +52,6 @@ python3Packages.buildPythonApplication (finalAttrs: {
disabledTestPaths = [
# Tests need network access
"tests/unit/test_openai_adapter.py"
"tests/integration/"
];

View File

@@ -4,7 +4,6 @@
fetchFromGitHub,
cmake,
llvmPackages,
sqlite,
}:
rustPlatform.buildRustPackage (finalAttrs: {
@@ -31,8 +30,6 @@ rustPlatform.buildRustPackage (finalAttrs: {
rustPlatform.bindgenHook
];
buildInputs = [ sqlite ];
# Add CFLAGS to suppress the stringop-overflow error during aws-lc-sys compilation.
NIX_CFLAGS_COMPILE = "-Wno-error=stringop-overflow";

View File

@@ -397,6 +397,8 @@ buildPythonPackage (
pname = "apache-airflow";
version = "3.3.2";
__structuredAttrs = true;
src = fetchFromGitHub {
owner = "apache";
repo = "airflow";

View File

@@ -10,6 +10,8 @@ python3Packages.buildPythonApplication (finalAttrs: {
version = "0.35.0";
pyproject = true;
__structuredAttrs = true;
src = fetchFromGitHub {
owner = "microsoft";
repo = "apm";

View File

@@ -2,16 +2,12 @@
lib,
fetchFromGitHub,
rustPlatform,
pkg-config,
aws-lc,
}:
rustPlatform.buildRustPackage (finalAttrs: {
pname = "apt-swarm";
version = "0.6.1";
__structuredAttrs = true;
src = fetchFromGitHub {
owner = "kpcyrd";
repo = "apt-swarm";
@@ -21,10 +17,6 @@ rustPlatform.buildRustPackage (finalAttrs: {
cargoHash = "sha256-Fo/+UbdfDhbAsoWjoko4tAmyDZK6tPn/0d2CjPKyaaQ=";
nativeBuildInputs = [ pkg-config ];
buildInputs = [ aws-lc ];
meta = {
description = "Experimental p2p gossip network for OpenPGP signature transparency";
homepage = "https://github.com/kpcyrd/apt-swarm";

View File

@@ -9,6 +9,7 @@ python3Packages.buildPythonApplication (finalAttrs: {
pname = "aqtinstall";
version = "3.3.0";
pyproject = true;
__structuredAttrs = true;
src = fetchFromGitHub {
owner = "miurahr";

View File

@@ -172,6 +172,10 @@ stdenv.mkDerivation (finalAttrs: {
"TestS3FS.*"
"TestS3FSGeneric.*"
"TestS3FSHTTPS.*" # Needs Minio
]
++ lib.optionals (stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isx86_64) [
# https://github.com/apache/arrow/issues/41505
"TestAzuriteGeneric.Empty"
];
in
"-${lib.concatStringsSep ":" filteredTests}";
@@ -348,6 +352,8 @@ stdenv.mkDerivation (finalAttrs: {
__structuredAttrs = true;
meta = {
# https://hydra.nixos.org/job/nixpkgs/unstable/arrow-cpp.x86_64-darwin/all
broken = stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isx86_64;
description = "Cross-language development platform for in-memory data";
homepage = "https://arrow.apache.org/docs/cpp/";
changelog = "https://arrow.apache.org/release/${finalAttrs.version}.html";

View File

@@ -6,7 +6,6 @@
pkg-config,
sqlite,
openssl,
zstd,
versionCheckHook,
nix-update-script,
nixosTests,
@@ -37,13 +36,9 @@ rustPlatform.buildRustPackage (finalAttrs: {
buildAndTestSubdir = "crates/arti";
cargoHash = "sha256-g+t5X1t0koUzqoHpY8+lncqRobdDuZggXtD3HRk9ryE=";
nativeBuildInputs = [ pkg-config ];
nativeBuildInputs = lib.optionals stdenv.hostPlatform.isLinux [ pkg-config ];
buildInputs = [
sqlite
zstd
]
++ lib.optionals stdenv.hostPlatform.isLinux [ openssl ];
buildInputs = [ sqlite ] ++ lib.optionals stdenv.hostPlatform.isLinux [ openssl ];
# `full` includes all stable and non-conflicting feature flags. the primary
# downsides are increased binary size and memory usage for building, but

View File

@@ -7,7 +7,7 @@
autoreconfHook,
installShellFiles,
enableStandardFeatures ? false,
source-highlight,
sourceHighlight,
highlight,
graphviz,
texliveMinimal,
@@ -246,7 +246,7 @@ python3.pkgs.buildPythonApplication (finalAttrs: {
-e "s|run('convert|run('${lib.getExe' imagemagick "convert"}|g" \
-i "asciidoc/resources/filters/music/music2png.py"
sed -e 's|filter="source-highlight|filter="${source-highlight}/bin/source-highlight|' \
sed -e 's|filter="source-highlight|filter="${sourceHighlight}/bin/source-highlight|' \
-e 's|filter="highlight|filter="${highlight}/bin/highlight|' \
-e 's|filter="pygmentize|filter="${pygments}/bin/pygmentize|' \
-i "asciidoc/resources/filters/source/source-highlight-filter.conf"
@@ -283,10 +283,10 @@ python3.pkgs.buildPythonApplication (finalAttrs: {
)
+ ''
# Fix tests
substituteInPlace $(grep -R --files-with-matches "2002-11-25" tests/data) \
--replace-fail "2002-11-25" "1980-01-02"
substituteInPlace $(grep -R --files-with-matches "00:37:42" tests/data) \
--replace-fail "00:37:42" "00:00:00"
for f in $(grep -R --files-with-matches "2002-11-25") ; do
substituteInPlace $f --replace "2002-11-25" "1980-01-02"
substituteInPlace $f --replace "00:37:42" "00:00:00"
done
''
+ lib.optionalString (stdenv.buildPlatform != stdenv.hostPlatform) ''
# We want to use asciidoc from the build platform to build the documentation.
@@ -317,6 +317,8 @@ python3.pkgs.buildPythonApplication (finalAttrs: {
runHook postCheck
'';
__structuredAttrs = true;
meta = {
description = "Text-based document generation system";
longDescription = ''

View File

@@ -10,6 +10,8 @@ python3Packages.buildPythonApplication (finalAttrs: {
version = "1.2.7";
pyproject = true;
__structuredAttrs = true;
src = fetchPypi {
inherit (finalAttrs) pname version;
hash = "sha256-SqwViOnVx1TcpY8Kd5VQCg1A8KQnBhL8aq9Gsrwer3k=";

View File

@@ -32,7 +32,7 @@ stdenv.mkDerivation (finalAttrs: {
lib.optionalString (!buildDocs) ''
substituteInPlace Makefile --replace "all: binaries docs" "all: binaries"
''
+ lib.optionalString stdenv.hostPlatform.isDarwin ''
+ lib.optionalString (stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isAarch64) ''
substituteInPlace sysdefs.h --replace "x86_64" "aarch64"
'';

View File

@@ -29,7 +29,7 @@
stdenv.mkDerivation (finalAttrs: {
pname = "at-spi2-core";
version = "2.62.0";
version = "2.60.6";
outputs = [
"out"
@@ -39,7 +39,7 @@ stdenv.mkDerivation (finalAttrs: {
src = fetchurl {
url = "mirror://gnome/sources/at-spi2-core/${lib.versions.majorMinor finalAttrs.version}/at-spi2-core-${finalAttrs.version}.tar.xz";
hash = "sha256-A6lPe/NfMA2vKEOjfN82R5qRvFP1mo6kN8eeJdldHeM=";
hash = "sha256-qJtkqLIXqAQr3w41y/q2Kc7uNWQNunXfV4r96ap4nVc=";
};
nativeBuildInputs = [

View File

@@ -5,8 +5,6 @@
nixVersions,
nixosTests,
boost,
sqlite,
zstd,
pkg-config,
stdenv,
installShellFiles,
@@ -39,14 +37,7 @@ rustPlatform.buildRustPackage {
installShellFiles
];
buildInputs = [
boost
]
++ lib.optionals needNixInclude [ nix ]
++ lib.optionals (lib.elem "attic-server" crates) [
sqlite
zstd
];
buildInputs = lib.optional needNixInclude nix ++ [ boost ];
cargoBuildFlags = map (c: "--package=${c}") crates;
cargoHash = "sha256-UGgM78QEWJ2QgbQhxEI+yLYXH6T4ey+1oenPTMlJ3GU=";

View File

@@ -8,7 +8,7 @@
which,
pkg-config,
perl,
guile,
guile_2_2,
libxml2,
}:
@@ -101,7 +101,7 @@ stdenv.mkDerivation (finalAttrs: {
buildPackages.texinfo
];
buildInputs = [
guile
guile_2_2
libxml2
];

View File

@@ -24,6 +24,8 @@ let
pname = "fernet_key";
inherit version src;
__structuredAttrs = true;
format = "other";
# this would run the upstream docker makefile

View File

@@ -51,7 +51,7 @@ buildDotnetModule rec {
bintools
fixDarwinDylibNames
]
++ lib.optionals stdenv.hostPlatform.isDarwin [
++ lib.optionals (stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isAarch64) [
autoSignDarwinBinariesHook
];

View File

@@ -9,6 +9,7 @@ python3Packages.buildPythonApplication (finalAttrs: {
pname = "aw-watcher-steam";
version = "0-unstable-2025-06-16";
pyproject = true;
__structuredAttrs = true;
src = fetchFromGitHub {
owner = "Edwardsoen";

View File

@@ -1,94 +0,0 @@
diff --git i/crypto/CMakeLists.txt w/crypto/CMakeLists.txt
index 7bac21b..da56759 100644
--- i/crypto/CMakeLists.txt
+++ w/crypto/CMakeLists.txt
@@ -895,20 +895,23 @@ if(BUILD_TESTING)
add_dependencies(${DYNAMIC_LOADING_TEST_EXEC} crypto)
set_test_location(${DYNAMIC_LOADING_TEST_EXEC})
set(DYNAMIC_LINKER_LIB "")
if(CMAKE_SYSTEM_NAME STREQUAL "Linux" OR APPLE OR ANDROID)
set(DYNAMIC_LINKER_LIB "dl")
endif()
if (BUILD_SHARED_LIBS AND NOT WIN32)
target_compile_options(${DYNAMIC_LOADING_TEST_EXEC} PUBLIC "-DLIBCRYPTO_PATH=\"$<TARGET_FILE:crypto>\"")
+ if(BORINGSSL_PREFIX)
+ target_compile_options(${DYNAMIC_LOADING_TEST_EXEC} PUBLIC "-DSYMBOL_PREFIX=\"${BORINGSSL_PREFIX}_\"")
+ endif()
# Do not link to boringssl_gtest_main or any library that might be linked to libcrypto.so.
if(ANDROID)
target_link_libraries(${DYNAMIC_LOADING_TEST_EXEC} PUBLIC boringssl_gtest ${DYNAMIC_LINKER_LIB})
else()
target_link_libraries(${DYNAMIC_LOADING_TEST_EXEC} PUBLIC boringssl_gtest pthread ${DYNAMIC_LINKER_LIB})
endif()
endif()
add_dependencies(all_tests ${DYNAMIC_LOADING_TEST_EXEC})
diff --git i/crypto/dynamic_loading_test.c w/crypto/dynamic_loading_test.c
index 4c37c28..88002dc 100644
--- i/crypto/dynamic_loading_test.c
+++ w/crypto/dynamic_loading_test.c
@@ -20,53 +20,57 @@
#include <stdio.h>
#ifdef LIBCRYPTO_PATH
#include <stdint.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <pthread.h>
+#ifndef SYMBOL_PREFIX
+#define SYMBOL_PREFIX ""
+#endif
+
typedef void (*fp_lc_clear_error_t)(void);
typedef int (*fp_lc_tl_func_t)(void);
typedef int (*fp_rand_bytes_t)(uint8_t *buf, size_t len);
#define BUFFER_SIZE 16
#define TEST_ITERS 10
#define THREAD_COUNT 10
static void *cycle_thread_local_setup(void *lc_so) {
uint8_t buffer[BUFFER_SIZE];
- fp_lc_clear_error_t lc_clear_error = dlsym(lc_so, "ERR_clear_error");
- fp_rand_bytes_t lc_rand_bytes = dlsym(lc_so, "RAND_bytes");
- fp_lc_tl_func_t lc_tl_clear = dlsym(lc_so, "AWSLC_thread_local_clear");
+ fp_lc_clear_error_t lc_clear_error = dlsym(lc_so, SYMBOL_PREFIX "ERR_clear_error");
+ fp_rand_bytes_t lc_rand_bytes = dlsym(lc_so, SYMBOL_PREFIX "RAND_bytes");
+ fp_lc_tl_func_t lc_tl_clear = dlsym(lc_so, SYMBOL_PREFIX "AWSLC_thread_local_clear");
for (int i = 0; i < TEST_ITERS; i++) {
(*lc_clear_error)();
if (1 != (*lc_rand_bytes)(buffer, BUFFER_SIZE)) {
fprintf(stderr, "Call to RAND_bytes failed.");
exit(1);
}
if (1 != (*lc_tl_clear)()) {
fprintf(stderr, "Call to AWSLC_thread_local_clear failed.");
exit(1);
}
}
return NULL;
}
static void *load_unload(void *ctx) {
const char* path = ctx;
void *lc_so = dlopen(path, RTLD_NOW);
- fp_lc_tl_func_t lc_tl_shutdown = dlsym(lc_so, "AWSLC_thread_local_shutdown");
+ fp_lc_tl_func_t lc_tl_shutdown = dlsym(lc_so, SYMBOL_PREFIX "AWSLC_thread_local_shutdown");
pthread_t thread_id[THREAD_COUNT];
for (int i = 0; i < THREAD_COUNT; i++) {
if (pthread_create(&thread_id[i], NULL, cycle_thread_local_setup, lc_so)) {
fprintf(stderr, "Call to pthread_create in load_unload failed.");
exit(1);
}
}
// Also cycle on the current thread

View File

@@ -1,50 +0,0 @@
Commit ID: eaef466931b704cbded48be8c51f7a8fa75ca6e0
Change ID: yxsyyzwrzkrtqvksxqsurozmktvqsssw
Author : Marie Ramlow <marie@marie.cologne> (2026-11-01 13:28:50)
Committer: Marie Ramlow <marie@marie.cologne> (2026-11-01 13:29:10)
Fix OpenSSL-compat shim symlinks
diff --git a/CMakeLists.txt b/CMakeLists.txt
index aa64e1aa22..005dc11c58 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1844,12 +1844,12 @@
endif()
install(CODE "
execute_process(COMMAND \${CMAKE_COMMAND} -E create_symlink
- lib${CRYPTO_LIB_NAME}.${SHIM_LIB_EXT} \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/libcrypto.${SHIM_LIB_EXT}\")
+ lib${CRYPTO_LIB_NAME}.${SHIM_LIB_EXT} \"\$ENV{DESTDIR}${CMAKE_INSTALL_FULL_LIBDIR}/libcrypto.${SHIM_LIB_EXT}\")
" ${SHIM_LINK_COMPONENT})
if(BUILD_LIBSSL)
install(CODE "
execute_process(COMMAND \${CMAKE_COMMAND} -E create_symlink
- lib${SSL_LIB_NAME}.${SHIM_LIB_EXT} \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/libssl.${SHIM_LIB_EXT}\")
+ lib${SSL_LIB_NAME}.${SHIM_LIB_EXT} \"\$ENV{DESTDIR}/${CMAKE_INSTALL_FULL_LIBDIR}/libssl.${SHIM_LIB_EXT}\")
" ${SHIM_LINK_COMPONENT})
endif()
endif()
@@ -1858,7 +1858,7 @@
# Always create the include directory symlink for OpenSSL compatibility
install(CODE "
execute_process(COMMAND \${CMAKE_COMMAND} -E create_symlink
- aws-lc/openssl \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}/openssl\")
+ aws-lc/openssl \"\$ENV{DESTDIR}/${CMAKE_INSTALL_FULL_INCLUDEDIR}/openssl\")
" COMPONENT Development)
endif()
endif()
diff --git a/tool-openssl/CMakeLists.txt b/tool-openssl/CMakeLists.txt
index 262b42aa00..6f16cfa198 100644
--- a/tool-openssl/CMakeLists.txt
+++ b/tool-openssl/CMakeLists.txt
@@ -191,8 +191,8 @@
if(INSTALL_OPENSSL_SHIM AND COHABITANT_BINARIES)
install(CODE "
execute_process(COMMAND \${CMAKE_COMMAND} -E create_symlink
- \"${AWSLC_BIN_PREFIX}openssl\" \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}/openssl\")
+ \"${AWSLC_BIN_PREFIX}openssl\" \"\$ENV{DESTDIR}/${CMAKE_INSTALL_FULL_BINDIR}/openssl\")
execute_process(COMMAND \${CMAKE_COMMAND} -E create_symlink
- \"${AWSLC_BIN_PREFIX}c_rehash\" \"\$ENV{DESTDIR}\${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}/c_rehash\")
+ \"${AWSLC_BIN_PREFIX}c_rehash\" \"\$ENV{DESTDIR}/${CMAKE_INSTALL_FULL_BINDIR}/c_rehash\")
")
endif()

View File

@@ -2,58 +2,18 @@
lib,
stdenv,
fetchFromGitHub,
buildGoModule,
cmake,
ninja,
go,
perl,
rust-bindgen,
testers,
nix-update-script,
aws-lc,
writableTmpDirAsHomeHook,
runCommand,
useSharedLibraries ? !stdenv.hostPlatform.isStatic,
withRustBindings ? true,
symbolPrefix ? "AWS_LC",
# This option might lead to OpenSSL being silently swapped to AWS-LC. Only use it if you know what you are doing.
withOpenSSLShim ? false,
}:
let
aws-lc' = aws-lc.override {
useSharedLibraries = false;
symbolPrefix = null;
};
symbols =
runCommand "aws-lc-symbols"
{
inherit (aws-lc) src;
nativeBuildInputs = [
writableTmpDirAsHomeHook
go
];
}
''
cd "$src"
go run ./util/read_symbols.go -out "$TMPDIR/symbols_crypto.txt" ${aws-lc'}/lib/libcrypto-awslc.a
go run ./util/read_symbols.go -out "$TMPDIR/symbols_ssl.txt" ${aws-lc'}/lib/libssl-awslc.a
cat "$TMPDIR"/symbols_{crypto,ssl}.txt > $out
'';
in
stdenv.mkDerivation (finalAttrs: {
pname = "aws-lc";
version = "5.12.0";
patches = [
./fix-dynamic-loading-test.patch
./fix-openssl-shim-symlinks.patch
];
__structuredAttrs = true;
strictDeps = true;
src = fetchFromGitHub {
owner = "aws";
repo = "aws-lc";
@@ -68,51 +28,26 @@ stdenv.mkDerivation (finalAttrs: {
];
nativeBuildInputs = [
writableTmpDirAsHomeHook
cmake
ninja
go
perl
]
++ lib.optionals withRustBindings [
rust-bindgen
];
goDeps =
(buildGoModule {
inherit (finalAttrs) pname version src;
vendorHash = "sha256-495bUr3Cuo7kuhuNLMVhrVg9NXTAXyFmnXRmBrCHovA=";
}).goModules;
# it seems that ENABLE_DIST_PKG rejects apple because of symbol versioning,
# but we disable symbol versioning ourselves.
postPatch = ''
substituteInPlace CMakeLists.txt \
--replace-fail "if(NOT UNIX OR APPLE)" "if(NOT UNIX)"
'';
preConfigure = ''
ln -s ${finalAttrs.goDeps} vendor
'';
cmakeFlags = [
(lib.cmakeBool "BUILD_SHARED_LIBS" useSharedLibraries)
(lib.cmakeBool "DISABLE_GO" true)
(lib.cmakeBool "DISABLE_PERL" true)
(lib.cmakeBool "GENERATE_RUST_BINDINGS" withRustBindings)
(lib.cmakeBool "ENABLE_DIST_PKG" true)
(lib.cmakeBool "ENABLE_DIST_PKG_OPENSSL_SHIM" withOpenSSLShim)
(lib.cmakeBool "ENABLE_SYMBOL_VERSIONING" false)
]
++ lib.optionals stdenv.cc.isGNU [
# Needed with gcc but breaks with clang
(lib.cmakeFeature "CMAKE_C_FLAGS" "-Wno-error=stringop-overflow")
]
++ lib.optionals (symbolPrefix != null) [
(lib.cmakeFeature "BORINGSSL_PREFIX" symbolPrefix)
(lib.cmakeFeature "BORINGSSL_PREFIX_SYMBOLS" (toString symbols))
];
doCheck = true;
checkTarget = "run_tests";
checkTarget = "run_minimal_tests";
postInstall = ''
moveToOutput lib/crypto/cmake "$dev"
@@ -142,7 +77,7 @@ stdenv.mkDerivation (finalAttrs: {
tests = {
version = testers.testVersion {
package = finalAttrs.finalPackage;
command = "aws-lc-bssl version";
command = "bssl version";
};
pkg-config = testers.testMetaPkgConfig finalAttrs.finalPackage;
};
@@ -162,14 +97,15 @@ stdenv.mkDerivation (finalAttrs: {
asl20
isc
];
mainProgram = "aws-lc-bssl";
mainProgram = "bssl";
maintainers = with lib.maintainers; [
whispersofthedawn
];
pkgConfigModules = [
"aws-lc"
"libcrypto-awslc"
"libssl-awslc"
"libcrypto"
"libssl"
"openssl"
];
platforms = lib.platforms.unix;
};

View File

@@ -8,6 +8,7 @@ python3Packages.buildPythonApplication (finalAttrs: {
pname = "awscurl";
version = "0.44";
pyproject = true;
__structuredAttrs = true;
src = fetchFromGitHub {
owner = "okigan";

View File

@@ -10,6 +10,8 @@ python3Packages.buildPythonApplication (finalAttrs: {
version = "1.5.0";
pyproject = true;
__structuredAttrs = true;
src = fetchFromGitHub {
owner = "TacoRocket";
repo = "AzureFox";

View File

@@ -32,10 +32,6 @@ buildNpmPackage (finalAttrs: {
libsecret
];
# @vscode/vsce-sign's postinstall script fails on exotic architectures.
# We ignore the scripts, and this does not change the output.
npmFlags = [ "--ignore-scripts" ];
meta = {
description = "Lightweight server clone of Azure Storage that simulates most of the commands supported by it with minimal dependencies";
homepage = "https://github.com/Azure/Azurite";

View File

@@ -12,6 +12,7 @@ python3Packages.buildPythonApplication (finalAttrs: {
pname = "babeldoc";
version = "0.6.4";
pyproject = true;
__structuredAttrs = true;
src = fetchFromGitHub {
owner = "funstory-ai";

View File

@@ -9,6 +9,8 @@ python3.pkgs.buildPythonApplication (finalAttrs: {
version = "0.8.0";
pyproject = true;
__structuredAttrs = true;
src = fetchFromGitHub {
owner = "meeb";
repo = "bandcampsync";

View File

@@ -6,7 +6,6 @@
less,
installShellFiles,
makeWrapper,
oniguruma,
libgit2,
zlib,
versionCheckHook,
@@ -36,7 +35,6 @@ rustPlatform.buildRustPackage (finalAttrs: {
];
buildInputs = [
oniguruma
libgit2
zlib
];

View File

@@ -28,7 +28,7 @@ rustPlatform.buildRustPackage (finalAttrs: {
license = lib.licenses.asl20;
mainProgram = "batmon";
platforms = with lib.platforms; unix ++ windows;
broken = stdenv.hostPlatform.isDarwin;
broken = stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isAarch64;
maintainers = with lib.maintainers; [ _6543 ];
};
})

View File

@@ -1,15 +1,13 @@
{
lib,
stdenv,
fetchFromGitLab,
fetchFromGitHub,
blueprint-compiler,
desktop-file-utils,
dbus,
meson,
python3,
ninja,
pkg-config,
vala,
wrapGAppsHook4,
appstream,
flatpak,
@@ -31,13 +29,12 @@
md4c,
webkitgtk_6_0,
libsecret,
systemdLibs,
nix-update-script,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "bazaar";
version = "0.9.9";
version = "0.9.1";
__structuredAttrs = true;
strictDeps = true;
@@ -49,12 +46,11 @@ stdenv.mkDerivation (finalAttrs: {
"dev"
];
src = fetchFromGitLab {
domain = "gitlab.gnome.org";
owner = "World";
src = fetchFromGitHub {
owner = "bazaar-org";
repo = "bazaar";
tag = "v${finalAttrs.version}";
hash = "sha256-qmMwlvB8DXNP0SHip1mQoktYFeH/DwfvVtVIny16Ryo=";
hash = "sha256-9J+XI5JnV8Yfk3xRI/VM5RSG4eMafbw2rBRpPMIu5yA=";
};
nativeBuildInputs = [
@@ -64,7 +60,6 @@ stdenv.mkDerivation (finalAttrs: {
meson
ninja
pkg-config
vala
wrapGAppsHook4
(python3.withPackages (p: [
p.babel
@@ -74,7 +69,6 @@ stdenv.mkDerivation (finalAttrs: {
buildInputs = [
appstream
dbus
flatpak
glib-networking
gtk4
@@ -93,7 +87,6 @@ stdenv.mkDerivation (finalAttrs: {
md4c
webkitgtk_6_0
libsecret
systemdLibs
];
postInstall = ''
@@ -119,7 +112,7 @@ stdenv.mkDerivation (finalAttrs: {
meta = {
description = "FlatHub-first app store for GNOME";
homepage = "https://gitlab.gnome.org/World/bazaar";
homepage = "https://github.com/kolunmi/bazaar";
license = lib.licenses.gpl3Plus;
maintainers = with lib.maintainers; [
dtomvan

View File

@@ -31,6 +31,7 @@ python3Packages.buildPythonApplication (finalAttrs: {
webrtcvad
];
__structuredAttrs = true;
dontBuild = true;
dontWrapPythonPrograms = true;
pyproject = false;

View File

@@ -118,6 +118,11 @@ let
url = "https://github.com/bazelbuild/bazel/releases/download/${version}/bazel_nojdk-${version}-linux-arm64";
hash = "sha256-wfuZLSHa77wr0A4ZLF5DqH7qyOljYNXM2a5imoS+nGQ";
}
else if stdenv.hostPlatform.system == "x86_64-darwin" then
fetchurl {
url = "https://github.com/bazelbuild/bazel/releases/download/${version}/bazel-${version}-darwin-x86_64";
hash = "sha256-qAb9s6R5+EbqVfWHUT7sk1sOrbDEPv4EhgXH7nC46Zw=";
}
else
fetchurl {
# stdenv.hostPlatform.system == "aarch64-darwin"
@@ -279,12 +284,12 @@ let
platforms = lib.platforms.linux ++ lib.platforms.darwin;
inherit (stdenv.hostPlatform) isDarwin;
inherit (stdenv.hostPlatform) isDarwin isAarch64;
system = if isDarwin then "darwin" else "linux";
# on aarch64 Darwin, `uname -m` returns "arm64"
arch = if isDarwin then stdenv.hostPlatform.darwinArch else stdenv.hostPlatform.parsed.cpu.name;
arch = with stdenv.hostPlatform; if isDarwin && isAarch64 then "arm64" else parsed.cpu.name;
bazelRC = writeTextFile {
name = "bazel-rc";

View File

@@ -36,13 +36,12 @@
let
inherit (callPackage ./build-support/patching.nix { }) addFilePatch;
inherit (stdenv.hostPlatform) isDarwin;
inherit (stdenv.hostPlatform) isDarwin isAarch64;
bazelSystem = if isDarwin then "darwin" else "linux";
# on aarch64 Darwin, `uname -m` returns "arm64"
bazelArch =
if isDarwin then stdenv.hostPlatform.darwinArch else stdenv.hostPlatform.parsed.cpu.name;
bazelArch = if isDarwin && isAarch64 then "arm64" else stdenv.hostPlatform.parsed.cpu.name;
src = fetchzip {
url = "https://github.com/bazelbuild/bazel/releases/download/${version}/bazel-${version}-dist.zip";

View File

@@ -34,7 +34,7 @@
let
inherit (callPackage ./build-support/patching.nix { }) addFilePatch;
inherit (stdenv.hostPlatform) isDarwin;
inherit (stdenv.hostPlatform) isDarwin isAarch64;
defaultShellUtils =
# Keep this list conservative. For more exotic tools, prefer to use
@@ -85,8 +85,7 @@ let
bazelSystem = if isDarwin then "darwin" else "linux";
# on aarch64 Darwin, `uname -m` returns "arm64"
bazelArch =
if isDarwin then stdenv.hostPlatform.darwinArch else stdenv.hostPlatform.parsed.cpu.name;
bazelArch = if isDarwin && isAarch64 then "arm64" else stdenv.hostPlatform.parsed.cpu.name;
src = fetchzip {
url = "https://github.com/bazelbuild/bazel/releases/download/${version}/bazel-${version}-dist.zip";

View File

@@ -2,7 +2,6 @@
lib,
stdenv,
fetchFromGitHub,
fetchpatch,
pkg-config,
libuuid,
libsodium,
@@ -42,14 +41,6 @@ stdenv.mkDerivation (finalAttrs: {
hash = "sha256-H8uzTohV30NU1wYhr/WXN76g1zDqGEzRE5QZcmcM7Jc=";
};
# Fix build with linux-headers 7.3
patches = [
(fetchpatch {
url = "https://github.com/koverstreet/bcachefs-tools/commit/adef3bf68249ac674ddc2cbdfe8c7d0d153e15a8.diff";
hash = "sha256-nQsL+1fTQ4ltVyTIwIpO9z9nS66Dtr6WTepBZQ0phL8=";
})
];
cargoDeps = rustPlatform.fetchCargoVendor {
inherit (finalAttrs) src;
hash = "sha256-4ZStyYaT+6Suup1ue2wFFCTAlnsnEO9WaUJHe47BKXY=";

View File

@@ -58,7 +58,5 @@ stdenv.mkDerivation {
homepage = "https://github.com/hexagonal-sun/bic";
platforms = lib.platforms.unix;
maintainers = with lib.maintainers; [ hexagonal-sun ];
# never built on aarch64-darwin since first introduction in nixpkgs
broken = stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isAarch64;
};
}

View File

@@ -43,7 +43,7 @@ buildDotnetModule rec {
stdenv.cc.cc.lib
];
doCheck = !stdenv.hostPlatform.isDarwin; # mono is not available on aarch64-darwin
doCheck = !(stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isAarch64); # mono is not available on aarch64-darwin
meta = {
description = "Domain Specific Language (DSL) for deploying Azure resources declaratively";

View File

@@ -13,6 +13,8 @@ python3Packages.buildPythonApplication (finalAttrs: {
version = "2.19.0";
format = "wheel";
__structuredAttrs = true;
src = fetchPypi {
pname = "bitbake_setup";
inherit (finalAttrs) version;

View File

@@ -49,7 +49,7 @@ stdenv.mkDerivation (finalAttrs: {
installShellFiles
gnupg
]
++ lib.optionals stdenv.hostPlatform.isDarwin [
++ lib.optionals (stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isAarch64) [
darwin.autoSignDarwinBinariesHook
]
++ lib.optionals withGui [

View File

@@ -62,7 +62,7 @@ stdenv.mkDerivation (finalAttrs: {
installShellFiles
gnupg
]
++ lib.optionals stdenv.hostPlatform.isDarwin [
++ lib.optionals (stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isAarch64) [
autoSignDarwinBinariesHook
]
++ lib.optionals withGui [ qt6.wrapQtAppsHook ];

View File

@@ -6,26 +6,24 @@
libadwaita,
meson,
ninja,
python3,
runCommand,
stdenv,
testers,
wrapGAppsNoGuiHook,
xvfb-run,
gnome,
python3Packages,
}:
python3Packages.buildPythonApplication (finalAttrs: {
stdenv.mkDerivation (finalAttrs: {
pname = "blueprint-compiler";
version = "0.22.2";
pyproject = false;
version = "0.20.4";
src = fetchFromGitLab {
domain = "gitlab.gnome.org";
owner = "GNOME";
repo = "blueprint-compiler";
rev = "v${finalAttrs.version}";
hash = "sha256-DRpPUfiufwK2c2RW01IYIX6tgVyxfFl5hnv5F8+9aD4=";
hash = "sha256-dA+FQTRmTz6rl5ToZJ8CXY1Zd7Em7VwvF3U3Qoyvu80=";
};
postPatch = ''
@@ -36,11 +34,17 @@ python3Packages.buildPythonApplication (finalAttrs: {
gobject-introspection
meson
ninja
python3
wrapGAppsNoGuiHook
];
buildInputs = [
libadwaita
(python3.withPackages (
ps: with ps; [
pygobject3
]
))
];
propagatedBuildInputs = [
@@ -48,8 +52,6 @@ python3Packages.buildPythonApplication (finalAttrs: {
gobject-introspection
];
dependencies = [ python3Packages.pygobject3 ];
nativeCheckInputs = [
dbus
xvfb-run
@@ -68,13 +70,6 @@ python3Packages.buildPythonApplication (finalAttrs: {
runHook postCheck
'';
# Prevent double wrapping, let the Python wrapper use the args in preFixup.
dontWrapGApps = true;
preFixup = ''
makeWrapperArgs+=("''${gappsWrapperArgs[@]}")
'';
passthru = {
tests = {
version = testers.testVersion {

View File

@@ -74,8 +74,13 @@ stdenv.mkDerivation (finalAttrs: {
export NIX_LDFLAGS="$NIX_LDFLAGS -T $TMP/openbsd.ldscript"
'';
# `gctest` fails on aarch64-linux under qemu-user.
doCheck = !(stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isAarch64);
# `gctest` fails under x86_64 emulation on aarch64-darwin
# and also on aarch64-linux (qemu-user)
doCheck =
!(
(stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isx86_64)
|| (stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isAarch64)
);
enableParallelBuilding = true;

Some files were not shown because too many files have changed in this diff Show More