Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
71353962cf | ||
|
|
dc5399dedc | ||
|
|
19ad871b74 | ||
|
|
f76b2961e7 |
-24
@@ -16,27 +16,3 @@ Checks:
|
||||
- -bugprone-unchecked-optional-access
|
||||
# many warnings, seems like a questionable lint
|
||||
- -bugprone-branch-clone
|
||||
# extremely noisy before clang 19: https://github.com/llvm/llvm-project/issues/93959
|
||||
- -bugprone-multi-level-implicit-pointer-conversion
|
||||
# we don't compile out our asserts
|
||||
- -bugprone-assert-side-effect
|
||||
# FIXME(jade): figure out if this warning is any good
|
||||
- -bugprone-exception-escape
|
||||
# all thrown exceptions must derive from std::exception
|
||||
- hicpp-exception-baseclass
|
||||
# capturing async lambdas are dangerous
|
||||
- cppcoreguidelines-avoid-capturing-lambda-coroutines
|
||||
# crimes must be appropriately declared as crimes
|
||||
- cppcoreguidelines-pro-type-cstyle-cast
|
||||
- lix-*
|
||||
# This can not yet be applied to Lix itself since we need to do source
|
||||
# reorganization so that lix/ include paths work.
|
||||
- -lix-fixincludes
|
||||
# This lint is included as an example, but the lib function it replaces is
|
||||
# already gone.
|
||||
- -lix-hasprefixsuffix
|
||||
|
||||
|
||||
CheckOptions:
|
||||
bugprone-reserved-identifier.AllowedIdentifiers: '__asan_default_options'
|
||||
bugprone-unused-return-value.AllowCastToVoid: true
|
||||
|
||||
@@ -29,11 +29,3 @@ trim_trailing_whitespace = false
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
max_line_length = 0
|
||||
|
||||
[meson.build]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[*.json]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
name: Missing or incorrect documentation
|
||||
about: Help us improve the reference manual
|
||||
title: ''
|
||||
labels: docs
|
||||
labels: documentation
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
@@ -19,10 +19,10 @@ assignees: ''
|
||||
|
||||
<!-- make sure this issue is not redundant or obsolete -->
|
||||
|
||||
- [ ] checked [latest Lix manual] or its [source code]
|
||||
- [ ] checked [latest Lix manual] \([source]\)
|
||||
- [ ] checked [documentation issues] and [recent documentation changes] for possible duplicates
|
||||
|
||||
[latest Lix manual]: https://docs.lix.systems/manual/lix/nightly
|
||||
[source code]: https://git.lix.systems/lix-project/lix/src/main/doc/manual/src
|
||||
[latest Nix manual]: https://docs.lix.systems/manual/lix/nightly
|
||||
[source]: https://git.lix.systems/lix-project/lix/src/main/doc/manual/src
|
||||
[documentation issues]: https://git.lix.systems/lix-project/lix/issues?labels=151&state=all
|
||||
[recent documentation changes]: https://gerrit.lix.systems/q/p:lix+path:%22%5Edoc/manual/.*%22
|
||||
|
||||
-12
@@ -9,10 +9,6 @@ GTAGS
|
||||
# ccls
|
||||
/.ccls-cache
|
||||
|
||||
# auto-generated compilation database
|
||||
compile_commands.json
|
||||
rust-project.json
|
||||
|
||||
result
|
||||
result-*
|
||||
|
||||
@@ -33,11 +29,3 @@ buildtime.bin
|
||||
/.pre-commit-config.yaml
|
||||
/.nocontribmsg
|
||||
/release
|
||||
|
||||
# Rust build files when using Cargo (not actually supported for building but it spews the files anyway)
|
||||
/target/
|
||||
|
||||
# Python compiled files from the code generators and test suite
|
||||
*.pyc
|
||||
|
||||
**/.idea
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
Fiona Behrens <me@kloenk.dev>
|
||||
Fiona Behrens <me@kloenk.dev> <me@kloenk.de>
|
||||
Generated
-79
@@ -1,79 +0,0 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "countme"
|
||||
version = "3.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636"
|
||||
|
||||
[[package]]
|
||||
name = "dissimilar"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "59f8e79d1fbf76bdfbde321e902714bf6c49df88a7dda6fc682fc2979226962d"
|
||||
|
||||
[[package]]
|
||||
name = "expect-test"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e0be0a561335815e06dab7c62e50353134c796e7a6155402a64bcff66b6a5e0"
|
||||
dependencies = [
|
||||
"dissimilar",
|
||||
"once_cell",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||
|
||||
[[package]]
|
||||
name = "lix-doc"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"expect-test",
|
||||
"rnix",
|
||||
"rowan",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||
|
||||
[[package]]
|
||||
name = "rnix"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f15e00b0ab43abd70d50b6f8cd021290028f9b7fdd7cdfa6c35997173bc1ba9"
|
||||
dependencies = [
|
||||
"rowan",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rowan"
|
||||
version = "0.15.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0a542b0253fa46e632d27a1dc5cf7b930de4df8659dc6e720b647fc72147ae3d"
|
||||
dependencies = [
|
||||
"countme",
|
||||
"hashbrown",
|
||||
"rustc-hash",
|
||||
"text-size",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||
|
||||
[[package]]
|
||||
name = "text-size"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f18aa187839b2bdb1ad2fa35ead8c4c2976b64e4363c386d45ac0f7ee85c9233"
|
||||
@@ -1,6 +0,0 @@
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
members = ["lix/lix-doc"]
|
||||
|
||||
[workspace.package]
|
||||
edition = "2021"
|
||||
@@ -1,26 +0,0 @@
|
||||
# Docs
|
||||
per-file README.md=*
|
||||
per-file CONTRIBUTING.md=*
|
||||
|
||||
# DevX
|
||||
per-file justfile=*
|
||||
per-file .envrc=*
|
||||
per-file .gitignore=*
|
||||
per-file .github=*
|
||||
per-file .mailmap=*
|
||||
|
||||
# Build
|
||||
per-file meson.build=*
|
||||
per-file meson.options=*
|
||||
per-file flake.nix=*
|
||||
per-file flake.lock=*
|
||||
per-file *.nix=*
|
||||
per-file Cargo.lock=*
|
||||
per-file Cargo.toml=*
|
||||
per-file version.json=*
|
||||
|
||||
# Code style
|
||||
per-file .clang-tidy=*
|
||||
per-file .clang-format=*
|
||||
per-file .editorconfig=*
|
||||
per-file treefmt.toml=*
|
||||
@@ -17,16 +17,13 @@ For systems that **already have a Nix implementation installed**, such as NixOS
|
||||
|
||||
## Building And Developing
|
||||
|
||||
See our [Hacking guide](https://git.lix.systems/lix-project/lix/src/branch/main/doc/manual/src/contributing/hacking.md) in our manual for instruction on how to set up a development environment and build Lix from source.
|
||||
See our [Hacking guide](https://git.lix.systems/lix-project/lix/src/branch/main/doc/manual/src/contributing/hacking.md) in our manual for instruction on how to to set up a development environment and build Lix from source.
|
||||
|
||||
## Additional Resources
|
||||
|
||||
- The Lix reference manual:
|
||||
- [Stable](https://docs.lix.systems/manual/lix/stable/)
|
||||
- [Nightly](https://docs.lix.systems/manual/lix/nightly/) (NOTE: [not automatically updated, yet](https://git.lix.systems/lix-project/lix/issues/742))
|
||||
- [Our wiki](https://wiki.lix.systems)
|
||||
- [Matrix - #space:lix.systems](https://matrix.to/#/#space:lix.systems)
|
||||
|
||||
## License
|
||||
|
||||
Lix is released under [LGPL-2.1-or-later](./COPYING).
|
||||
Lix is released under the [LGPL v2.1](./COPYING).
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
bench-*.json
|
||||
bench-*.md
|
||||
perf-*.json
|
||||
nixpkgs
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
*
|
||||
-237
@@ -1,237 +0,0 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i python3 -p python3 -p hyperfine -p "if stdenv.isLinux then linuxPackages.perf else null"
|
||||
|
||||
import argparse
|
||||
import subprocess
|
||||
import os
|
||||
import json
|
||||
import tempfile
|
||||
import platform
|
||||
import shlex
|
||||
import textwrap
|
||||
import dataclasses
|
||||
|
||||
flake_args = ["--extra-experimental-features", "nix-command flakes"]
|
||||
cases = {
|
||||
"search": lambda build: [
|
||||
f"{build}/bin/nix",
|
||||
*flake_args,
|
||||
"search",
|
||||
"--no-eval-cache",
|
||||
"github:nixos/nixpkgs/e1fa12d4f6c6fe19ccb59cac54b5b3f25e160870",
|
||||
"hello",
|
||||
],
|
||||
"rebuild": lambda build: [
|
||||
f"{build}/bin/nix",
|
||||
*flake_args,
|
||||
"eval",
|
||||
"--raw",
|
||||
"--impure",
|
||||
"--expr",
|
||||
textwrap.dedent("""
|
||||
(import <nixpkgs/nixos> {
|
||||
configuration = ./bench/nixpkgs/nixos/modules/installer/cd-dvd/installation-cd-graphical-calamares-plasma6.nix;
|
||||
}).config.system.build.toplevel
|
||||
""").replace("\n", " "),
|
||||
],
|
||||
"rebuild_lh": lambda build: [
|
||||
"GC_INITIAL_HEAP_SIZE=10g",
|
||||
*cases['rebuild'](build),
|
||||
],
|
||||
"parse": lambda build: [
|
||||
f"{build}/bin/nix",
|
||||
*flake_args,
|
||||
"eval",
|
||||
"-f",
|
||||
"bench/nixpkgs/pkgs/development/haskell-modules/hackage-packages.nix",
|
||||
],
|
||||
}
|
||||
|
||||
arg_parser = argparse.ArgumentParser()
|
||||
# FIXME(jade, gilice): it is a reasonable use case to want to run a benchmark run
|
||||
# on just one build. However, since we are using hyperfine in comparison
|
||||
# mode, we would have to combine the JSON ourselves to support that, which
|
||||
# would probably be better done by writing a benchmarking script in
|
||||
# not-bash.
|
||||
arg_parser.add_argument(
|
||||
'builds',
|
||||
nargs='+',
|
||||
help="At least two build directories to compare, containing bin/nix",
|
||||
)
|
||||
arg_parser.add_argument(
|
||||
'--cases',
|
||||
type=str,
|
||||
help="A comma-separated list of cases you want to run. Defaults to running all",
|
||||
)
|
||||
arg_parser.add_argument(
|
||||
'--mode',
|
||||
nargs='+',
|
||||
choices=[ "walltime", "memory" ] + [ "icount" ] if platform.system() == 'Linux' else [], # perf doesn't run on Darwin
|
||||
default=[ "walltime" ],
|
||||
)
|
||||
arg_parser.add_argument(
|
||||
'--daemon',
|
||||
action='store_true',
|
||||
help='Run a temporary daemon for the benchmark instead of using a local store directly',
|
||||
)
|
||||
args = arg_parser.parse_args()
|
||||
if len(args.builds) < 1:
|
||||
raise ValueError("need at least one build directory to benchmark")
|
||||
|
||||
benchmarks: list[str] = []
|
||||
if args.cases is None:
|
||||
benchmarks = list(cases.keys())
|
||||
else:
|
||||
for case in args.cases.split(","):
|
||||
if case not in cases:
|
||||
raise ValueError(f"no such case: {case}")
|
||||
benchmarks.append(case)
|
||||
|
||||
def make_full_command(build, case):
|
||||
cmd = " ".join(map(shlex.quote, cases[case](build)))
|
||||
if args.daemon:
|
||||
return " ".join([
|
||||
f"{build}/bin/nix --extra-experimental-features nix-command daemon &",
|
||||
"trap 'kill %1' EXIT;",
|
||||
f"NIX_REMOTE=daemon {cmd}",
|
||||
])
|
||||
else:
|
||||
return cmd
|
||||
|
||||
def bench_walltime(env):
|
||||
for case in benchmarks:
|
||||
for build in args.builds:
|
||||
subprocess.run([
|
||||
"taskset", "-c", "2,3",
|
||||
"chrt", "-f","50",
|
||||
*[
|
||||
"hyperfine", "--warmup", "2", "--runs", "10",
|
||||
"--export-json", f"bench/bench-{case}-{build}.json",
|
||||
"--export-markdown", f"bench/bench-{case}-{build}.md",
|
||||
"--", make_full_command(build, case),
|
||||
],
|
||||
], env=env, check=True)
|
||||
|
||||
print("Benchmarks summary\n---\n")
|
||||
for case in benchmarks:
|
||||
results = []
|
||||
for build in args.builds:
|
||||
with open(f"bench/bench-{case}-{build}.json") as fd:
|
||||
results.append(json.load(fd)["results"][0])
|
||||
for result in results:
|
||||
print(result["command"])
|
||||
print("-" * min(80,len(result["command"])))
|
||||
def attr_rounded(attr):
|
||||
return f"{result[attr]:.3f}"
|
||||
print(" mean: ", attr_rounded("mean"), "±", attr_rounded("stddev"))
|
||||
print(" user:", attr_rounded("user"), "| system", attr_rounded("system"))
|
||||
print(" median: ", attr_rounded("median"))
|
||||
print(" range: ", attr_rounded("min") + "s.." + attr_rounded("max")+"s")
|
||||
print(" relative:", f"{result["mean"]/results[0]["mean"]:.3f}")
|
||||
print("\n")
|
||||
|
||||
|
||||
def bench_icount(env):
|
||||
perf_results_for: dict[str, list[tuple[str, float]]] = {}
|
||||
for case in benchmarks:
|
||||
for build in args.builds:
|
||||
# the perf stat -j output (incorrectly) localizes numbers, which will trip up the json parser.
|
||||
env["LC_ALL"]="C"
|
||||
case_command = make_full_command(build, case)
|
||||
commandline = [
|
||||
"perf", "stat", "-o", f"bench/perf-{case}.json", "-j",
|
||||
"sh", "-c", case_command,
|
||||
]
|
||||
print("running", case_command)
|
||||
subprocess.run(commandline, env=env, check=True, stdout=subprocess.DEVNULL) # warmup run
|
||||
subprocess.run(commandline, env=env, check=True, stdout=subprocess.DEVNULL)
|
||||
perf_fd = open(f"bench/perf-{case}.json")
|
||||
perf_data = [json.loads(x) for x in perf_fd.readlines()]
|
||||
perf_fd.close()
|
||||
|
||||
instr = next(x for x in perf_data if x["event"] in ["instructions", "instructions:u"]) # an implementation of a find_first iterator
|
||||
if case not in perf_results_for:
|
||||
perf_results_for[case] = []
|
||||
perf_results_for[case].append((case_command, float(instr["counter-value"])))
|
||||
|
||||
print("Benchmarks summary\n---\n")
|
||||
for (case, entries) in perf_results_for.items():
|
||||
for entry in entries:
|
||||
cmd,instr = entry
|
||||
print(cmd)
|
||||
print("-" * min(80,len(cmd)))
|
||||
print(" instructions: ", int(instr))
|
||||
print(" relative instructions:", int(instr)/perf_results_for[case][0][1])
|
||||
print("\n")
|
||||
|
||||
@dataclasses.dataclass
|
||||
class MemoryStatistics:
|
||||
envBytes: int
|
||||
listBytes: int
|
||||
setBytes: int
|
||||
valueBytes: int
|
||||
heapBytes: int
|
||||
heapSize: int
|
||||
|
||||
def bench_memory(env):
|
||||
path = "bench/bench-memory.json"
|
||||
env = env | {
|
||||
'NIX_SHOW_STATS': '1',
|
||||
'NIX_SHOW_STATS_PATH': path,
|
||||
}
|
||||
results: dict[str, list[tuple[str, MemoryStatistics]]] = {}
|
||||
for case in benchmarks:
|
||||
for build in args.builds:
|
||||
case_command = make_full_command(build, case)
|
||||
commandline = [ "sh", "-c", case_command ]
|
||||
print("running", case_command)
|
||||
subprocess.run(commandline, env=env, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
with open(path) as fd:
|
||||
stats = json.load(fd)
|
||||
results.setdefault(case, []).append((case_command, MemoryStatistics(
|
||||
envBytes=stats['envs']['bytes'],
|
||||
listBytes=stats['list']['bytes'],
|
||||
setBytes=stats['sets']['bytes'],
|
||||
valueBytes=stats['values']['bytes'],
|
||||
heapSize=stats['gc']['heapSize'],
|
||||
heapBytes=stats['gc']['totalBytes'],
|
||||
)))
|
||||
|
||||
print("Benchmarks summary\n---\n")
|
||||
for (case, entries) in results.items():
|
||||
for cmd, stats in entries:
|
||||
print(cmd)
|
||||
print("-" * min(80, len(cmd)))
|
||||
print(f" env bytes: {stats.envBytes :15d} | {(stats.envBytes / entries[0][1].envBytes) :.3f}x")
|
||||
print(f" list bytes: {stats.listBytes :15d} | {(stats.listBytes / entries[0][1].listBytes) :.3f}x")
|
||||
print(f" set bytes: {stats.setBytes :15d} | {(stats.setBytes / entries[0][1].setBytes) :.3f}x")
|
||||
if not entries[0][1].valueBytes:
|
||||
print(f" value bytes: {0:15d}")
|
||||
else:
|
||||
print(f" value bytes: {stats.valueBytes:15d} | {(stats.valueBytes / entries[0][1].valueBytes):.3f}x")
|
||||
print(f" heap alloc'd: {stats.heapBytes :15d} | {(stats.heapBytes / entries[0][1].heapBytes) :.3f}x")
|
||||
print(f" heap size: {stats.heapSize :15d} | {(stats.heapSize / entries[0][1].heapSize) :.3f}x")
|
||||
print("\n")
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmp_dir:
|
||||
subprocess.run([
|
||||
"nix", "build",
|
||||
"--extra-experimental-features", "nix-command flakes",
|
||||
"--impure", "--expr",'(builtins.getFlake "git+file:.").inputs.nixpkgs.outPath',
|
||||
"-o","bench/nixpkgs"
|
||||
], check=True)
|
||||
subenv = os.environ.copy()
|
||||
subenv["NIX_CONF_DIR"] = "/var/empty"
|
||||
subenv["NIX_REMOTE"] = tmp_dir
|
||||
subenv["NIX_PATH"] = ":".join([
|
||||
"nixpkgs=bench/nixpkgs",
|
||||
])
|
||||
subenv["NIX_DAEMON_SOCKET_PATH"] = f"{tmp_dir}/daemon"
|
||||
|
||||
for mode in args.mode:
|
||||
if mode == "walltime":
|
||||
bench_walltime(subenv)
|
||||
elif mode == "memory":
|
||||
bench_memory(subenv)
|
||||
else:
|
||||
bench_icount(subenv)
|
||||
Executable
+62
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
shopt -s inherit_errexit
|
||||
|
||||
scriptdir=$(cd "$(dirname -- "$0")" ; pwd -P)
|
||||
cd "$scriptdir/.."
|
||||
|
||||
if [[ $# -lt 2 ]]; then
|
||||
# FIXME(jade): it is a reasonable use case to want to run a benchmark run
|
||||
# on just one build. However, since we are using hyperfine in comparison
|
||||
# mode, we would have to combine the JSON ourselves to support that, which
|
||||
# would probably be better done by writing a benchmarking script in
|
||||
# not-bash.
|
||||
echo "Fewer than two result dirs given, nothing to compare!" >&2
|
||||
echo "Pass some directories (with names indicating which alternative they are) with bin/nix in them" >&2
|
||||
echo "Usage: ./bench/bench.sh result-1 result-2 [result-3...]" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
_exit=""
|
||||
trap "$_exit" EXIT
|
||||
|
||||
# XXX: yes this is very silly. flakes~!!
|
||||
nix build --impure --expr '(builtins.getFlake "git+file:.").inputs.nixpkgs.outPath' -o bench/nixpkgs
|
||||
|
||||
export NIX_REMOTE="$(mktemp -d)"
|
||||
_exit='rm -rfv "$NIX_REMOTE"; $_exit'
|
||||
export NIX_PATH="nixpkgs=bench/nixpkgs:nixos-config=bench/configuration.nix"
|
||||
|
||||
builds=("$@")
|
||||
|
||||
flake_args="--extra-experimental-features 'nix-command flakes'"
|
||||
|
||||
hyperfineArgs=(
|
||||
--parameter-list BUILD "$(IFS=,; echo "${builds[*]}")"
|
||||
--warmup 2 --runs 10
|
||||
)
|
||||
|
||||
declare -A cases
|
||||
cases=(
|
||||
[search]="{BUILD}/bin/nix $flake_args search --no-eval-cache github:nixos/nixpkgs/e1fa12d4f6c6fe19ccb59cac54b5b3f25e160870 hello"
|
||||
[rebuild]="{BUILD}/bin/nix $flake_args eval --raw --impure --expr 'with import <nixpkgs/nixos> {}; system'"
|
||||
[rebuild-lh]="GC_INITIAL_HEAP_SIZE=10g {BUILD}/bin/nix eval $flake_args --raw --impure --expr 'with import <nixpkgs/nixos> {}; system'"
|
||||
[parse]="{BUILD}/bin/nix $flake_args eval -f bench/nixpkgs/pkgs/development/haskell-modules/hackage-packages.nix"
|
||||
)
|
||||
|
||||
benches=(
|
||||
rebuild
|
||||
rebuild-lh
|
||||
search
|
||||
parse
|
||||
)
|
||||
|
||||
for k in "${benches[@]}"; do
|
||||
taskset -c 2,3 \
|
||||
chrt -f 50 \
|
||||
hyperfine "${hyperfineArgs[@]}" --export-json="bench/bench-${k}.json" --export-markdown="bench/bench-${k}.md" "${cases[$k]}"
|
||||
done
|
||||
|
||||
echo "Benchmarks summary (from ./bench/summarize.jq bench/bench-*.json)"
|
||||
bench/summarize.jq bench/*.json
|
||||
@@ -0,0 +1,325 @@
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
|
||||
{
|
||||
boot = {
|
||||
initrd = {
|
||||
availableKernelModules = [
|
||||
"xhci_pci"
|
||||
"ahci"
|
||||
];
|
||||
kernelModules = [ "dm-snapshot" ];
|
||||
luks.devices = {
|
||||
croot = {
|
||||
device = "/dev/sdb";
|
||||
allowDiscards = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
kernelModules = [ "kvm-intel" ];
|
||||
kernelPackages = pkgs.linuxPackages_latest;
|
||||
|
||||
loader = {
|
||||
systemd-boot.enable = true;
|
||||
efi.canTouchEfiVariables = true;
|
||||
};
|
||||
};
|
||||
|
||||
hardware = {
|
||||
enableRedistributableFirmware = true;
|
||||
cpu.intel.updateMicrocode = true;
|
||||
opengl.driSupport32Bit = true;
|
||||
opengl.extraPackages = with pkgs; [
|
||||
vaapiIntel
|
||||
intel-media-driver
|
||||
intel-compute-runtime
|
||||
];
|
||||
};
|
||||
|
||||
fileSystems = {
|
||||
"/" = {
|
||||
device = "/dev/sda2";
|
||||
fsType = "xfs";
|
||||
options = [ "noatime" ];
|
||||
};
|
||||
|
||||
"/boot" = {
|
||||
device = "/dev/sda1";
|
||||
fsType = "vfat";
|
||||
};
|
||||
|
||||
"/nas" = {
|
||||
device = "nas:/";
|
||||
fsType = "nfs4";
|
||||
options = [
|
||||
"ro"
|
||||
"x-systemd.automount"
|
||||
];
|
||||
};
|
||||
};
|
||||
swapDevices = [ { device = "/dev/swap"; } ];
|
||||
|
||||
networking = {
|
||||
useDHCP = false;
|
||||
hostName = "host";
|
||||
wireless = {
|
||||
enable = true;
|
||||
interfaces = [ "eth1" ];
|
||||
};
|
||||
interfaces = {
|
||||
eth0.useDHCP = true;
|
||||
eth1.useDHCP = true;
|
||||
};
|
||||
wg-quick.interfaces = {
|
||||
wg0 = {
|
||||
address = [ "2001:db8::1" ];
|
||||
privateKeyFile = "/etc/secrets/wg0.key";
|
||||
peers = [
|
||||
{
|
||||
publicKey = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
|
||||
endpoint = "[2001:db8::2]:61021";
|
||||
allowedIPs = [ "2001::db8:1::/64" ];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
firewall.allowedUDPPorts = [ 4567 ];
|
||||
};
|
||||
|
||||
i18n = {
|
||||
defaultLocale = "en_US.UTF-8";
|
||||
inputMethod.enabled = "ibus";
|
||||
};
|
||||
|
||||
services = {
|
||||
xserver = {
|
||||
enable = true;
|
||||
layout = "us";
|
||||
xkbVariant = "altgr-intl";
|
||||
xkbOptions = "ctrl:nocaps";
|
||||
libinput.enable = true;
|
||||
wacom.enable = true;
|
||||
videoDrivers = [ "modesetting" ];
|
||||
modules = [ pkgs.xf86_input_wacom ];
|
||||
|
||||
displayManager.sx.enable = true;
|
||||
windowManager.i3.enable = true;
|
||||
};
|
||||
|
||||
udev.extraHwdb = ''
|
||||
# not like this mattered at all
|
||||
# we're not running udev from here
|
||||
'';
|
||||
|
||||
udev.extraRules = ''
|
||||
# ACTION=="add", SUBSYSTEM=="input", ...
|
||||
'';
|
||||
};
|
||||
|
||||
sound.enable = true;
|
||||
hardware.pulseaudio = {
|
||||
enable = true;
|
||||
package = pkgs.pulseaudioFull;
|
||||
daemon.config = {
|
||||
lock-memory = "yes";
|
||||
realtime-scheduling = "yes";
|
||||
rlimit-rtprio = "-1";
|
||||
};
|
||||
};
|
||||
|
||||
programs = {
|
||||
light.enable = true;
|
||||
wireshark = {
|
||||
enable = true;
|
||||
package = pkgs.wireshark-qt;
|
||||
};
|
||||
gnupg.agent = {
|
||||
enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
fonts.packages = with pkgs; [
|
||||
font-awesome
|
||||
noto-fonts
|
||||
noto-fonts-cjk
|
||||
noto-fonts-emoji
|
||||
noto-fonts-extra
|
||||
dejavu_fonts
|
||||
powerline-fonts
|
||||
source-code-pro
|
||||
cantarell-fonts
|
||||
];
|
||||
|
||||
users = {
|
||||
mutableUsers = false;
|
||||
|
||||
users = {
|
||||
user = {
|
||||
isNormalUser = true;
|
||||
group = "user";
|
||||
extraGroups = [
|
||||
"wheel"
|
||||
"video"
|
||||
"audio"
|
||||
"dialout"
|
||||
"users"
|
||||
"kvm"
|
||||
"wireshark"
|
||||
];
|
||||
password = "unimportant";
|
||||
};
|
||||
};
|
||||
|
||||
groups = {
|
||||
user = { };
|
||||
};
|
||||
};
|
||||
|
||||
security = {
|
||||
pam.loginLimits = [
|
||||
{
|
||||
domain = "@audio";
|
||||
item = "memlock";
|
||||
type = "-";
|
||||
value = "unlimited";
|
||||
}
|
||||
{
|
||||
domain = "@audio";
|
||||
item = "rtprio";
|
||||
type = "-";
|
||||
value = "99";
|
||||
}
|
||||
{
|
||||
domain = "@audio";
|
||||
item = "nofile";
|
||||
type = "soft";
|
||||
value = "99999";
|
||||
}
|
||||
{
|
||||
domain = "@audio";
|
||||
item = "nofile";
|
||||
type = "hard";
|
||||
value = "99999";
|
||||
}
|
||||
];
|
||||
|
||||
sudo.extraRules = [
|
||||
{
|
||||
users = [ "user" ];
|
||||
commands = [
|
||||
{
|
||||
command = "${pkgs.linuxPackages.cpupower}/bin/cpupower";
|
||||
options = [ "NOPASSWD" ];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
a2jmidid
|
||||
age
|
||||
ardour
|
||||
bemenu
|
||||
blender
|
||||
breeze-icons
|
||||
breeze-qt5
|
||||
bubblewrap
|
||||
calf
|
||||
claws-mail
|
||||
darktable
|
||||
duperemove
|
||||
emacs
|
||||
feh
|
||||
file
|
||||
firefox
|
||||
fluidsynth
|
||||
gnome3.adwaita-icon-theme
|
||||
gnuplot
|
||||
graphviz
|
||||
helm
|
||||
i3status-rust
|
||||
inkscape
|
||||
jack2
|
||||
jq
|
||||
krita
|
||||
ldns
|
||||
libqalculate
|
||||
libreoffice
|
||||
man-pages
|
||||
nheko
|
||||
nix-diff
|
||||
nix-index
|
||||
nix-output-monitor
|
||||
open-music-kontrollers.patchmatrix
|
||||
pamixer
|
||||
pavucontrol
|
||||
pciutils
|
||||
picom
|
||||
pwgen
|
||||
redshift
|
||||
ripgrep
|
||||
rlwrap
|
||||
silver-searcher
|
||||
soundfont-fluid
|
||||
whois
|
||||
wol
|
||||
xclip
|
||||
xdot
|
||||
xdotool
|
||||
xorg.xkbcomp
|
||||
yt-dlp
|
||||
zathura
|
||||
borgbackup
|
||||
linuxPackages.cpupower
|
||||
mtr
|
||||
kitty
|
||||
xf86_input_wacom
|
||||
];
|
||||
|
||||
environment.pathsToLink = [ "/share/soundfonts" ];
|
||||
|
||||
systemd.user.services.run-python = {
|
||||
after = [ "network-online.target" ];
|
||||
script = ''
|
||||
exec ${pkgs.python3}/bin/python
|
||||
'';
|
||||
serviceConfig = {
|
||||
CapabilityBoundingSet = [ "" ];
|
||||
KeyringMode = "private";
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateDevices = true;
|
||||
PrivateTmp = true;
|
||||
PrivateUsers = true;
|
||||
ProcSubset = "pid";
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "invisible";
|
||||
ProtectSystem = "strict";
|
||||
RestrictAddressFamilies = "AF_INET AF_INET6";
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = [
|
||||
"@system-service"
|
||||
"~ @resources @privileged"
|
||||
];
|
||||
UMask = "077";
|
||||
};
|
||||
};
|
||||
|
||||
system.stateVersion = "23.11";
|
||||
}
|
||||
Executable
+22
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env -S jq -Mrf
|
||||
|
||||
def round3:
|
||||
. * 1000 | round | . / 1000
|
||||
;
|
||||
|
||||
def stats($first):
|
||||
[
|
||||
" mean: \(.mean | round3)s ± \(.stddev | round3)s",
|
||||
" user: \(.user | round3)s | system: \(.system | round3)s",
|
||||
" median: \(.median | round3)s",
|
||||
" range: \(.min | round3)s ... \(.max | round3)s",
|
||||
" relative: \(.mean / $first.mean | round3)"
|
||||
]
|
||||
| join("\n")
|
||||
;
|
||||
|
||||
def fmt($first):
|
||||
"\(.command)\n" + (. | stats($first))
|
||||
;
|
||||
|
||||
[.results | .[0] as $first | .[] | fmt($first)] | join("\n\n") | (. + "\n\n---\n")
|
||||
@@ -0,0 +1,54 @@
|
||||
diff --git a/pthread_stop_world.c b/pthread_stop_world.c
|
||||
index 2b45489..0e6d8ef 100644
|
||||
--- a/pthread_stop_world.c
|
||||
+++ b/pthread_stop_world.c
|
||||
@@ -776,6 +776,8 @@ STATIC void GC_restart_handler(int sig)
|
||||
/* world is stopped. Should not fail if it isn't. */
|
||||
GC_INNER void GC_push_all_stacks(void)
|
||||
{
|
||||
+ size_t stack_limit;
|
||||
+ pthread_attr_t pattr;
|
||||
GC_bool found_me = FALSE;
|
||||
size_t nthreads = 0;
|
||||
int i;
|
||||
@@ -868,6 +870,40 @@ GC_INNER void GC_push_all_stacks(void)
|
||||
hi = p->altstack + p->altstack_size;
|
||||
# endif
|
||||
/* FIXME: Need to scan the normal stack too, but how ? */
|
||||
+ } else {
|
||||
+ #ifdef HAVE_PTHREAD_ATTR_GET_NP
|
||||
+ if (pthread_attr_init(&pattr) != 0) {
|
||||
+ ABORT("GC_push_all_stacks: pthread_attr_init failed!");
|
||||
+ }
|
||||
+ if (pthread_attr_get_np(p->id, &pattr) != 0) {
|
||||
+ ABORT("GC_push_all_stacks: pthread_attr_get_np failed!");
|
||||
+ }
|
||||
+ #else
|
||||
+ if (pthread_getattr_np(p->id, &pattr)) {
|
||||
+ ABORT("GC_push_all_stacks: pthread_getattr_np failed!");
|
||||
+ }
|
||||
+ #endif
|
||||
+ if (pthread_attr_getstacksize(&pattr, &stack_limit)) {
|
||||
+ ABORT("GC_push_all_stacks: pthread_attr_getstacksize failed!");
|
||||
+ }
|
||||
+ if (pthread_attr_destroy(&pattr)) {
|
||||
+ ABORT("GC_push_all_stacks: pthread_attr_destroy failed!");
|
||||
+ }
|
||||
+ // When a thread goes into a coroutine, we lose its original sp until
|
||||
+ // control flow returns to the thread.
|
||||
+ // While in the coroutine, the sp points outside the thread stack,
|
||||
+ // so we can detect this and push the entire thread stack instead,
|
||||
+ // as an approximation.
|
||||
+ // We assume that the coroutine has similarly added its entire stack.
|
||||
+ // This could be made accurate by cooperating with the application
|
||||
+ // via new functions and/or callbacks.
|
||||
+ #ifndef STACK_GROWS_UP
|
||||
+ if (lo >= hi || lo < hi - stack_limit) { // sp outside stack
|
||||
+ lo = hi - stack_limit;
|
||||
+ }
|
||||
+ #else
|
||||
+ #error "STACK_GROWS_UP not supported in boost_coroutine2 (as of june 2021), so we don't support it in Nix."
|
||||
+ #endif
|
||||
}
|
||||
# ifdef STACKPTR_CORRECTOR_AVAILABLE
|
||||
if (GC_sp_corrector != 0)
|
||||
@@ -0,0 +1,90 @@
|
||||
#include "FixIncludes.hh"
|
||||
#include <clang-tidy/ClangTidyCheck.h>
|
||||
#include <clang/Basic/Diagnostic.h>
|
||||
#include <clang/Basic/SourceManager.h>
|
||||
#include <clang/Lex/PPCallbacks.h>
|
||||
#include <clang/Lex/Preprocessor.h>
|
||||
#include <llvm/ADT/StringRef.h>
|
||||
#include <llvm/Support/Debug.h>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
|
||||
namespace nix::clang_tidy {
|
||||
|
||||
using namespace clang;
|
||||
using namespace clang::tidy;
|
||||
|
||||
class FixIncludesCallbacks : public PPCallbacks {
|
||||
public:
|
||||
ClangTidyCheck &Check;
|
||||
Preprocessor &PP;
|
||||
FixIncludesCallbacks(ClangTidyCheck &Check, Preprocessor &PP)
|
||||
: Check(Check), PP(PP) {}
|
||||
|
||||
private:
|
||||
bool Ignore = false;
|
||||
virtual void LexedFileChanged(FileID FID, LexedFileChangeReason Reason,
|
||||
SrcMgr::CharacteristicKind FileType,
|
||||
FileID PrevFID, SourceLocation Loc) override;
|
||||
|
||||
virtual void InclusionDirective(SourceLocation HashLoc,
|
||||
const Token &IncludeTok, StringRef FileName,
|
||||
bool IsAngled, CharSourceRange FilenameRange,
|
||||
OptionalFileEntryRef File,
|
||||
StringRef SearchPath, StringRef RelativePath,
|
||||
const Module *Imported,
|
||||
SrcMgr::CharacteristicKind FileType) override;
|
||||
};
|
||||
|
||||
void FixIncludesCallbacks::LexedFileChanged(FileID, LexedFileChangeReason,
|
||||
SrcMgr::CharacteristicKind FileType,
|
||||
FileID, SourceLocation) {
|
||||
Ignore = FileType != SrcMgr::C_User;
|
||||
}
|
||||
|
||||
void FixIncludesCallbacks::InclusionDirective(
|
||||
SourceLocation, const Token &, StringRef FileName, bool IsAngled,
|
||||
CharSourceRange FilenameRange, OptionalFileEntryRef File, StringRef,
|
||||
StringRef, const Module *, SrcMgr::CharacteristicKind) {
|
||||
if (Ignore)
|
||||
return;
|
||||
|
||||
// FIXME: this is kinda evil, but this is a one-time fixup
|
||||
const std::vector<std::string> SourceDirs = {"src/", "include/lix/"};
|
||||
|
||||
const auto Bracketize = [IsAngled](StringRef s) {
|
||||
return IsAngled ? ("<" + s + ">").str() : ("\"" + s + "\"").str();
|
||||
};
|
||||
|
||||
for (const auto &SourceDir : SourceDirs) {
|
||||
const bool IsAlreadyFixed = FileName.starts_with("lix/lib");
|
||||
if (File && File->getNameAsRequested().contains(SourceDir) &&
|
||||
!IsAlreadyFixed) {
|
||||
StringRef Name = File->getNameAsRequested();
|
||||
auto Idx = Name.find(SourceDir);
|
||||
assert(Idx != std::string::npos);
|
||||
std::string Suffix = Name.drop_front(Idx + SourceDir.length()).str();
|
||||
|
||||
if (!Suffix.starts_with("lib")) {
|
||||
llvm::dbgs() << "ignored: " << Suffix << "\n";
|
||||
return;
|
||||
}
|
||||
|
||||
Suffix = "lix/" + Suffix;
|
||||
|
||||
auto Diag = Check.diag(FilenameRange.getBegin(),
|
||||
"include needs to specify the source subdir");
|
||||
|
||||
Diag << FilenameRange
|
||||
<< FixItHint::CreateReplacement(FilenameRange, Bracketize(Suffix));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FixIncludesCheck::registerPPCallbacks(const SourceManager &,
|
||||
Preprocessor *PP, Preprocessor *) {
|
||||
PP->addPPCallbacks(std::make_unique<FixIncludesCallbacks>(*this, *PP));
|
||||
}
|
||||
|
||||
}; // namespace nix::clang_tidy
|
||||
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
///@file
|
||||
|
||||
#include <clang-tidy/ClangTidyCheck.h>
|
||||
#include <clang/ASTMatchers/ASTMatchFinder.h>
|
||||
#include <llvm/ADT/StringRef.h>
|
||||
|
||||
namespace nix::clang_tidy {
|
||||
|
||||
using namespace clang;
|
||||
using namespace clang::tidy;
|
||||
|
||||
class FixIncludesCheck : public ClangTidyCheck {
|
||||
public:
|
||||
FixIncludesCheck(StringRef Name, ClangTidyContext *Context)
|
||||
: ClangTidyCheck(Name, Context) {}
|
||||
|
||||
void registerPPCallbacks(const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) override;
|
||||
};
|
||||
|
||||
};
|
||||
+3
-11
@@ -1,11 +1,7 @@
|
||||
#include "CharPtrCast.hh"
|
||||
#include "DisallowedDecls.hh"
|
||||
#include "ForeignExceptions.hh"
|
||||
#include "HasPrefixSuffix.hh"
|
||||
#include "NeverAsync.hh"
|
||||
#include "UnsafeCCalls.hh"
|
||||
#include <clang-tidy/ClangTidyModule.h>
|
||||
#include <clang-tidy/ClangTidyModuleRegistry.h>
|
||||
#include "FixIncludes.hh"
|
||||
#include "HasPrefixSuffix.hh"
|
||||
|
||||
namespace nix::clang_tidy {
|
||||
using namespace clang;
|
||||
@@ -15,11 +11,7 @@ class NixClangTidyChecks : public ClangTidyModule {
|
||||
public:
|
||||
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
|
||||
CheckFactories.registerCheck<HasPrefixSuffixCheck>("lix-hasprefixsuffix");
|
||||
CheckFactories.registerCheck<CharPtrCastCheck>("lix-charptrcast");
|
||||
CheckFactories.registerCheck<NeverAsync>("lix-never-async");
|
||||
CheckFactories.registerCheck<DisallowedDeclsCheck>("lix-disallowed-decls");
|
||||
CheckFactories.registerCheck<ForeignExceptions>("lix-foreign-exceptions");
|
||||
CheckFactories.registerCheck<UnsafeCCalls>("lix-unsafe-c-calls");
|
||||
CheckFactories.registerCheck<FixIncludesCheck>("lix-fixincludes");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -10,13 +10,13 @@ goal and is there as an example), `HasPrefixSuffixCheck`.
|
||||
One file:
|
||||
|
||||
```
|
||||
ninja -C build && clang-tidy --checks='-*,lix-*' --load=build/liblix-clang-tidy.so -p ../../build -header-filter '\.\./lix/.*\.h' --fix ../../lix/libcmd/installables.cc
|
||||
ninja -C build && clang-tidy --checks='-*,lix-*' --load=build/liblix-clang-tidy.so -p ../compile_commands.json -header-filter '\.\./src/.*\.h' --fix ../src/libcmd/installables.cc
|
||||
```
|
||||
|
||||
Several files, in parallel:
|
||||
|
||||
```
|
||||
ninja -C build && run-clang-tidy -checks='-*,lix-*' -load=build/liblix-clang-tidy.so -p ../../build -header-filter '\.\./lix/.*\.h' -fix ../../lix | tee -a clang-tidy-result
|
||||
ninja -C build && run-clang-tidy -checks='-*,lix-*' -load=build/liblix-clang-tidy.so -p .. -header-filter '\.\./src/.*\.h' -fix ../src | tee -a clang-tidy-result
|
||||
```
|
||||
|
||||
## Resources
|
||||
@@ -40,7 +40,7 @@ enable output dump
|
||||
match callExpr(callee(functionDecl(hasName("hasPrefix"))), optionally(hasArgument( 0, cxxConstructExpr(hasDeclaration(functionDecl(hasParameter(0, parmVarDecl(hasType(asString("const char *"))).bind("meow2"))))))))
|
||||
```
|
||||
|
||||
Then run, e.g. `clang-query --preload hasprefix.query -p compile_commands.json lix/libcmd/installables.cc`.
|
||||
Then run, e.g. `clang-query --preload hasprefix.query -p compile_commands.json src/libcmd/installables.cc`.
|
||||
|
||||
With this you can iterate a query before writing it in C++ and suffering from
|
||||
C++.
|
||||
@@ -0,0 +1,13 @@
|
||||
project('lix-clang-tidy', ['cpp', 'c'],
|
||||
version : '0.1',
|
||||
default_options : ['warning_level=3', 'cpp_std=c++20'])
|
||||
|
||||
llvm = dependency('Clang', version: '>= 14', modules: ['libclang'])
|
||||
sources = files(
|
||||
'HasPrefixSuffix.cc',
|
||||
'LixClangTidyChecks.cc',
|
||||
'FixIncludes.cc',
|
||||
)
|
||||
|
||||
shared_module('lix-clang-tidy', sources,
|
||||
dependencies: llvm)
|
||||
@@ -1 +0,0 @@
|
||||
*
|
||||
@@ -1,14 +0,0 @@
|
||||
plugin_mtls_store = shared_module(
|
||||
'plugin_mtls_store',
|
||||
'plugin_mtls_store.cc',
|
||||
dependencies : [
|
||||
liblixutil,
|
||||
liblixstore,
|
||||
liblixexpr,
|
||||
liblixfetchers,
|
||||
curl,
|
||||
],
|
||||
install : false,
|
||||
build_by_default : true,
|
||||
link_args : strict_shared_module_link_args,
|
||||
)
|
||||
@@ -1,13 +0,0 @@
|
||||
R"(
|
||||
|
||||
**Store URL format**: `https+mtls://...`
|
||||
|
||||
This store allows a binary cache to be accessed via the HTTPS
|
||||
protocol with mutual TLS mandated.
|
||||
|
||||
Two parameters can be passed to the query string:
|
||||
|
||||
- `tls-certificate`, a path to the TLS client certificate (optional)
|
||||
- `tls-private-key`, a path to the TLS private key backing the client certificate (required)
|
||||
|
||||
)"
|
||||
@@ -1,102 +0,0 @@
|
||||
#include "lix/libstore/store-api.hh"
|
||||
#include "lix/libutil/config.hh"
|
||||
#include "lix/libstore/http-binary-cache-store.hh"
|
||||
#include <stdlib.h>
|
||||
#include <curl/curl.h>
|
||||
|
||||
namespace nix {
|
||||
struct mTLSBinaryCacheStoreConfig : HttpBinaryCacheStoreConfig
|
||||
{
|
||||
using HttpBinaryCacheStoreConfig::HttpBinaryCacheStoreConfig;
|
||||
|
||||
const std::string name() override
|
||||
{
|
||||
return "mTLS HTTP Binary Cache Store";
|
||||
}
|
||||
|
||||
std::string doc() override
|
||||
{
|
||||
return
|
||||
#include "mtls-http-binary-cache-store.md"
|
||||
;
|
||||
}
|
||||
|
||||
PathsSetting<nix::Path> tlsCertificate{
|
||||
this,
|
||||
"",
|
||||
"tls-certificate",
|
||||
"Path of an optional TLS client certificate in PEM format as expected by CURLOPT_SSLCERT"
|
||||
};
|
||||
|
||||
PathsSetting<nix::Path> tlsKey{
|
||||
this,
|
||||
"",
|
||||
"tls-private-key",
|
||||
"Path of an TLS client certificate private key in PEM format as expected by CURLOPT_SSLKEY"
|
||||
};
|
||||
};
|
||||
|
||||
struct mTLSBinaryCacheStoreImpl : public HttpBinaryCacheStore
|
||||
{
|
||||
struct Keyring
|
||||
{
|
||||
nix::Path tlsCertificate;
|
||||
nix::Path tlsKey;
|
||||
};
|
||||
|
||||
mTLSBinaryCacheStoreConfig config_;
|
||||
std::shared_ptr<Keyring> keyring;
|
||||
|
||||
mTLSBinaryCacheStoreConfig & config() override
|
||||
{
|
||||
return config_;
|
||||
}
|
||||
const mTLSBinaryCacheStoreConfig & config() const override
|
||||
{
|
||||
return config_;
|
||||
}
|
||||
|
||||
mTLSBinaryCacheStoreImpl(
|
||||
const std::string & uriScheme, const Path & _cacheUri, mTLSBinaryCacheStoreConfig config
|
||||
)
|
||||
: Store(config)
|
||||
, HttpBinaryCacheStore("https", _cacheUri, config)
|
||||
, config_(std::move(config))
|
||||
, keyring(std::make_shared<Keyring>(config_.tlsCertificate.get(), config_.tlsKey.get()))
|
||||
{
|
||||
}
|
||||
|
||||
FileTransferOptions makeOptions(Headers && headers = {}) override
|
||||
{
|
||||
auto options = HttpBinaryCacheStore::makeOptions(std::move(headers));
|
||||
auto baseExtraSetup = std::move(options.extraSetup);
|
||||
auto keyring = this->keyring;
|
||||
|
||||
options.extraSetup =
|
||||
[keyring, baseExtraSetup{std::move(baseExtraSetup)}](CURL * req) {
|
||||
if (baseExtraSetup) {
|
||||
baseExtraSetup(req);
|
||||
}
|
||||
|
||||
if (!keyring->tlsCertificate.empty()) {
|
||||
curl_easy_setopt(req, CURLOPT_SSLCERT, keyring->tlsCertificate.c_str());
|
||||
}
|
||||
|
||||
curl_easy_setopt(req, CURLOPT_SSLKEY, keyring->tlsKey.c_str());
|
||||
};
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
static std::set<std::string> uriSchemes()
|
||||
{
|
||||
return {"https+mtls"};
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
extern "C" void nix_plugin_entry()
|
||||
{
|
||||
nix::StoreImplementations::add<nix::mTLSBinaryCacheStoreImpl, nix::mTLSBinaryCacheStoreConfig>();
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
*
|
||||
@@ -20,7 +20,7 @@ OUTPUT_DIRECTORY = @docdir@
|
||||
# for a project that appears at the top of each page and should give viewer a
|
||||
# quick idea about the purpose of the project. Keep the description short.
|
||||
|
||||
PROJECT_BRIEF = "Lix: A modern, delicious implementation of the Nix package manager; unstable internal interfaces"
|
||||
PROJECT_BRIEF = "Nix, the purely functional package manager; unstable internal interfaces"
|
||||
|
||||
# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
|
||||
# The default value is: YES.
|
||||
@@ -33,7 +33,32 @@ GENERATE_LATEX = NO
|
||||
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
|
||||
# Note: If this tag is empty the current directory is searched.
|
||||
|
||||
INPUT = @INPUT_PATHS@
|
||||
# FIXME Make this list more maintainable somehow. We could maybe generate this
|
||||
# in the Makefile, but we would need to change how `.in` files are preprocessed
|
||||
# so they can expand variables despite configure variables.
|
||||
|
||||
INPUT = \
|
||||
src/libcmd \
|
||||
src/libexpr \
|
||||
src/libexpr/flake \
|
||||
tests/unit/libexpr \
|
||||
tests/unit/libexpr/value \
|
||||
tests/unit/libexpr/test \
|
||||
tests/unit/libexpr/test/value \
|
||||
src/libexpr/value \
|
||||
src/libfetchers \
|
||||
src/libmain \
|
||||
src/libstore \
|
||||
src/libstore/build \
|
||||
src/libstore/builtins \
|
||||
tests/unit/libstore \
|
||||
tests/unit/libstore/test \
|
||||
src/libutil \
|
||||
tests/unit/libutil \
|
||||
tests/unit/libutil/test \
|
||||
src/nix \
|
||||
src/nix-env \
|
||||
src/nix-store
|
||||
|
||||
# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
|
||||
# in the source code. If set to NO, only conditional compilation will be
|
||||
@@ -72,15 +97,3 @@ EXPAND_AS_DEFINED = \
|
||||
DECLARE_WORKER_SERIALISER \
|
||||
DECLARE_SERVE_SERIALISER \
|
||||
LENGTH_PREFIXED_PROTO_HELPER
|
||||
|
||||
# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
|
||||
# Stripping is only done if one of the specified strings matches the left-hand
|
||||
# part of the path. The tag can be used to show relative paths in the file list.
|
||||
# If left blank the directory from which doxygen is run is used as the path to
|
||||
# strip.
|
||||
#
|
||||
# Note that you can specify absolute paths here, but also relative paths, which
|
||||
# will be relative from the directory where doxygen is started.
|
||||
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
|
||||
|
||||
STRIP_FROM_PATH = "@PROJECT_SOURCE_ROOT@"
|
||||
|
||||
@@ -1,35 +1,3 @@
|
||||
internal_api_sources = [
|
||||
'lix/libcmd',
|
||||
'lix/libexpr',
|
||||
'lix/libexpr/flake',
|
||||
'tests/unit/libexpr',
|
||||
'tests/unit/libexpr/value',
|
||||
'tests/unit/libexpr/test',
|
||||
'tests/unit/libexpr/test/value',
|
||||
'lix/libexpr/value',
|
||||
'lix/libfetchers',
|
||||
'lix/libmain',
|
||||
'lix/libstore',
|
||||
'lix/libstore/build',
|
||||
'lix/libstore/builtins',
|
||||
'tests/unit/libstore',
|
||||
'tests/unit/libstore/test',
|
||||
'lix/libutil',
|
||||
'tests/unit/libutil',
|
||||
'tests/unit/libutil/test',
|
||||
'lix/nix',
|
||||
'lix/nix-env',
|
||||
'lix/nix-store',
|
||||
]
|
||||
|
||||
# We feed Doxygen absolute paths so it can be invoked from any working directory.
|
||||
internal_api_sources_absolute = []
|
||||
foreach src : internal_api_sources
|
||||
internal_api_sources_absolute += '"' + (meson.project_source_root() / src) + '"'
|
||||
endforeach
|
||||
|
||||
internal_api_sources_oneline = ' \\\n '.join(internal_api_sources_absolute)
|
||||
|
||||
doxygen_cfg = configure_file(
|
||||
input : 'doxygen.cfg.in',
|
||||
output : 'doxygen.cfg',
|
||||
@@ -37,16 +5,22 @@ doxygen_cfg = configure_file(
|
||||
'PACKAGE_VERSION': meson.project_version(),
|
||||
'RAPIDCHECK_HEADERS': rapidcheck_meson.get_variable('includedir'),
|
||||
'docdir' : meson.current_build_dir(),
|
||||
'INPUT_PATHS' : internal_api_sources_oneline,
|
||||
'PROJECT_SOURCE_ROOT' : meson.project_source_root(),
|
||||
},
|
||||
)
|
||||
|
||||
internal_api_docs = custom_target(
|
||||
'internal-api-docs',
|
||||
command : [
|
||||
doxygen.full_path(),
|
||||
'@INPUT0@',
|
||||
bash,
|
||||
# Meson can you please just give us a `workdir` argument to custom targets...
|
||||
'-c',
|
||||
# We have to prefix the doxygen_cfg path with the project build root
|
||||
# because of the cd in front.
|
||||
'cd @0@ && @1@ @2@/@INPUT0@'.format(
|
||||
meson.project_source_root(),
|
||||
doxygen.full_path(),
|
||||
meson.project_build_root(),
|
||||
),
|
||||
],
|
||||
input : [
|
||||
doxygen_cfg,
|
||||
|
||||
@@ -7,8 +7,9 @@ create-missing = false
|
||||
[output.html]
|
||||
additional-css = ["custom.css"]
|
||||
additional-js = ["redirects.js"]
|
||||
# Jumps directly into a new Gerrit CL editing the file in question.
|
||||
edit-url-template = "https://gerrit.lix.systems/admin/repos/edit/repo/lix/branch/main/file/doc/manual/{path}"
|
||||
# Using our GitHub mirror enables easier typo fixes since there is no easy way
|
||||
# to just submit a Gerrit CL by the web for trivial stuff.
|
||||
edit-url-template = "https://github.com/lix-project/lix/tree/main/doc/manual/{path}"
|
||||
git-repository-url = "https://git.lix.systems/lix-project/lix"
|
||||
# Folding by default would prevent things like "Ctrl+F for nix-env" from working
|
||||
# trivially, but the user should be able to fold if they want to.
|
||||
|
||||
@@ -12,10 +12,6 @@
|
||||
forgejo: rbt
|
||||
github: 9999years
|
||||
|
||||
9p4:
|
||||
display_name: Ersei Saggi
|
||||
github: 9p4
|
||||
|
||||
Artturin:
|
||||
github: Artturin
|
||||
|
||||
@@ -40,23 +36,10 @@ alois31:
|
||||
forgejo: alois31
|
||||
github: alois31
|
||||
|
||||
andrewhamon:
|
||||
display_name: Andrew Hamon
|
||||
github: andrewhamon
|
||||
|
||||
artemist:
|
||||
display_name: Artemis Tosini
|
||||
forgejo: artemist
|
||||
|
||||
bb010g:
|
||||
display_name: Dusk Banks
|
||||
forgejo: bb010g
|
||||
github: bb010g
|
||||
|
||||
blitz:
|
||||
display_name: Julian Stecklina
|
||||
github: blitz
|
||||
|
||||
cole-h:
|
||||
display_name: Cole Helbling
|
||||
github: cole-h
|
||||
@@ -66,39 +49,14 @@ delan:
|
||||
forgejo: delan
|
||||
github: delan
|
||||
|
||||
delroth:
|
||||
github: delroth
|
||||
|
||||
detroyejr:
|
||||
display_name: Jonathan De Troye
|
||||
github: detroyejr
|
||||
|
||||
edolstra:
|
||||
display_name: Eelco Dolstra
|
||||
github: edolstra
|
||||
|
||||
emilazy:
|
||||
display_name: Emily
|
||||
forgejo: emilazy
|
||||
github: emilazy
|
||||
|
||||
ericson:
|
||||
display_name: John Ericson
|
||||
github: ericson2314
|
||||
|
||||
getchoo:
|
||||
display_name: Seth Flynn
|
||||
forgejo: getchoo
|
||||
github: getchoo
|
||||
|
||||
gilice:
|
||||
forgejo: gilice
|
||||
|
||||
goldstein:
|
||||
display_name: goldstein
|
||||
forgejo: goldstein
|
||||
github: GoldsteinE
|
||||
|
||||
horrors:
|
||||
display_name: eldritch horrors
|
||||
forgejo: pennae
|
||||
@@ -107,57 +65,14 @@ horrors:
|
||||
iFreilicht:
|
||||
github: iFreilicht
|
||||
|
||||
ian-h-chamberlain:
|
||||
forgejo: ian-h-chamberlain
|
||||
github: ian-h-chamberlain
|
||||
|
||||
infinisil:
|
||||
github: infinisil
|
||||
|
||||
isabelroses:
|
||||
forgejo: isabelroses
|
||||
github: isabelroses
|
||||
|
||||
jade:
|
||||
forgejo: jade
|
||||
github: lf-
|
||||
|
||||
just1602:
|
||||
forgejo: just1602
|
||||
|
||||
kasimeka:
|
||||
display_name: ورد
|
||||
forgejo: janw4ld
|
||||
github: kasimeka
|
||||
|
||||
kfears:
|
||||
display_name: KFears
|
||||
forgejo: kfearsoff
|
||||
github: kfearsoff
|
||||
|
||||
kiara:
|
||||
github: KiaraGrouwstra
|
||||
|
||||
kjeremy:
|
||||
github: kjeremy
|
||||
|
||||
kloenk:
|
||||
display_name: Fiona Behrens
|
||||
forgejo: kloenk
|
||||
github: kloenk
|
||||
|
||||
lheckemann:
|
||||
forgejo: lheckemann
|
||||
github: lheckemann
|
||||
|
||||
lily:
|
||||
forgejo: lilyinstarlight
|
||||
github: lilyinstarlight
|
||||
|
||||
lilyball:
|
||||
forgejo: lilyball
|
||||
github: lilyball
|
||||
|
||||
lovesegfault:
|
||||
github: lovesegfault
|
||||
|
||||
@@ -168,51 +83,19 @@ ma27:
|
||||
matthewbauer:
|
||||
github: matthewbauer
|
||||
|
||||
mic92:
|
||||
github: mic92
|
||||
|
||||
midnightveil:
|
||||
display_name: julia
|
||||
forgejo: midnightveil
|
||||
github: midnightveil
|
||||
|
||||
nan-git:
|
||||
display_name: NaN-git
|
||||
github: NaN-git
|
||||
|
||||
ncfavier:
|
||||
github: ncfavier
|
||||
|
||||
not-my-profile:
|
||||
display_name: Martin Fischer
|
||||
github: not-my-profile
|
||||
|
||||
p-e-meunier:
|
||||
display_name: Pierre-Etienne Meunier
|
||||
github: P-E-Meunier
|
||||
|
||||
pamplemousse:
|
||||
display_name: Xavier Maso
|
||||
github: pamplemousse
|
||||
|
||||
piegames:
|
||||
display_name: piegames
|
||||
forgejo: piegames
|
||||
github: piegamesde
|
||||
|
||||
poliorcetics:
|
||||
display_name: Poliorcetics
|
||||
github: poliorcetics
|
||||
|
||||
puck:
|
||||
display_name: puck
|
||||
forgejo: puck
|
||||
github: puckipedia
|
||||
|
||||
quantenzitrone:
|
||||
display_name: Zitrone
|
||||
forgejo: quantenzitrone
|
||||
|
||||
quantumjump:
|
||||
display_name: Quantum Jump
|
||||
github: QuantumBJump
|
||||
@@ -229,18 +112,6 @@ roberth:
|
||||
display_name: Robert Hensing
|
||||
github: roberth
|
||||
|
||||
seppel3210:
|
||||
github: Seppel3210
|
||||
|
||||
teofilc:
|
||||
forgejo: teofilc
|
||||
github: TeofilC
|
||||
|
||||
thubrecht:
|
||||
display_name: Tom Hubrecht
|
||||
forgejo: tom-hubrecht
|
||||
github: Tom-Hubrecht
|
||||
|
||||
thufschmitt:
|
||||
display_name: Théophane Hufschmitt
|
||||
github: thufschmitt
|
||||
@@ -253,34 +124,9 @@ valentin:
|
||||
display_name: Valentin Gagarin
|
||||
github: fricklerhandwerk
|
||||
|
||||
vigress8:
|
||||
display_name: Vigress
|
||||
forgejo: vigress8
|
||||
github: vigress8
|
||||
|
||||
vlaci:
|
||||
github: vlaci
|
||||
|
||||
vlinkz:
|
||||
display_name: Victor Fuentes
|
||||
forgejo: vlinkz
|
||||
github: vlinkz
|
||||
|
||||
winter:
|
||||
forgejo: winter
|
||||
github: winterqt
|
||||
|
||||
xanderio:
|
||||
github: xanderio
|
||||
|
||||
xokdvium:
|
||||
github: xokdvium
|
||||
|
||||
yorickvp:
|
||||
github: yorickvp
|
||||
|
||||
yshui:
|
||||
github: yshui
|
||||
|
||||
zimbatm:
|
||||
github: zimbatm
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
let
|
||||
inherit (builtins) concatStringsSep attrValues mapAttrs;
|
||||
inherit (import ./utils.nix) optionalString squash;
|
||||
in
|
||||
|
||||
builtinsInfo:
|
||||
let
|
||||
showBuiltin =
|
||||
name:
|
||||
{
|
||||
doc,
|
||||
type,
|
||||
impure-only,
|
||||
}:
|
||||
let
|
||||
type' = optionalString (type != null) " (${type})";
|
||||
|
||||
impureNotice = optionalString impure-only ''
|
||||
> **Note**
|
||||
>
|
||||
> Not available in [pure evaluation mode](@docroot@/command-ref/conf-file.md#conf-pure-eval).
|
||||
'';
|
||||
in
|
||||
squash ''
|
||||
<dt id="builtins-${name}">
|
||||
<a href="#builtins-${name}"><code>${name}</code></a>${type'}
|
||||
</dt>
|
||||
<dd>
|
||||
|
||||
${doc}
|
||||
|
||||
${impureNotice}
|
||||
|
||||
</dd>
|
||||
'';
|
||||
in
|
||||
concatStringsSep "\n" (attrValues (mapAttrs showBuiltin builtinsInfo))
|
||||
@@ -0,0 +1,35 @@
|
||||
let
|
||||
inherit (builtins) concatStringsSep attrValues mapAttrs;
|
||||
inherit (import ./utils.nix) optionalString squash;
|
||||
in
|
||||
|
||||
builtinsInfo:
|
||||
let
|
||||
showBuiltin =
|
||||
name:
|
||||
{
|
||||
doc,
|
||||
args,
|
||||
arity,
|
||||
experimental-feature,
|
||||
}:
|
||||
let
|
||||
experimentalNotice = optionalString (experimental-feature != null) ''
|
||||
This function is only available if the [${experimental-feature}](@docroot@/contributing/experimental-features.md#xp-feature-${experimental-feature}) experimental feature is enabled.
|
||||
'';
|
||||
in
|
||||
squash ''
|
||||
<dt id="builtins-${name}">
|
||||
<a href="#builtins-${name}"><code>${name} ${listArgs args}</code></a>
|
||||
</dt>
|
||||
<dd>
|
||||
|
||||
${doc}
|
||||
|
||||
${experimentalNotice}
|
||||
|
||||
</dd>
|
||||
'';
|
||||
listArgs = args: concatStringsSep " " (map (s: "<var>${s}</var>") args);
|
||||
in
|
||||
concatStringsSep "\n" (attrValues (mapAttrs showBuiltin builtinsInfo))
|
||||
+23
-131
@@ -1,134 +1,26 @@
|
||||
with builtins;
|
||||
|
||||
let
|
||||
splitLines = s: filter (x: !isList x) (split "\n" s);
|
||||
|
||||
concatStrings = concatStringsSep "";
|
||||
|
||||
replaceStringsRec =
|
||||
from: to: string:
|
||||
# recursively replace occurrences of `from` with `to` within `string`
|
||||
# example:
|
||||
# replaceStringRec "--" "-" "hello-----world"
|
||||
# => "hello-world"
|
||||
let
|
||||
replaced = replaceStrings [ from ] [ to ] string;
|
||||
in
|
||||
if replaced == string then string else replaceStringsRec from to replaced;
|
||||
|
||||
squash = replaceStringsRec "\n\n\n" "\n\n";
|
||||
|
||||
trim =
|
||||
string:
|
||||
# trim trailing spaces and squash non-leading spaces
|
||||
let
|
||||
trimLine =
|
||||
line:
|
||||
let
|
||||
# separate leading spaces from the rest
|
||||
parts = split "(^ *)" line;
|
||||
spaces = head (elemAt parts 1);
|
||||
rest = elemAt parts 2;
|
||||
# drop trailing spaces
|
||||
body = head (split " *$" rest);
|
||||
in
|
||||
spaces + replaceStringsRec " " " " body;
|
||||
in
|
||||
concatStringsSep "\n" (map trimLine (splitLines string));
|
||||
|
||||
# FIXME: O(n^2)
|
||||
unique = foldl' (acc: e: if elem e acc then acc else acc ++ [ e ]) [ ];
|
||||
|
||||
nameValuePair = name: value: { inherit name value; };
|
||||
|
||||
filterAttrs =
|
||||
pred: set:
|
||||
listToAttrs (
|
||||
concatMap (
|
||||
name:
|
||||
let
|
||||
v = set.${name};
|
||||
in
|
||||
if pred name v then [ (nameValuePair name v) ] else [ ]
|
||||
) (attrNames set)
|
||||
);
|
||||
|
||||
optionalString = cond: string: if cond then string else "";
|
||||
|
||||
showSetting =
|
||||
{ inlineHTML }:
|
||||
name:
|
||||
{
|
||||
description,
|
||||
documentDefault,
|
||||
defaultValue,
|
||||
aliases,
|
||||
value,
|
||||
experimentalFeature,
|
||||
}:
|
||||
let
|
||||
result = squash ''
|
||||
- ${
|
||||
if inlineHTML then ''<span id="conf-${name}">[`${name}`](#conf-${name})</span>'' else ''`${name}`''
|
||||
}
|
||||
|
||||
${indent " " body}
|
||||
'';
|
||||
|
||||
experimentalFeatureNote = optionalString (experimentalFeature != null) ''
|
||||
> **Warning**
|
||||
> This setting is part of an
|
||||
> [experimental feature](@docroot@/contributing/experimental-features.md).
|
||||
|
||||
To change this setting, you need to make sure the corresponding experimental feature,
|
||||
[`${experimentalFeature}`](@docroot@/contributing/experimental-features.md#xp-feature-${experimentalFeature}),
|
||||
is enabled.
|
||||
For example, include the following in [`nix.conf`](#):
|
||||
|
||||
```
|
||||
extra-experimental-features = ${experimentalFeature}
|
||||
${name} = ...
|
||||
```
|
||||
'';
|
||||
|
||||
# separate body to cleanly handle indentation
|
||||
body = ''
|
||||
${description}
|
||||
|
||||
${experimentalFeatureNote}
|
||||
|
||||
**Default:** ${showDefault documentDefault defaultValue}
|
||||
|
||||
${showAliases aliases}
|
||||
'';
|
||||
|
||||
showDefault =
|
||||
documentDefault: defaultValue:
|
||||
if documentDefault then
|
||||
# a StringMap value type is specified as a string, but
|
||||
# this shows the value type. The empty stringmap is `null` in
|
||||
# JSON, but that converts to `{ }` here.
|
||||
if defaultValue == "" || defaultValue == [ ] || isAttrs defaultValue then
|
||||
"*empty*"
|
||||
else if isBool defaultValue then
|
||||
if defaultValue then "`true`" else "`false`"
|
||||
else
|
||||
"`${toString defaultValue}`"
|
||||
else
|
||||
"*machine-specific*";
|
||||
|
||||
showAliases =
|
||||
aliases:
|
||||
optionalString (aliases != [ ])
|
||||
"**Deprecated alias:** ${(concatStringsSep ", " (map (s: "`${s}`") aliases))}";
|
||||
in
|
||||
result;
|
||||
|
||||
indent =
|
||||
prefix: s: concatStringsSep "\n" (map (x: if x == "" then x else "${prefix}${x}") (splitLines s));
|
||||
|
||||
showSettings =
|
||||
args: settingsInfo: concatStrings (attrValues (mapAttrs (showSetting args) settingsInfo));
|
||||
inherit (builtins)
|
||||
attrNames
|
||||
attrValues
|
||||
fromJSON
|
||||
listToAttrs
|
||||
mapAttrs
|
||||
concatStringsSep
|
||||
concatMap
|
||||
length
|
||||
lessThan
|
||||
replaceStrings
|
||||
sort
|
||||
;
|
||||
inherit (import ./utils.nix)
|
||||
concatStrings
|
||||
optionalString
|
||||
filterAttrs
|
||||
trim
|
||||
squash
|
||||
unique
|
||||
showSettings
|
||||
;
|
||||
in
|
||||
|
||||
inlineHTML: commandDump:
|
||||
@@ -225,7 +117,7 @@ let
|
||||
showCategory = cat: ''
|
||||
${optionalString (cat != "") "**${cat}:**"}
|
||||
|
||||
${listOptions (filterAttrs (n: v: v.category == cat && !v.hidden) allOptions)}
|
||||
${listOptions (filterAttrs (n: v: v.category == cat) allOptions)}
|
||||
'';
|
||||
listOptions = opts: concatStringsSep "\n" (attrValues (mapAttrs showOption opts));
|
||||
showOption =
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
with builtins;
|
||||
with import ./utils.nix;
|
||||
|
||||
let
|
||||
showExperimentalFeature = name: doc: ''
|
||||
- [`${name}`](@docroot@/contributing/experimental-features.md#xp-feature-${name})
|
||||
'';
|
||||
in
|
||||
xps: indent " " (concatStrings (attrValues (mapAttrs showExperimentalFeature xps)))
|
||||
@@ -0,0 +1,13 @@
|
||||
with builtins;
|
||||
with import ./utils.nix;
|
||||
|
||||
let
|
||||
showExperimentalFeature =
|
||||
name: doc:
|
||||
squash ''
|
||||
## [`${name}`]{#xp-feature-${name}}
|
||||
|
||||
${doc}
|
||||
'';
|
||||
in
|
||||
xps: (concatStringsSep "\n" (attrValues (mapAttrs showExperimentalFeature xps)))
|
||||
+55
-11
@@ -1,7 +1,6 @@
|
||||
nix_env_for_docs = {
|
||||
'HOME': '/dummy',
|
||||
'NIX_CONF_DIR': '/dummy',
|
||||
'XDG_CONFIG_HOME': '/dummy',
|
||||
'NIX_SSL_CERT_FILE': '/dummy/no-ca-bundle.crt',
|
||||
'NIX_STATE_DIR': '/dummy',
|
||||
'NIX_CONFIG': 'cores = 0',
|
||||
@@ -16,21 +15,67 @@ nix_eval_for_docs_common = nix_for_docs + [
|
||||
]
|
||||
nix_eval_for_docs = nix_eval_for_docs_common + '--raw'
|
||||
|
||||
conf_file_json = custom_target(
|
||||
command : nix_for_docs + [ 'show-config', '--json' ],
|
||||
capture : true,
|
||||
output : 'conf-file.json',
|
||||
env : nix_env_for_docs,
|
||||
)
|
||||
|
||||
nix_conf_file_md_body = custom_target(
|
||||
command : nix_eval_for_docs + [
|
||||
'--expr',
|
||||
'(import @INPUT0@).showSettings { inlineHTML = true; } (builtins.fromJSON (builtins.readFile @INPUT1@))',
|
||||
],
|
||||
capture : true,
|
||||
input : [
|
||||
'utils.nix',
|
||||
conf_file_json,
|
||||
],
|
||||
output : 'conf-file.md.body',
|
||||
env : nix_env_for_docs,
|
||||
)
|
||||
|
||||
nix_conf_file_md = custom_target(
|
||||
command : [ 'cat', '@INPUT@' ],
|
||||
capture : true,
|
||||
input : [
|
||||
'src/command-ref/conf-file.md',
|
||||
nix_conf_file_md_body,
|
||||
],
|
||||
output : 'conf-file.md',
|
||||
)
|
||||
|
||||
nix_exp_features_json = custom_target(
|
||||
command : [ nix, '__dump-xp-features' ],
|
||||
capture : true,
|
||||
output : 'xp-features.json',
|
||||
)
|
||||
|
||||
language_json = custom_target(
|
||||
command: [nix, '__dump-language'],
|
||||
output : 'language.json',
|
||||
capture : true,
|
||||
env : nix_env_for_docs,
|
||||
)
|
||||
|
||||
nix3_cli_json = custom_target(
|
||||
command : [ nix, '__dump-cli' ],
|
||||
capture : true,
|
||||
output : 'nix.json',
|
||||
env : nix_env_for_docs,
|
||||
# FIXME: put the actual lib targets in here? meson have introspection challenge 2024 though.
|
||||
build_always_stale : true,
|
||||
)
|
||||
|
||||
generate_manual_deps = files(
|
||||
'generate-deps.py',
|
||||
)
|
||||
|
||||
# Generates new-cli pages and conf-file.md.
|
||||
# Generates builtins.md and builtin-constants.md.
|
||||
subdir('src/language')
|
||||
# Generates new-cli pages, experimental-features-shortlist.md, and conf-file.md.
|
||||
subdir('src/command-ref')
|
||||
# Generates experimental-feature-descriptions.md.
|
||||
subdir('src/contributing')
|
||||
# Generates rl-next-generated.md.
|
||||
subdir('src/release-notes')
|
||||
|
||||
@@ -61,8 +106,6 @@ manual = custom_target(
|
||||
nix3_cli_files,
|
||||
experimental_features_shortlist_md,
|
||||
experimental_feature_descriptions_md,
|
||||
deprecated_features_shortlist_md,
|
||||
deprecated_feature_descriptions_md,
|
||||
conf_file_md,
|
||||
builtins_md,
|
||||
builtin_constants_md,
|
||||
@@ -73,19 +116,20 @@ manual = custom_target(
|
||||
'manual',
|
||||
'markdown',
|
||||
],
|
||||
install : true,
|
||||
install_dir : [
|
||||
datadir / 'doc/nix',
|
||||
false,
|
||||
],
|
||||
depfile : 'manual.d',
|
||||
env : {
|
||||
'RUST_LOG': 'info',
|
||||
'MDBOOK_SUBSTITUTE_SEARCH': meson.current_build_dir() / 'src',
|
||||
},
|
||||
)
|
||||
manual_html = manual[0]
|
||||
manual_md = manual[1]
|
||||
|
||||
install_subdir(
|
||||
manual_html.full_path(),
|
||||
install_dir : datadir / 'doc/nix',
|
||||
)
|
||||
|
||||
nix_nested_manpages = [
|
||||
[ 'nix-env',
|
||||
[
|
||||
|
||||
@@ -345,7 +345,7 @@ const redirects = {
|
||||
"linux": "uninstall.html#linux",
|
||||
"macos": "uninstall.html#macos",
|
||||
"uninstalling": "uninstall.html",
|
||||
},
|
||||
}
|
||||
"contributing/hacking.html": {
|
||||
"nix-with-flakes": "#building-nix-with-flakes",
|
||||
"classic-nix": "#building-nix",
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
---
|
||||
synopsis: "Trace which part of a `foo.bar.baz` expression errors"
|
||||
cls: 1505, 1506
|
||||
credits: Qyriad
|
||||
category: Improvements
|
||||
---
|
||||
|
||||
Previously, if an attribute path selection expression like `linux_4_9.meta.description` it wouldn't show you which one of those parts in the attribute path, or even that that line of code is what caused evaluation of the failing expression.
|
||||
The previous error looks like this:
|
||||
|
||||
```
|
||||
pkgs.linuxKernel.kernels.linux_4_9.meta.description
|
||||
|
||||
error:
|
||||
… while evaluating the attribute 'linuxKernel.kernels.linux_4_9.meta.description'
|
||||
at /nix/store/dk2rpyb6ndvfbf19bkb2plcz5y3k8i5v-source/pkgs/top-level/linux-kernels.nix:278:5:
|
||||
277| } // lib.optionalAttrs config.allowAliases {
|
||||
278| linux_4_9 = throw "linux 4.9 was removed because it will reach its end of life within 22.11";
|
||||
| ^
|
||||
279| linux_4_14 = throw "linux 4.14 was removed because it will reach its end of life within 23.11";
|
||||
|
||||
… while calling the 'throw' builtin
|
||||
at /nix/store/dk2rpyb6ndvfbf19bkb2plcz5y3k8i5v-source/pkgs/top-level/linux-kernels.nix:278:17:
|
||||
277| } // lib.optionalAttrs config.allowAliases {
|
||||
278| linux_4_9 = throw "linux 4.9 was removed because it will reach its end of life within 22.11";
|
||||
| ^
|
||||
279| linux_4_14 = throw "linux 4.14 was removed because it will reach its end of life within 23.11";
|
||||
|
||||
error: linux 4.9 was removed because it will reach its end of life within 22.11
|
||||
```
|
||||
|
||||
Now, the error will look like this:
|
||||
|
||||
```
|
||||
pkgs.linuxKernel.kernels.linux_4_9.meta.description
|
||||
|
||||
error:
|
||||
… while evaluating the attribute 'linuxKernel.kernels.linux_4_9.meta.description'
|
||||
at /nix/store/dk2rpyb6ndvfbf19bkb2plcz5y3k8i5v-source/pkgs/top-level/linux-kernels.nix:278:5:
|
||||
277| } // lib.optionalAttrs config.allowAliases {
|
||||
278| linux_4_9 = throw "linux 4.9 was removed because it will reach its end of life within 22.11";
|
||||
| ^
|
||||
279| linux_4_14 = throw "linux 4.14 was removed because it will reach its end of life within 23.11";
|
||||
|
||||
… while evaluating 'pkgs.linuxKernel.kernels.linux_4_9' to select 'meta' on it
|
||||
at «string»:1:1:
|
||||
1| pkgs.linuxKernel.kernels.linux_4_9.meta.description
|
||||
| ^
|
||||
|
||||
… caused by explicit throw
|
||||
at /nix/store/dk2rpyb6ndvfbf19bkb2plcz5y3k8i5v-source/pkgs/top-level/linux-kernels.nix:278:17:
|
||||
277| } // lib.optionalAttrs config.allowAliases {
|
||||
278| linux_4_9 = throw "linux 4.9 was removed because it will reach its end of life within 22.11";
|
||||
| ^
|
||||
279| linux_4_14 = throw "linux 4.14 was removed because it will reach its end of life within 23.11";
|
||||
|
||||
error: linux 4.9 was removed because it will reach its end of life within 22.11
|
||||
```
|
||||
|
||||
Not only does the line of code that referenced the failing attribute show up in the trace, it also tells you that it was specifically the `linux_4_9` part that failed.
|
||||
|
||||
This includes if the failing part is a top-level binding:
|
||||
|
||||
```
|
||||
let
|
||||
inherit (pkgs.linuxKernel.kernels) linux_4_9;
|
||||
in linux_4_9.meta.description
|
||||
error:
|
||||
… while evaluating 'linux_4_9' to select 'meta.description' on it
|
||||
at «string»:3:4:
|
||||
2| inherit (pkgs.linuxKernel.kernels) linux_4_9;
|
||||
3| in linux_4_9.meta.description
|
||||
| ^
|
||||
|
||||
… while evaluating the attribute 'linux_4_9'
|
||||
at /nix/store/dk2rpyb6ndvfbf19bkb2plcz5y3k8i5v-source/pkgs/top-level/linux-kernels.nix:278:5:
|
||||
277| } // lib.optionalAttrs config.allowAliases {
|
||||
278| linux_4_9 = throw "linux 4.9 was removed because it will reach its end of life within 22.11";
|
||||
| ^
|
||||
279| linux_4_14 = throw "linux 4.14 was removed because it will reach its end of life within 23.11";
|
||||
|
||||
… caused by explicit throw
|
||||
at /nix/store/dk2rpyb6ndvfbf19bkb2plcz5y3k8i5v-source/pkgs/top-level/linux-kernels.nix:278:17:
|
||||
277| } // lib.optionalAttrs config.allowAliases {
|
||||
278| linux_4_9 = throw "linux 4.9 was removed because it will reach its end of life within 22.11";
|
||||
| ^
|
||||
279| linux_4_14 = throw "linux 4.14 was removed because it will reach its end of life within 23.11";
|
||||
|
||||
error: linux 4.9 was removed because it will reach its end of life within 22.11
|
||||
```
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
synopsis: "Add a `build-dir` setting to set the backing directory for builds"
|
||||
cls: 1514
|
||||
credits: [roberth, tomberek]
|
||||
category: Improvements
|
||||
---
|
||||
|
||||
`build-dir` can now be set in the Nix configuration to choose the backing directory for the build sandbox.
|
||||
This can be useful on systems with `/tmp` on tmpfs, or simply to relocate large builds to another disk.
|
||||
|
||||
Also, `XDG_RUNTIME_DIR` is no longer considered when selecting the default temporary directory,
|
||||
as it's not intended to be used for large amounts of data.
|
||||
@@ -0,0 +1,70 @@
|
||||
---
|
||||
synopsis: "Distinguish between explicit throws and errors that happened while evaluating a throw"
|
||||
cls: 1511
|
||||
credits: Qyriad
|
||||
category: Improvements
|
||||
---
|
||||
|
||||
Previously, errors caused by an expression like `throw "invalid argument"` were treated like an error that happened simply while some builtin function was being called:
|
||||
|
||||
```
|
||||
let
|
||||
throwMsg = p: throw "${p} isn't the right package";
|
||||
in throwMsg "linuz"
|
||||
|
||||
error:
|
||||
… while calling the 'throw' builtin
|
||||
at «string»:2:17:
|
||||
1| let
|
||||
2| throwMsg = p: throw "${p} isn't the right package";
|
||||
| ^
|
||||
3| in throwMsg "linuz"
|
||||
|
||||
error: linuz isn't the right package
|
||||
```
|
||||
|
||||
But the error didn't just happen "while" calling the `throw` builtin — it's a throw error!
|
||||
Now it looks like this:
|
||||
|
||||
```
|
||||
let
|
||||
throwMsg = p: throw "${p} isn't the right package";
|
||||
in throwMsg "linuz"
|
||||
|
||||
error:
|
||||
… caused by explicit throw
|
||||
at «string»:2:17:
|
||||
1| let
|
||||
2| throwMsg = p: throw "${p} isn't the right package";
|
||||
| ^
|
||||
3| in throwMsg "linuz"
|
||||
|
||||
error: linuz isn't the right package
|
||||
```
|
||||
|
||||
This also means that incorrect usage of `throw` or errors evaluating its arguments are easily distinguishable from explicit throws:
|
||||
|
||||
```
|
||||
let
|
||||
throwMsg = p: throw "${p} isn't the right package";
|
||||
in throwMsg { attrs = "error when coerced in string interpolation"; }
|
||||
|
||||
error:
|
||||
… while calling the 'throw' builtin
|
||||
at «string»:2:17:
|
||||
1| let
|
||||
2| throwMsg = p: throw "${p} isn't the right package";
|
||||
| ^
|
||||
3| in throwMsg { attrs = "error when coerced in string interpolation"; }
|
||||
|
||||
… while evaluating a path segment
|
||||
at «string»:2:24:
|
||||
1| let
|
||||
2| throwMsg = p: throw "${p} isn't the right package";
|
||||
| ^
|
||||
3| in throwMsg { attrs = "error when coerced in string interpolation"; }
|
||||
|
||||
error: cannot coerce a set to a string: { attrs = "error when coerced in string interpolation"; }
|
||||
```
|
||||
|
||||
Here, instead of an actual thrown error, a type error happens first (trying to coerce an attribute set to a string), but that type error happened *while* calling `throw`.
|
||||
@@ -0,0 +1,29 @@
|
||||
---
|
||||
synopsis: Fix nix-collect-garbage --dry-run
|
||||
issues: [fj#432]
|
||||
cls: [1566]
|
||||
category: Fixes
|
||||
credits: [quantumjump]
|
||||
---
|
||||
|
||||
`nix-collect-garbage --dry-run` did not previously give any output - it simply
|
||||
exited without even checking to see what paths would be deleted.
|
||||
|
||||
```
|
||||
$ nix-collect-garbage --dry-run
|
||||
$
|
||||
```
|
||||
|
||||
We updated the behaviour of the flag such that instead it prints out how many
|
||||
paths it *would* delete, but doesn't actually delete them.
|
||||
|
||||
```
|
||||
$ nix-collect-garbage --dry-run
|
||||
finding garbage collector roots...
|
||||
determining live/dead paths...
|
||||
...
|
||||
<nix store paths>
|
||||
...
|
||||
2670 store paths deleted, 0.00MiB freed
|
||||
$
|
||||
```
|
||||
@@ -0,0 +1,16 @@
|
||||
---
|
||||
synopsis: "Hash mismatch diagnostics for fixed-output derivations include the URL"
|
||||
cls: [1536]
|
||||
credits: [jade]
|
||||
category: Improvements
|
||||
---
|
||||
|
||||
Now, when building fixed-output derivations, Lix will guess the URL that was used in the derivation using the `url` or `urls` properties in the derivation environment.
|
||||
This is a layering violation but making these diagnostics tractable when there are multiple instances of the `AAAA` hash is too significant of an improvement to pass it up.
|
||||
|
||||
```
|
||||
error: hash mismatch in fixed-output derivation '/nix/store/sjfw324j4533lwnpmr5z4icpb85r63ai-x1.drv':
|
||||
likely URL: https://meow.puppy.forge/puppy.tar.gz
|
||||
specified: sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
|
||||
got: sha256-a1Qvp3FOOkWpL9kFHgugU1ok5UtRPSu+NwCZKbbaEro=
|
||||
```
|
||||
@@ -1,42 +0,0 @@
|
||||
---
|
||||
synopsis: "mTLS store connections via a plugin"
|
||||
issues: []
|
||||
cls: [3754, 3696, 3697, 3698]
|
||||
category: Improvements
|
||||
credits: [raito, horrors, mic92, vlaci]
|
||||
---
|
||||
|
||||
To support use cases requiring mutual TLS (mTLS) authentication when connecting
|
||||
to remote Nix stores, e.g. private stores, we have introduced a **contributed**
|
||||
mTLS plugin extending the Lix store interface.
|
||||
|
||||
This design follows an extensibility model which was brought up [by a proposal
|
||||
of making Kerberos authentication possible in Lix
|
||||
directly](https://gerrit.lix.systems/c/lix/+/3637).
|
||||
|
||||
This mTLS plugin serves as a concrete example of how store connection
|
||||
mechanisms can be modularized through external plugins, without extending Lix
|
||||
core. This idea can be generalized to integrate automatic certificate renewal
|
||||
or advanced integrations with secrets engine or posture checks.
|
||||
|
||||
It enables custom TLS client certificates to be used for authenticating against
|
||||
a remote store that enforces mTLS.
|
||||
|
||||
To use the plugin, configure Lix manually by setting in your `nix.conf`:
|
||||
|
||||
```
|
||||
plugin-files = /a/path/to/libplugin_mtls_store.so
|
||||
```
|
||||
|
||||
Currently, this must be done explicitly. In the future, Nixpkgs will provide a
|
||||
mechanism to reference an up-to-date and curated set of plugins automatically.
|
||||
|
||||
Making plugins easily consumable outside of Nixpkgs (e.g., from external plugin
|
||||
registries or binary distributions) remains an open question and will require
|
||||
further design.
|
||||
|
||||
Contributed plugins come with significantly reduced **stability** and
|
||||
**maintenance** guarantees compared to the Lix core. We encourage users who
|
||||
depend on a given plugin to take on maintenance responsibilities and apply for
|
||||
ownership within the Lix mono-repository. These plugins are subject to removal
|
||||
at any time.
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
synopsis: Add log formats `multiline` and `multiline-with-logs`
|
||||
cls: [1369]
|
||||
credits: [kloenk]
|
||||
category: Improvements
|
||||
---
|
||||
|
||||
Added two new log formats (`multiline` and `multiline-with-logs`) that display
|
||||
current activities below each other for better visibility.
|
||||
|
||||
These formats attempt to use the maximum available lines
|
||||
(defaulting to 25 if unable to determine) and print up to that many lines.
|
||||
The status bar is displayed as the first line, with each subsequent
|
||||
activity on its own line.
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
synopsis: "`nix copy` is now several times faster at `querying info about /nix/store/...`"
|
||||
cls: [1462]
|
||||
issues: [fj#366]
|
||||
credits: [jade]
|
||||
category: Fixes
|
||||
---
|
||||
|
||||
We fixed a locking bug that serialized `querying info about /nix/store/...`
|
||||
onto just one thread such that it was eating `O(paths to copy * latency)` time
|
||||
while setting up to copy paths to s3 and other stores. It is now `nproc` times
|
||||
faster.
|
||||
@@ -0,0 +1,21 @@
|
||||
---
|
||||
synopsis: "Lix no longer speaks the Nix remote-build worker protocol to clients or servers older than CppNix 2.3"
|
||||
cls: [1207, 1208, 1206, 1205, 1204, 1203, 1479]
|
||||
issues: [fj#325]
|
||||
credits: [jade]
|
||||
category: Breaking Changes
|
||||
---
|
||||
|
||||
CppNix 2.3 was released in 2019, and is the new oldest supported version. We
|
||||
will increase our support baseline in the future up to a final version of CppNix
|
||||
2.18 (which may happen soon given that it is the only still-packaged and thus
|
||||
still-tested >2.3 version), but this step already removes a significant amount
|
||||
of dead, untested, code paths.
|
||||
|
||||
Lix speaks the same version of the protocol as CppNix 2.18 and that fact will
|
||||
never change in the future; the Lix plans to replace the protocol for evolution
|
||||
will entail a complete incompatible replacement that will be supported in
|
||||
parallel with the old protocol. Lix will thus retain remote build compatibility
|
||||
with CppNix as long as CppNix maintains protocol compatibility with 2.18, and
|
||||
as long as Lix retains legacy protocol support (which will likely be a long
|
||||
time given that we plan to convert it to a frozen-in-time shim).
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
synopsis: "`nix registry add` now requires a shorthand flakeref on the 'from' side"
|
||||
cls: 1494
|
||||
credits: delan
|
||||
category: Improvements
|
||||
---
|
||||
|
||||
The 'from' argument must now be a shorthand flakeref like `nixpkgs` or `nixpkgs/nixos-20.03`, making it harder to accidentally swap the 'from' and 'to' arguments.
|
||||
|
||||
Registry entries that map from other flake URLs can still be specified in registry.json, the `nix.registry` option in NixOS, or the `--override-flake` option in the CLI, but they are not guaranteed to work correctly.
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
synopsis: Allow automatic rejection of configuration options from flakes
|
||||
cls: [1541]
|
||||
credits: [alois31]
|
||||
category: Improvements
|
||||
---
|
||||
|
||||
Setting `accept-flake-config` to `false` now respects user choice by automatically rejecting configuration options set by flakes.
|
||||
The old behaviour of asking each time is still available (and default) by setting it to the special value `ask`.
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
synopsis: "`nix repl` now allows tab-completing the special repl :colon commands"
|
||||
cls: 1367
|
||||
credits: Qyriad
|
||||
category: Improvements
|
||||
---
|
||||
|
||||
The REPL (`nix repl`) supports pressing `<TAB>` to complete a partial expression, but now also supports completing the special :colon commands as well (`:b`, `:edit`, `:doc`, etc), if the line starts with a colon.
|
||||
@@ -0,0 +1,10 @@
|
||||
---
|
||||
synopsis: "Lix now supports building with UndefinedBehaviorSanitizer"
|
||||
cls: [1483]
|
||||
credits: [jade]
|
||||
category: Development
|
||||
---
|
||||
|
||||
You can now build Lix with the configuration option `-Db_sanitize=undefined` and it will both work and pass tests. AddressSanitizer support is also coming soon.
|
||||
|
||||
For a list of undefined behaviour fixed by sanitizer usage, see [the gerrit topic "undefined-behaviour"](https://gerrit.lix.systems/q/topic:%22undefined-behaviour%22).
|
||||
@@ -20,6 +20,7 @@
|
||||
- [Basic Package Management](package-management/basic-package-mgmt.md)
|
||||
- [Profiles](package-management/profiles.md)
|
||||
- [Garbage Collection](package-management/garbage-collection.md)
|
||||
- [Garbage Collector Roots](package-management/garbage-collector-roots.md)
|
||||
- [Sharing Packages Between Machines](package-management/sharing-packages.md)
|
||||
- [Serving a Nix store via HTTP](package-management/binary-cache-substituter.md)
|
||||
- [Copying Closures via SSH](package-management/copy-closure.md)
|
||||
@@ -39,9 +40,6 @@
|
||||
- [Tuning Cores and Jobs](advanced-topics/cores-vs-jobs.md)
|
||||
- [Verifying Build Reproducibility](advanced-topics/diff-hook.md)
|
||||
- [Using the `post-build-hook`](advanced-topics/post-build-hook.md)
|
||||
- [Pasta](advanced-topics/pasta.md)
|
||||
- [Known Issues](known-issues/known-issues.md)
|
||||
- [Limitations around non-isolated builds](known-issues/non-isolated-build-limits.md)
|
||||
- [Command Reference](command-ref/command-ref.md)
|
||||
- [Common Options](command-ref/opt-common.md)
|
||||
- [Common Environment Variables](command-ref/env-common.md)
|
||||
@@ -194,17 +192,12 @@
|
||||
- [Hacking](contributing/hacking.md)
|
||||
- [Testing](contributing/testing.md)
|
||||
- [Experimental Features](contributing/experimental-features.md)
|
||||
- [Deprecated Features](contributing/deprecated-features.md)
|
||||
- [CLI guideline](contributing/cli-guideline.md)
|
||||
- [C++ style guide](contributing/cxx.md)
|
||||
- [Release Notes](release-notes/release-notes.md)
|
||||
- [Upcoming release](release-notes/rl-next.md)
|
||||
<!-- RELENG-AUTO-INSERTION-MARKER (see releng/release_notes.py) -->
|
||||
- [Lix 2.94 (2025-11-17)](release-notes/rl-2.94.md)
|
||||
- [Lix 2.93 (2025-05-09)](release-notes/rl-2.93.md)
|
||||
- [Lix 2.92 (2025-01-18)](release-notes/rl-2.92.md)
|
||||
- [Lix 2.91 (2024-08-12)](release-notes/rl-2.91.md)
|
||||
- [Lix 2.90 (2024-07-10)](release-notes/rl-2.90.md)
|
||||
<!-- RELENG-AUTO-INSERTION-MARKER (see releng/release_notes.py) -->
|
||||
- [Lix 2.90 (FIXME date)](release-notes/rl-2.90.md)
|
||||
- [Nix 2.18 (2023-09-20)](release-notes/rl-2.18.md)
|
||||
- [Nix 2.17 (2023-07-24)](release-notes/rl-2.17.md)
|
||||
- [Nix 2.16 (2023-05-31)](release-notes/rl-2.16.md)
|
||||
|
||||
@@ -75,9 +75,7 @@ by spaces. Only the first element is required. To leave a field at its
|
||||
default, set it to `-`.
|
||||
|
||||
1. The URI of the remote store in the format
|
||||
`ssh://[username@]hostname[?port=<port>]`, e.g. `ssh://nix@mac` or `ssh://mac`.
|
||||
If the ssh server is not listening on port 22 (e.g. port 1337 in this case)
|
||||
the URI would be `ssh://nix@mac?port=1337`
|
||||
`ssh://[username@]hostname`, e.g. `ssh://nix@mac` or `ssh://mac`.
|
||||
For backward compatibility, `ssh://` may be omitted. The hostname
|
||||
may be an alias defined in your `~/.ssh/config`.
|
||||
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
# [Pasta](https://passt.top/passt/about/): a network sandbox for fixed-output derivations
|
||||
|
||||
## Introduction
|
||||
|
||||
This section only applies to **Linux systems** as Pasta is a Linux-only measure.
|
||||
|
||||
Since [CVE-2025-46416](https://lix.systems/blog/2025-06-24-lix-cves/), the Lix project decided to adopt [Pasta](https://passt.top/passt/about/) for all fixed-output derivations, protecting against various attack vectors such as UNIX abstract domain sockets or more manipulation at the network layer from a malicious fixed-output derivation code.
|
||||
|
||||
Pasta acts as a translation layer between a layer-2 network interface and layer-4 sockets (TCP, UDP, ICMP/ICMPv6 echo) on the host. It requires no special privileges and can serve as a alternative to [SLiRP](https://en.wikipedia.org/wiki/Slirp) which was used [by Guix to mitigate the same problem](https://codeberg.org/guix/guix/commit/fb42611b8f27960304db5a1c0d33b8371dcde2a8).
|
||||
|
||||
## How to disable Pasta?
|
||||
|
||||
It's sufficient to pass `pasta-path = ""` in your `/etc/nix/nix.conf` or on the command line `--pasta-path ""` of a Lix invocation.
|
||||
|
||||
## Known issues surrounding Pasta
|
||||
|
||||
- Only the first DNS server in `/etc/resolv.conf` is considered: failover is not possible.
|
||||
- [Reduced feature set compared to the Linux kernel](https://passt.top/passt/about/#features)
|
||||
- [Performance overhead in multi-gigabits contexts and IMIX MTUs](https://passt.top/passt/about/#performance_1)
|
||||
@@ -22,9 +22,9 @@ The following [concept map] shows its main components (rectangles), the objects
|
||||
| |
|
||||
+----------|-------------------|--------------------------------+
|
||||
| Nix impl.| V |
|
||||
| (Lix) | +------------------------+ |
|
||||
| | | command line interface |------. |
|
||||
| | +------------------------+ | |
|
||||
| (Lix) | +-------------------------+ |
|
||||
| | | commmand line interface |------. |
|
||||
| | +-------------------------+ | |
|
||||
| | | | |
|
||||
| evaluated by calls manages |
|
||||
| | | | |
|
||||
|
||||
@@ -34,15 +34,9 @@ keep-outputs = true # Nice for developers
|
||||
keep-derivations = true # Idem
|
||||
```
|
||||
|
||||
Other files can be included with a line like `include <path>`.
|
||||
Other files can be included with a line like `include <path>`, where `<path>` is interpreted relative to the current configuration file.
|
||||
A missing file is an error unless `!include` is used instead.
|
||||
|
||||
Paths in `include`s and option values are interpreted relative to the current configuration file.
|
||||
In user configuration files, paths starting with `~/` are tilde expanded (by replacing the tilde by the value of `$HOME`).
|
||||
|
||||
Only user configuration files (like `$XDG_CONFIG_HOME/nix/nix.conf` or the files listed in `$NIX_USER_CONF_FILES`) can use tilde paths relative to your home directory.
|
||||
Configuration listed in the `$NIX_CONFIG` environment variable may not use relative paths.
|
||||
|
||||
A configuration setting usually overrides any previous value.
|
||||
However, for settings that take a list of items, you can prefix the name of the setting by `extra-` to *append* to the previous value.
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
<!--
|
||||
File-ish argument syntax summary.
|
||||
This file gets included into pages like nix-build.md and nix-instantiate.md, and each individual page that includes
|
||||
this also links to nix-build.md for the full explanation.
|
||||
-->
|
||||
- A normal filesystem path, like `/home/meow/nixfiles/default.nix`
|
||||
- Or a directory, like `/home/meow/nixfiles`, equivalent to above
|
||||
- A single lookup path, like `<nixpkgs>` or `<nixos>`
|
||||
- A URL to a tarball, like `https://github.com/NixOS/nixpkgs/archive/refs/heads/release-23.11.tar.gz`
|
||||
- A [flakeref](@docroot@/command-ref/new-cli/nix3-flake.md#flake-references), introduced by the prefix `flake:`, like `flake:git+https://git.lix.systems/lix-project/lix`
|
||||
- A *nixpkgs* channel tarball name, introduced by the prefix `channel:`, like `channel:nixos-unstable`.
|
||||
- This uses a hard-coded URL pattern and is *not* related to the subscribed channels managed by the [nix-channel](@docroot@/command-ref/nix-channel.md) command.
|
||||
@@ -1,3 +1,23 @@
|
||||
xp_features_json = custom_target(
|
||||
command : [nix, '__dump-xp-features'],
|
||||
capture : true,
|
||||
output : 'xp-features.json',
|
||||
)
|
||||
|
||||
experimental_features_shortlist_md = custom_target(
|
||||
command : nix_eval_for_docs + [
|
||||
'--expr',
|
||||
'import @INPUT0@ (builtins.fromJSON (builtins.readFile @INPUT1@))',
|
||||
],
|
||||
input : [
|
||||
'../../generate-xp-features-shortlist.nix',
|
||||
xp_features_json,
|
||||
],
|
||||
capture : true,
|
||||
output : 'experimental-features-shortlist.md',
|
||||
env : nix_env_for_docs,
|
||||
)
|
||||
|
||||
# Intermediate step for manpage generation.
|
||||
# This splorks the output of generate-manpage.nix as JSON,
|
||||
# which gets written as a directory tree below.
|
||||
@@ -31,23 +51,16 @@ nix3_cli_files = custom_target(
|
||||
|
||||
conf_file_md = custom_target(
|
||||
command : [
|
||||
python.full_path(),
|
||||
'@SOURCE_ROOT@/lix/code-generation/build_settings.py',
|
||||
'--kernel', host_machine.system(),
|
||||
'--docs', '@OUTPUT@',
|
||||
'--experimental-features', '@SOURCE_ROOT@/lix/libutil/experimental-features',
|
||||
'@INPUT@',
|
||||
nix_eval_for_docs,
|
||||
'--expr',
|
||||
'(import @INPUT0@).showSettings { inlineHTML = true; } (builtins.fromJSON (builtins.readFile @INPUT1@))',
|
||||
],
|
||||
capture : true,
|
||||
input : [
|
||||
libexpr_setting_definitions,
|
||||
libfetchers_setting_definitions,
|
||||
file_transfer_setting_definitions,
|
||||
libstore_setting_definitions,
|
||||
archive_setting_definitions,
|
||||
feature_setting_definitions,
|
||||
logging_setting_definitions,
|
||||
daemon_setting_definitions,
|
||||
develop_settings_definitions,
|
||||
'../../utils.nix',
|
||||
conf_file_json,
|
||||
experimental_features_shortlist_md,
|
||||
],
|
||||
output : 'conf-file.md',
|
||||
env : nix_env_for_docs,
|
||||
)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
# Synopsis
|
||||
|
||||
`nix-build` [*fileish…*]
|
||||
`nix-build` [*paths…*]
|
||||
[`--arg` *name* *value*]
|
||||
[`--argstr` *name* *value*]
|
||||
[{`--attr` | `-A`} *attrPath*]
|
||||
@@ -20,55 +20,19 @@ For documentation on the latter, run `nix build --help` or see `man nix3-build`.
|
||||
# Description
|
||||
|
||||
The `nix-build` command builds the derivations described by the Nix
|
||||
expressions in each *fileish*. If the build succeeds, it places a symlink to
|
||||
expressions in *paths*. If the build succeeds, it places a symlink to
|
||||
the result in the current directory. The symlink is called `result`. If
|
||||
there are multiple Nix expressions, or the Nix expressions evaluate to
|
||||
multiple derivations, multiple sequentially numbered symlinks are
|
||||
created (`result`, `result-2`, and so on).
|
||||
|
||||
If no *fileish* is specified, then `nix-build` will use `default.nix` in
|
||||
If no *paths* are specified, then `nix-build` will use `default.nix` in
|
||||
the current directory, if it exists.
|
||||
|
||||
## Fileish Syntax
|
||||
|
||||
A given *fileish* may take one of a few different forms, the first being a simple filesystem path, e.g. `nix-build /tmp/some-file.nix`.
|
||||
Like the [import builtin](../language/builtins.md#builtins-import) specifying a directory is equivalent to specifying `default.nix` within that directory.
|
||||
It may also be a [search path](./env-common.md#env-NIX_PATH) (also known as a lookup path) like `<nixpkgs>`, which is convenient to use with `--attr`/`-A`:
|
||||
|
||||
```console
|
||||
$ nix-build '<nixpkgs>' -A firefox
|
||||
```
|
||||
|
||||
(Note the quotation marks around `<nixpkgs>`, which will be necessary in most Unix shells.)
|
||||
|
||||
If a *fileish* starts with `http://` or `https://`, it is interpreted as the URL of a tarball which will be fetched and unpacked.
|
||||
Lix will then `import` the unpacked directory, so these tarballs must include at least a single top-level directory with a file called `default.nix`
|
||||
For example, you could build from a specific version of Nixpkgs with something like:
|
||||
|
||||
```console
|
||||
$ nix-build "https://github.com/NixOS/nixpkgs/archive/refs/heads/release-23.11.tar.gz" -A firefox
|
||||
```
|
||||
|
||||
If a path starts with `flake:`, the rest of the argument is interpreted as a [flakeref](./new-cli/nix3-flake.md#flake-references) (see `nix flake --help` or `man nix3-flake`), which requires the "flakes" experimental feature to be enabled.
|
||||
Lix will fetch the flake, and then `import` its unpacked directory, so the flake must include a file called `default.nix`.
|
||||
For example, the flake analogues to the above `nix-build` commands are:
|
||||
|
||||
```console
|
||||
$ nix-build flake:nixpkgs -A firefox
|
||||
$ nix-build flake:github:NixOS/nixpkgs/release-23.11 -A firefox
|
||||
```
|
||||
|
||||
Finally, for legacy reasons, if a path starts with `channel:`, the rest of the argument is interpreted as the name of a *nixpkgs* channel tarball to fetch from `https://channels.nixos.org/$CHANNEL_NAME/nixexprs.tar.xz`.
|
||||
This is a **hard coded URL** pattern and is *not* related to the subscribed channels managed by the [nix-channel](./nix-channel.md) command.
|
||||
|
||||
> **Note**: any of the special syntaxes may always be disambiguated by prefixing the path.
|
||||
> For example: a file in the current directory literally called `<nixpkgs>` can be addressed as `./<nixpkgs>`, to escape the special interpretation.
|
||||
|
||||
In summary, a path argument may be one of:
|
||||
|
||||
{{#include ./fileish-summary.md}}
|
||||
|
||||
## Notes
|
||||
If an element of *paths* starts with `http://` or `https://`, it is
|
||||
interpreted as the URL of a tarball that will be downloaded and unpacked
|
||||
to a temporary location. The tarball must include a single top-level
|
||||
directory containing at least a file named `default.nix`.
|
||||
|
||||
`nix-build` is essentially a wrapper around
|
||||
[`nix-instantiate`](nix-instantiate.md) (to translate a high-level Nix
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
Channels are a mechanism for referencing remote Nix expressions and conveniently retrieving their latest version.
|
||||
|
||||
The moving parts of channels are:
|
||||
- The official channels listed at <https://channels.nixos.org>
|
||||
- The official channels listed at <https://nixos.org/channels>
|
||||
- The user-specific list of [subscribed channels](#subscribed-channels)
|
||||
- The [downloaded channel contents](#channels)
|
||||
- The [Nix expression search path](@docroot@/command-ref/conf-file.md#conf-nix-path), set with the [`-I` option](#opt-I) or the [`NIX_PATH` environment variable](#env-NIX_PATH)
|
||||
- The [Nix expression search path](@docroot@/command-ref/conf-file.md#conf-nix-path), set with the [`-I` option](#opt-i) or the [`NIX_PATH` environment variable](#env-NIX_PATH)
|
||||
|
||||
> **Note**
|
||||
>
|
||||
@@ -77,9 +77,9 @@ This command has the following operations:
|
||||
Subscribe to the Nixpkgs channel and run `hello` from the GNU Hello package:
|
||||
|
||||
```console
|
||||
$ nix-channel --add https://channels.nixos.org/nixpkgs-unstable
|
||||
$ nix-channel --add https://nixos.org/channels/nixpkgs-unstable
|
||||
$ nix-channel --list
|
||||
nixpkgs https://channels.nixos.org/nixpkgs
|
||||
nixpkgs https://nixos.org/channels/nixpkgs
|
||||
$ nix-channel --update
|
||||
$ nix-shell -p hello --run hello
|
||||
hello
|
||||
|
||||
@@ -36,7 +36,7 @@ Instead, it looks in a few locations, and acts on all profiles it finds there:
|
||||
>
|
||||
> Not stable; subject to change
|
||||
>
|
||||
> Do not rely on this functionality; it just exists for migration purposes and may change in the future.
|
||||
> Do not rely on this functionality; it just exists for migration purposes and is may change in the future.
|
||||
> These deprecated paths remain a private implementation detail of Lix.
|
||||
|
||||
<!-- FIXME(Qyriad): this is inconsistent with https://git.lix.systems/lix-project/lix/issues/215, needs updating when that happens -->
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
[`--option` *name* *value*]
|
||||
[`--arg` *name* *value*]
|
||||
[`--argstr` *name* *value*]
|
||||
[{`--file` | `-f`} *fileish*]
|
||||
[{`--file` | `-f`} *path*]
|
||||
[{`--profile` | `-p`} *path*]
|
||||
[`--system-filter` *system*]
|
||||
[`--dry-run`]
|
||||
|
||||
@@ -26,7 +26,7 @@ This operation deletes the specified generations of the current profile.
|
||||
>
|
||||
> Older *and newer* generations will be deleted by this operation.
|
||||
>
|
||||
> One might expect this to just delete older generations than the current one, but that is only true if the current generation is also the latest.
|
||||
> One might expect this to just delete older generations than the curent one, but that is only true if the current generation is also the latest.
|
||||
> Because one can roll back to a previous generation, it is possible to have generations newer than the current one.
|
||||
> They will also be deleted.
|
||||
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
[`--from-profile` *path*]
|
||||
[`--preserve-installed` | `-P`]
|
||||
[`--remove-all` | `-r`]
|
||||
[`--priority` *priority*]
|
||||
|
||||
# Description
|
||||
|
||||
@@ -60,11 +59,6 @@ a number of possible ways:
|
||||
unambiguous way, which is necessary if there are multiple
|
||||
derivations with the same name.
|
||||
|
||||
- If `--priority` *priority* is given, the priority of the derivations being
|
||||
installed is set to *priority*. This can be used to override the priority of
|
||||
the derivations being installed. This is useful if *args* are store paths,
|
||||
which don't have any priority information.
|
||||
|
||||
- If *args* are [store derivations](@docroot@/glossary.md#gloss-store-derivation), then these are
|
||||
[realised](@docroot@/command-ref/nix-store/realise.md), and the resulting output paths
|
||||
are installed.
|
||||
@@ -148,8 +142,8 @@ To copy the store path with symbolic name `gcc` from another profile:
|
||||
$ nix-env --install --from-profile /nix/var/nix/profiles/foo gcc
|
||||
```
|
||||
|
||||
To install a specific [store derivation](@docroot@/glossary.md#gloss-store-derivation)
|
||||
(typically created by `nix-instantiate`):
|
||||
To install a specific [store derivation] (typically created by
|
||||
`nix-instantiate`):
|
||||
|
||||
```console
|
||||
$ nix-env --install /nix/store/fibjb1bfbpm5mrsxc4mh2d8n37sxh91i-gcc-3.4.3.drv
|
||||
|
||||
@@ -2,16 +2,16 @@
|
||||
|
||||
The following options are allowed for all `nix-env` operations, but may not always have an effect.
|
||||
|
||||
- `--file` / `-f` *fileish*\
|
||||
- `--file` / `-f` *path*\
|
||||
Specifies the Nix expression (designated below as the *active Nix
|
||||
expression*) used by the `--install`, `--upgrade`, and `--query
|
||||
--available` operations to obtain derivations. The default is
|
||||
`~/.nix-defexpr`.
|
||||
|
||||
*fileish* is interpreted the same as with [nix-build](../nix-build.md#fileish-syntax).
|
||||
See that section for complete details (`nix-build --help`), but in summary, a path argument may be one of:
|
||||
|
||||
{{#include ../fileish-summary.md}}
|
||||
If the argument starts with `http://` or `https://`, it is
|
||||
interpreted as the URL of a tarball that will be downloaded and
|
||||
unpacked to a temporary location. The tarball must include a single
|
||||
top-level directory containing at least a file named `default.nix`.
|
||||
|
||||
- `--profile` / `-p` *path*\
|
||||
Specifies the profile to be used by those operations that operate on
|
||||
|
||||
@@ -22,7 +22,7 @@ left untouched; this is not an error. It is also not an error if an
|
||||
element of *args* matches no installed derivations.
|
||||
|
||||
For a description of how *args* is mapped to a set of store paths, see
|
||||
[`--install`](install.md). If *args* describes multiple
|
||||
[`--install`](#operation---install). If *args* describes multiple
|
||||
store paths with the same symbolic name, only the one with the highest
|
||||
version is installed.
|
||||
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
# Synopsis
|
||||
|
||||
`nix-instantiate`
|
||||
[`--parse` | `--eval` [`--strict`] [`--raw`] [`--json`] [`--xml`] ]
|
||||
[`--parse` | `--eval` [`--strict`] [`--json`] [`--xml`] ]
|
||||
[`--read-write-mode`]
|
||||
[`--arg` *name* *value*]
|
||||
[{`--attr`| `-A`} *attrPath*]
|
||||
[`--add-root` *path*]
|
||||
[`--expr` | `-E`]
|
||||
*fileish…*
|
||||
*files…*
|
||||
|
||||
`nix-instantiate` `--find-file` *files…*
|
||||
|
||||
@@ -25,11 +25,8 @@ of the resulting store derivations are printed on standard output.
|
||||
|
||||
[store derivation]: ../glossary.md#gloss-store-derivation
|
||||
|
||||
If *fileish* is the character `-`, then a Nix expression will be read from standard input.
|
||||
Otherwise, each *fileish* is interpreted the same as with [nix-build](./nix-build.md#fileish-syntax).
|
||||
See that section for complete details (`nix-build --help`), but in summary, a path argument may be one of:
|
||||
|
||||
{{#include ./fileish-summary.md}}
|
||||
If *files* is the character `-`, then a Nix expression will be read from
|
||||
standard input.
|
||||
|
||||
# Options
|
||||
|
||||
@@ -38,14 +35,7 @@ See that section for complete details (`nix-build --help`), but in summary, a pa
|
||||
|
||||
- `--parse`\
|
||||
Just parse the input files, and print their abstract syntax trees on
|
||||
standard output. The output format of the AST depends on the current
|
||||
internal representation and may change in the future.
|
||||
|
||||
Tooling can use the stderr and exit code of `--parse` to check any
|
||||
Nix code for correctness, but should not rely on stdout without careful
|
||||
versioning. Note that `--parse` also checks for unbound variables.
|
||||
In cases where this is undesired, `with {};` can be prepended
|
||||
to the program to transform all such parse errors into eval errors.
|
||||
standard output as a Nix expression.
|
||||
|
||||
- `--eval`\
|
||||
Just parse and evaluate the input files, and print the resulting
|
||||
@@ -107,27 +97,15 @@ See that section for complete details (`nix-build --help`), but in summary, a pa
|
||||
> This option can cause non-termination, because lazy data
|
||||
> structures can be infinitely large.
|
||||
|
||||
- `--raw`\
|
||||
When used with `--eval`, the result must be coercible to a string, i.e.,
|
||||
something that can be converted using `${...}`.
|
||||
|
||||
Integers will always generate an error when output via `--raw`, regardless of
|
||||
[`coerce-integers`](../contributing/experimental-features.md#xp-feature-coerce-integers) being enabled, to avoid ambiguity.
|
||||
|
||||
The output is printed exactly as-is, with no quotes, escaping, or trailing
|
||||
newline.
|
||||
|
||||
- `--json`\
|
||||
When used with `--eval`, print the resulting value as an JSON
|
||||
representation of the resulting value rather than as a Nix expression.
|
||||
|
||||
The conversion behaviour, if `--strict` is passed, is the same as
|
||||
[`builtins.toJSON`](../language/builtins.md#builtins-toJSON).
|
||||
representation of the abstract syntax tree rather than as a Nix expression.
|
||||
|
||||
- `--xml`\
|
||||
When used with `--eval`, print the resulting value as an XML
|
||||
representation of the resulting value rather than as a Nix expression.
|
||||
The schema is the same as that used by [`builtins.toXML`](../language/builtins.md#builtins-toXML).
|
||||
representation of the abstract syntax tree rather than as a Nix expression.
|
||||
The schema is the same as that used by the [`toXML`
|
||||
built-in](../language/builtins.md).
|
||||
|
||||
- `--read-write-mode`\
|
||||
When used with `--eval`, perform evaluation in read/write mode so
|
||||
|
||||
@@ -33,9 +33,10 @@ the environment of a derivation for development.
|
||||
If *path* is not given, `nix-shell` defaults to `shell.nix` if it
|
||||
exists, and `default.nix` otherwise.
|
||||
|
||||
If *path* is given it is interpreted like a [*fileish* argument to nix-build](./nix-build.md#fileish-syntax):
|
||||
|
||||
{{#include ./fileish-summary.md}}
|
||||
If *path* starts with `http://` or `https://`, it is interpreted as the
|
||||
URL of a tarball that will be downloaded and unpacked to a temporary
|
||||
location. The tarball must include a single top-level directory
|
||||
containing at least a file named `default.nix`.
|
||||
|
||||
If the derivation defines the variable `shellHook`, it will be run
|
||||
after `$stdenv/setup` has been sourced. Since this hook is not executed
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
# Synopsis
|
||||
|
||||
`nix-store` `--delete` [`--ignore-liveness`] [`--skip-live`] [`--delete-closure`] *paths…*
|
||||
`nix-store` `--delete` [`--ignore-liveness`] *paths…*
|
||||
|
||||
# Description
|
||||
|
||||
@@ -18,13 +18,6 @@ With the option `--ignore-liveness`, reachability from the roots is
|
||||
ignored. However, the path still won’t be deleted if there are other
|
||||
paths in the store that refer to it (i.e., depend on it).
|
||||
|
||||
This operation will raise an error if any of the paths are still live
|
||||
and `--ignore-liveness` is not passed. Passing `--skip-live` will
|
||||
prevent this from being considered an error.
|
||||
|
||||
The option `--delete-closure` will also attempt to delete any paths
|
||||
that are in the given path's dependency closure.
|
||||
|
||||
{{#include ./opt-common.md}}
|
||||
|
||||
{{#include ../opt-common.md}}
|
||||
|
||||
@@ -93,12 +93,9 @@ symlink.
|
||||
[deriver]: ../../glossary.md#gloss-deriver
|
||||
|
||||
- `--valid-derivers`\
|
||||
Prints the set of all [derivers](../../glossary.md#gloss-deriver) that can be
|
||||
used to build the store paths *paths*.
|
||||
This differs from `--deriver`, which prints the deriver that actually
|
||||
produced *paths*.
|
||||
No deriver may be returned if is not present in the store,
|
||||
eg, if *paths* were substituted from a binary cache.
|
||||
Prints a set of derivation files (`.drv`) which are supposed produce
|
||||
said paths when realized. Might print nothing, for example for source paths
|
||||
or paths subsituted from a binary cache.
|
||||
|
||||
- `--graph`\
|
||||
Prints the references graph of the store paths *paths* in the format
|
||||
|
||||
@@ -15,6 +15,7 @@ Each of *paths* is processed as follows:
|
||||
1. If it is not [valid], substitute the store derivation file itself.
|
||||
2. Realise its [output paths]:
|
||||
- Try to fetch from [substituters] the [store objects] associated with the output paths in the store derivation's [closure].
|
||||
- With [content-addressed derivations] (experimental): Determine the output paths to realise by querying content-addressed realisation entries in the [Nix database].
|
||||
- For any store paths that cannot be substituted, produce the required store objects. This involves first realising all outputs of the derivation's dependencies and then running the derivation's [`builder`](@docroot@/language/derivations.md#attr-builder) executable. <!-- TODO: Link to build process page #8888 -->
|
||||
- Otherwise, and if the path is not already valid: Try to fetch the associated [store objects] in the path's [closure] from [substituters].
|
||||
|
||||
@@ -27,6 +28,7 @@ If no substitutes are available and no store derivation is given, realisation fa
|
||||
[store objects]: @docroot@/glossary.md#gloss-store-object
|
||||
[closure]: @docroot@/glossary.md#gloss-closure
|
||||
[substituters]: @docroot@/command-ref/conf-file.md#conf-substituters
|
||||
[content-addressed derivations]: @docroot@/contributing/experimental-features.md#xp-feature-ca-derivations
|
||||
[Nix database]: @docroot@/glossary.md#gloss-nix-database
|
||||
|
||||
The resulting paths are printed on standard output.
|
||||
|
||||
@@ -85,7 +85,7 @@ Most commands in Lix accept the following command-line options:
|
||||
|
||||
- `multiline-with-logs`
|
||||
|
||||
Display the raw logs, with a progress bar and activities each in a new line at the bottom.
|
||||
Displayes the raw logs, with a progress bar and activities each in a new line at the bottom.
|
||||
|
||||
|
||||
- <span id="opt-no-build-output">[`--no-build-output`](#opt-no-build-output)</span> / `-Q`
|
||||
|
||||
@@ -661,8 +661,8 @@ Verbosity levels are:
|
||||
|
||||
The default level that the command starts is `ERROR`. The simplest way to
|
||||
increase the verbosity by stacking `-v` option (eg: `-vvv == level 3 == INFO`).
|
||||
Use `--quiet` to decrease verbosity by one level.
|
||||
There is one shortcut, `--debug` to run in `DEBUG` verbosity level.
|
||||
There are also two shortcuts, `--debug` to run in `DEBUG` verbosity level and
|
||||
`--quiet` to run in `ERROR` verbosity level.
|
||||
|
||||
----------
|
||||
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
This section describes the notion of *deprecated features*, and how it fits into the big picture of the development of Lix.
|
||||
|
||||
# What are deprecated features?
|
||||
|
||||
Deprecated features are disabled by default, with the intent to eventually remove them.
|
||||
Users must explicitly enable them to keep using them, by toggling the associated [deprecated feature flags](@docroot@/command-ref/conf-file.md#conf-deprecated-features).
|
||||
This allows backwards compatibility and a graceful transition away from undesired features.
|
||||
|
||||
# Which features can be deprecated?
|
||||
|
||||
Undesired features should be soft-deprecated by yielding a warning when used for a significant amount of time before the can be deprecated.
|
||||
Legacy obsolete feature with little to no usage may go through this process faster.
|
||||
Deprecated features should have a migration path to a preferred alternative.
|
||||
|
||||
# Lifecycle of a deprecated feature
|
||||
|
||||
This description is not normative, but a feature removal may roughly happen like this:
|
||||
|
||||
1. Add a warning when the feature is being used.
|
||||
2. Disable the feature by default, putting it behind a deprecated feature flag.
|
||||
- If disabling the feature started out as an opt-in experimental feature, turn that experimental flag into a no-op or remove it entirely.
|
||||
For example, `--extra-experimental-features=no-url-literals` becomes `--extra-deprecated-features=url-literals`.
|
||||
3. Decide on a time frame for how long that feature will still be supported for backwards compatibility, and clearly communicate that in the error messages.
|
||||
- Sometimes, automatic migration to alternatives is possible, and such should be provided if possible
|
||||
- At least one NixOS release cycle should be the minimum
|
||||
4. Finally remove the feature entirely, only keeping the error message for those still using it.
|
||||
|
||||
# Relation to language versioning
|
||||
|
||||
Obviously, removing anything breaks backwards compatibility.
|
||||
In an ideal world, we'd have SemVer controls over the language and its features, cleanly allowing us to make breaking changes.
|
||||
See https://wiki.lix.systems/books/lix-contributors/page/language-versioning and [RFC 137](https://github.com/nixos/rfcs/pull/137) for efforts on that.
|
||||
However, we do not live in such an ideal world, and currently this goal is so far away, that "just disable it with some back-compat for a couple of years" is the most realistic solution, especially for comparatively minor changes.
|
||||
|
||||
# Currently available deprecated features
|
||||
|
||||
{{#include @generated@/../../../lix/libutil/deprecated-feature-descriptions.md}}
|
||||
@@ -99,4 +99,4 @@ This means that experimental features and RFCs are orthogonal mechanisms, and ca
|
||||
|
||||
# Currently available experimental features
|
||||
|
||||
{{#include @generated@/../../../lix/libutil/experimental-feature-descriptions.md}}
|
||||
{{#include @generated@/contributing/experimental-feature-descriptions.md}}
|
||||
|
||||
@@ -11,19 +11,7 @@ The following instructions assume you already have some version of Nix or Lix in
|
||||
|
||||
[installation instructions]: ../installation/installation.md
|
||||
|
||||
A typical development flow for simple changes in Lix looks like:
|
||||
- [Set up and build Lix](#building)
|
||||
- For large changes, check in regarding design and possibly create an RFD issue on Forgejo
|
||||
- Make the changes in your editor
|
||||
- [Send the changes to Gerrit](#sending-to-gerrit)
|
||||
- Once you have the number for the CL from Gerrit to put in the changelog, [write a changelog entry](#release-notes) and amend it into the commit
|
||||
- Update the Gerrit change by submitting it with the same command as the first time
|
||||
- Request and receive a code review
|
||||
- Address feedback from the review
|
||||
- Amend commits, send to Gerrit again
|
||||
- Submit the approved change
|
||||
|
||||
## Building Lix in a development shell {#building}
|
||||
## Building Lix in a development shell
|
||||
|
||||
### Setting up the development shell
|
||||
|
||||
@@ -51,28 +39,17 @@ $ nix-shell -A native-clangStdenvPackages
|
||||
|
||||
### Building from the development shell
|
||||
|
||||
Run a clean build and test with `just clean setup build install test`.
|
||||
|
||||
You can also run the unit tests and integration tests separately:
|
||||
You can build and test Lix with just:
|
||||
|
||||
```bash
|
||||
$ just setup build test-unit
|
||||
$ just install test-integration
|
||||
$ just setup
|
||||
$ just build
|
||||
$ just test --suite=check
|
||||
$ just install
|
||||
$ just test --suite=installcheck
|
||||
```
|
||||
|
||||
Many justfile aliases have a `-custom` variant which pass extra arguments to `meson`.
|
||||
For example, to work on both Lix and nix-eval-jobs you can run:
|
||||
|
||||
```
|
||||
$ just setup-custom -Dnix-eval-jobs=enabled
|
||||
$ # or
|
||||
$ mesonFlags=-Dnix-eval-jobs=enabled just setup
|
||||
```
|
||||
|
||||
Note that only targets which don't accept extra arguments can be used when
|
||||
running multiple targets at once; `just setup build` is fine, but `just
|
||||
setup-custom build` is an error. The `test` target is usually the last one to
|
||||
run, so it always accepts extra arguments.
|
||||
(Check and installcheck may both be done after install, allowing you to omit the --suite argument entirely, but this is the order package.nix runs them in.)
|
||||
|
||||
You can also build Lix manually:
|
||||
|
||||
@@ -125,14 +102,14 @@ $ meson compile -C build nixexpr
|
||||
All targets may be addressed as their output, relative to the build directory, e.g.:
|
||||
|
||||
```bash
|
||||
$ meson compile -C build lix/libexpr/liblixexpr.so
|
||||
$ meson compile -C build src/libexpr/liblixexpr.so
|
||||
```
|
||||
|
||||
But Meson does not consider intermediate files like object files targets.
|
||||
To build a specific object file, use Ninja directly and specify the output file relative to the build directory:
|
||||
|
||||
```bash
|
||||
$ ninja -C build lix/libexpr/liblixexpr.so.p/nixexpr.cc.o
|
||||
$ ninja -C build src/libexpr/liblixexpr.so.p/nixexpr.cc.o
|
||||
```
|
||||
|
||||
To inspect the canonical source of truth on what the state of the buildsystem configuration is, use:
|
||||
@@ -141,44 +118,7 @@ To inspect the canonical source of truth on what the state of the buildsystem co
|
||||
$ meson introspect
|
||||
```
|
||||
|
||||
## Sending changes to Gerrit for review {#sending-to-gerrit}
|
||||
|
||||
We use Gerrit for all our code review in Lix.
|
||||
Our instance is at <https://gerrit.lix.systems>.
|
||||
|
||||
There's much more information about how to use Gerrit in the [wiki section on Gerrit][wiki-gerrit] including how to use Jujutsu, how to use the UI and more.
|
||||
The Snix project also has some Gerrit information [in their contributing docs][snix-gerrit].
|
||||
|
||||
[wiki-gerrit]: https://wiki.lix.systems/books/lix-contributors/chapter/gerrit
|
||||
[snix-gerrit]: https://snix.dev/docs/guides/contributing/
|
||||
|
||||
The gist is that once you have your SSH key and git remote set up, you can send commits for review with:
|
||||
|
||||
```
|
||||
$ git remote set-url origin ssh://YOURUSERNAME@gerrit.lix.systems:2022/lix
|
||||
$ git push origin HEAD:refs/for/main
|
||||
```
|
||||
|
||||
Then, you can request a review via the "Reply" button on the web UI.
|
||||
If you click "Suggest Owners", it will try to suggest the maintainers of the area of the code change to send review requests to.
|
||||
Requesting reviews from multiple people is normal.
|
||||
|
||||
We do our best to respond to directly sent reviews in a few days, so feel free to request another reviewer or ask on Matrix if you've not got a response for a while.
|
||||
Keep in mind that Lix is a volunteer project and we have limited bandwidth, so some changes aren't feasible to shepherd through; please check in on Matrix at design time when doing large changes.
|
||||
|
||||
Once you get a `Code-Review+2` vote on your change, it's rebased on `main` and CI marks it `Verified+1`, you're able (and usually expected, so you can have a second chance to check it over) to hit the Submit button to merge it.
|
||||
If the change appears as "Rebase Required", you need to rebase it on `main` locally or via the Gerrit UI and wait for `Verified+1` before the Submit button is made active
|
||||
The `Code-Review+2` from before will stick around through trivial rebases so no need to re-request review for a mere rebase.
|
||||
|
||||
## Interacting with the CI, Buildkite
|
||||
|
||||
We use Buildkite for our CI, usually you will not have to interact directly with it other than reviewing any errors it produces, which are linked from Gerrit.
|
||||
|
||||
However in certain cases a CI run will fail due to transient issues not related to your code and you will need to rerun it by hand.
|
||||
You can log in to the CI via [SSO](https://buildkite.com/sso/lix-project). On your job you can then hit the "Retry failed" button to rerun it, normally you will not have a repeat of the transient issue.
|
||||
If the build still fails on CI issues or all builds are failing this should be reported via [Zulip on #T-infra](https://zulip.lix.systems/#narrow/channel/7-T-infra) or [Matrix on #dev](https://matrix.to/#/%23dev%3Alix.systems?via=lix.systems).
|
||||
|
||||
## Building Lix with `nix`
|
||||
## Building Lix outside of development shells
|
||||
|
||||
To build a release version of Lix for the current operating system and CPU architecture:
|
||||
|
||||
@@ -201,7 +141,6 @@ Lix can be built for various platforms, as specified in [`flake.nix`]:
|
||||
|
||||
- `x86_64-linux`
|
||||
- `x86_64-darwin`
|
||||
- `x86_64-freebsd`
|
||||
- `i686-linux`
|
||||
- `aarch64-linux`
|
||||
- `aarch64-darwin`
|
||||
@@ -236,7 +175,6 @@ These are specified in `crossSystems` in `flake.nix`; feel free to submit change
|
||||
|
||||
- `armv6l-linux`
|
||||
- `armv7l-linux`
|
||||
- `aarch64-linux`
|
||||
- `riscv64-linux`
|
||||
|
||||
For example, to cross-compile Lix for `armv6l-linux` from another Linux, use the following:
|
||||
@@ -278,7 +216,7 @@ Lix uses a string with the following format to identify the *system type* or *pl
|
||||
|
||||
It is set when Lix is compiled for the given system, and determined by [Meson's `host_machine.cpu_family()` and `host_machine.system()` values](https://mesonbuild.com/Reference-manual_builtin_host_machine.html).
|
||||
|
||||
For historic reasons and backward-compatibility, some CPU and OS identifiers are translated from the GNU Autotools naming convention in [`meson.build`](https://git.lix.systems/lix-project/lix/src/branch/main/meson.build) as follows:
|
||||
For historic reasons and backward-compatibility, some CPU and OS identifiers are translated from the GNU Autotools naming convention in [`meson.build`](https://git.lix.systems/lix-project/lix/blob/main/meson.build) as follows:
|
||||
|
||||
| `host_machine.cpu_family()` | Nix |
|
||||
|----------------------------|---------------------|
|
||||
@@ -305,13 +243,13 @@ To build with one of those environments, you can use
|
||||
$ nix build .#nix-ccacheStdenv
|
||||
```
|
||||
|
||||
for <a id="nix-with-flakes">flake-enabled Nix</a>, or
|
||||
for flake-enabled Nix, or
|
||||
|
||||
```console
|
||||
$ nix-build --attr nix-ccacheStdenv
|
||||
```
|
||||
|
||||
for <a id="classic-nix">classic Nix</a>.
|
||||
for classic Nix.
|
||||
|
||||
You can use any of the other supported environments in place of `nix-ccacheStdenv`.
|
||||
|
||||
@@ -335,10 +273,10 @@ Configure your editor to use the `clangd` from the shell, either by running it i
|
||||
> Some other editors (e.g. Emacs, Vim) need a plugin to support LSP servers in general (e.g. [lsp-mode](https://github.com/emacs-lsp/lsp-mode) for Emacs and [vim-lsp](https://github.com/prabirshrestha/vim-lsp) for vim).
|
||||
> Editor-specific setup is typically opinionated, so we will not cover it here in more detail.
|
||||
|
||||
# Manual and documentation
|
||||
|
||||
## Building the manual
|
||||
### Checking links in the manual
|
||||
|
||||
The build checks for broken internal links.
|
||||
This happens late in the process, so `nix build` is not suitable for iterating.
|
||||
To build the manual incrementally, run:
|
||||
|
||||
```console
|
||||
@@ -350,20 +288,15 @@ meson compile -C build manual
|
||||
[`mdbook-linkcheck`]: https://github.com/Michael-F-Bryan/mdbook-linkcheck
|
||||
[URI fragments]: https://en.wikipedia.org/wiki/URI_fragment
|
||||
|
||||
The built manual is in `build/doc/manual/manual/index.html`.
|
||||
#### `@docroot@` variable
|
||||
|
||||
The build checks for broken internal links.
|
||||
This happens late in the process, so `nix build` is not suitable for iterating and it's recommended to use the `meson` command above instead.
|
||||
`@docroot@` provides a base path for links that occur in reusable snippets or other documentation that doesn't have a base path of its own.
|
||||
|
||||
### `@\docroot\@` variable
|
||||
If a broken link occurs in a snippet that was inserted into multiple generated files in different directories, use `@docroot@` to reference the `doc/manual/src` directory.
|
||||
|
||||
`@\docroot\@` provides a base path for links that occur in reusable snippets or other documentation that doesn't have a base path of its own.
|
||||
|
||||
If a broken link occurs in a snippet that was inserted into multiple generated files in different directories, use `@\docroot\@` to reference the `doc/manual/src` directory.
|
||||
|
||||
If the `@\docroot\@` literal appears in an error message from the `mdbook-linkcheck` tool, the `@\docroot\@` replacement needs to be applied to the generated source file that mentions it.
|
||||
See existing `@\docroot\@` logic in `doc/manual/substitute.py`.
|
||||
Regular markdown files used for the manual have a base path of their own and they can use relative paths instead of `@\docroot\@`.
|
||||
If the `@docroot@` literal appears in an error message from the `mdbook-linkcheck` tool, the `@docroot@` replacement needs to be applied to the generated source file that mentions it.
|
||||
See existing `@docroot@` logic in the [Makefile].
|
||||
Regular markdown files used for the manual have a base path of their own and they can use relative paths instead of `@docroot@`.
|
||||
|
||||
## API documentation
|
||||
|
||||
@@ -395,7 +328,7 @@ You can build it yourself:
|
||||
|
||||
Metrics about the change in line/function coverage over time will be available in the future (FIXME(lix-hydra)).
|
||||
|
||||
## Add a release note {#release-notes}
|
||||
## Add a release note
|
||||
|
||||
`doc/manual/rl-next` contains release notes entries for all unreleased changes.
|
||||
|
||||
@@ -464,77 +397,4 @@ The following properties are supported:
|
||||
### Build process
|
||||
|
||||
Releases have a precomputed `rl-MAJOR.MINOR.md`, and no `rl-next.md`.
|
||||
Development releases have a generated `rl-next.md`.
|
||||
|
||||
# Adding experimental or deprecated features, global settings, or builtins
|
||||
|
||||
Experimental and deprecated features, global settings, and builtins are generally referenced both in the code and in the documentation.
|
||||
To prevent duplication or divergence, they are defined in data files, and a script generates the necessary glue.
|
||||
The data file format is similar to the release notes: it consists of a YAML metadata header, followed by the documentation in Markdown format.
|
||||
|
||||
## Experimental or deprecated features
|
||||
|
||||
Experimental and deprecated features support the following metadata properties:
|
||||
* `name` (required): user-facing name of the feature, to be used in `nix.conf` options and on the command line.
|
||||
This should also be the stem of the file name (with extension `md`).
|
||||
* `internalName` (required): identifier used to refer to the feature inside the C++ code.
|
||||
|
||||
Experimental feature data files should live in `lix/libutil/experimental-features`, and deprecated features in `lix/libutil/deprecated-features`.
|
||||
They must be listed in the `experimental_feature_definitions` or `deprecated_feature_definitions` lists in `lix/libutil/meson.build` respectively to be considered by the build system.
|
||||
|
||||
## Global settings
|
||||
|
||||
Global settings support the following metadata properties:
|
||||
* `name` (required): user-facing name of the setting, to be used as key in `nix.conf` and in the `--option` command line argument.
|
||||
* `internalName` (required): identifier used to refer to the setting inside the C++ code.
|
||||
* `platforms` (optional): a list specifying the platforms on which this setting is available.
|
||||
If not specified, it is available on all platforms.
|
||||
Valid platform names are `darwin`, `linux`.
|
||||
* `type` (optional): C++ type of the setting value.
|
||||
This specifies the setting object type as `Setting<T>`; if more control is required, use `settingType` instead.
|
||||
* `settingType` (required if `type` is not specified): C++ type of the setting object.
|
||||
* `default` (optional): default value of the setting.
|
||||
`null`, truth values, integers, strings and lists are supported as long as the correct YAML type is used, `type` is not taken into account).
|
||||
Other types, machine-dependent values or non-standard representations must be handled using `defaultExpr` and `defaultText` instead.
|
||||
* `defaultExpr` (required if `default` is not specified): a string containing the C++ expression representing the default value.
|
||||
* `defaultText` (required if `default` is not specified): a string containing the Markdown expression representing the default value in the documentation.
|
||||
Literal values are conventionally surrounded by backticks, and a system-dependent value is signaled by `*machine-specific*`.
|
||||
* `aliases` (optional): a list of secondary user-facing names under which the setting is available.
|
||||
Defaults to empty if not specified.
|
||||
* `experimentalFeature` (optional): the user-facing name of the experimental feature which needs to be enabled to change the setting.
|
||||
If not specified, no experimental feature is required.
|
||||
* `deprecated` (optional): whether the setting is deprecated and shown as such in the documentation for `nix.conf`.
|
||||
Defaults to false if not specified.
|
||||
|
||||
Settings are not collected in a single place in the source tree, so an appropriate place needs to be found for the setting to live.
|
||||
Look for related setting definition files under second-level subdirectories of `lix` whose name includes `settings`.
|
||||
Then add the new file there, and don't forget to register it in the appropriate `meson.build` file.
|
||||
|
||||
## Builtin functions
|
||||
|
||||
The following metadata properties are supported for builtin functions:
|
||||
* `name` (required): the language-facing name (as a member of the `builtins` attribute set) of the function.
|
||||
* `implementation` (optional): a C++ expression specifying the implementation of the builtin.
|
||||
It must be a function of signature `void(EvalState &, PosIdx, Value * *, Value &)`.
|
||||
If not specified, defaults to `prim_${name}`.
|
||||
* `renameInGlobalScope` (optional): whether the definition should be "hidden" in the global scope by prefixing its name with two underscores.
|
||||
If not specified, defaults to `true`.
|
||||
* `args` (required): list containing the names of the arguments, as shown in the documentation.
|
||||
All arguments must be listed here since the function arity is derived as the length of this list.
|
||||
* `experimental_feature` (optional): the user-facing name of the experimental feature which needs to be enabled for the builtin function to be available.
|
||||
If not specified, no experimental feature is required.
|
||||
|
||||
New builtin function definition files must be added to `lix/libexpr/builtins` and registered in the `builtin_definitions` list in `lix/libexpr/meson.build`.
|
||||
|
||||
## Builtin constants
|
||||
The following metadata properties are supported for builtin constants:
|
||||
* `name` (required): the language-facing name (as a member of the `builtins` attribute set) of the constant.
|
||||
* `type` (required): the Nix language type of the constant; the C++ type is automatically derived.
|
||||
* `constructorArgs` (optional): list of strings containing C++ expressions passed as arguments to the appropriate `Value` constructor.
|
||||
If the value computation is more complex, `implementation` can be used instead.
|
||||
* `implementation` (required if `constructorArgs` is not specified): string containing a C++ expressing computing the value of the constant.
|
||||
* `impure` (optional): whether the constant is considered impure.
|
||||
Impure constants are not available when pure evaluation mode is activated.
|
||||
Defaults to `false` when not specified.
|
||||
|
||||
New builtin constant definition files must be added to `lix/libexpr/builtin-constants` and registered in the `builtin_constant_definitions` list in `lix/libexpr/meson.build`.
|
||||
Set `buildUnreleasedNotes = true;` in `flake.nix` to build the release notes on the fly.
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
# Intermediate step for experimental-feature-descriptions.md.
|
||||
# This splorks the output of generate-xp-features.nix as JSON,
|
||||
# which gets written as a directory tree below.
|
||||
experimental_feature_descriptions_md = custom_target(
|
||||
command : nix_eval_for_docs + [
|
||||
'--expr',
|
||||
'import @INPUT0@ (builtins.fromJSON (builtins.readFile @INPUT1@))',
|
||||
],
|
||||
input : [
|
||||
'../../generate-xp-features.nix',
|
||||
xp_features_json,
|
||||
],
|
||||
capture : true,
|
||||
output : 'experimental-feature-descriptions.md',
|
||||
)
|
||||
@@ -13,7 +13,7 @@ The unit tests are defined using the [googletest] and [rapidcheck] frameworks.
|
||||
>
|
||||
> ```
|
||||
> …
|
||||
> ├── lix
|
||||
> ├── src
|
||||
> │ ├── libexpr
|
||||
> │ │ ├── …
|
||||
> │ │ ├── value
|
||||
@@ -46,10 +46,10 @@ The unit tests are defined using the [googletest] and [rapidcheck] frameworks.
|
||||
> … … … … … …
|
||||
> ```
|
||||
|
||||
The unit tests for each Lix library (`liblixexpr`, `liblixstore`, etc..) live inside a directory `lix/${library_shortname}/tests` within the directory for the library (`lix/${library_shortname}`).
|
||||
The unit tests for each Lix library (`liblixexpr`, `liblixstore`, etc..) live inside a directory `src/${library_shortname}/tests` within the directory for the library (`src/${library_shortname}`).
|
||||
|
||||
The data is in `tests/unit/LIBNAME/data/LIBNAME`, with one subdir per library, with the same name as where the code goes.
|
||||
For example, `liblixstore` code is in `lix/libstore`, and its test data is in `tests/unit/libstore/data/libstore`.
|
||||
For example, `liblixstore` code is in `src/libstore`, and its test data is in `tests/unit/libstore/data/libstore`.
|
||||
The path to the unit test data directory is passed to the unit test executable with the environment variable `_NIX_TEST_UNIT_DATA`.
|
||||
|
||||
### Running tests
|
||||
@@ -62,12 +62,6 @@ For `installcheck` specifically, first run `just install` before running the tes
|
||||
|
||||
Finer-grained filtering within a test suite is also possible using the [--gtest_filter](https://google.github.io/googletest/advanced.html#running-a-subset-of-the-tests) command-line option to a test suite executable, or the `GTEST_FILTER` environment variable.
|
||||
|
||||
### Inspecting failures
|
||||
|
||||
The test suite emits logs in `build/meson-logs/`; the full textual failure logs are in `build/meson-logs/testlog.txt`.
|
||||
|
||||
If you want a much nicer experience of viewing the logs in a structured manner, use `xunit-viewer --results build/meson-logs/testlog.junit.xml --server` to view them in a web browser.
|
||||
|
||||
### Unit test support libraries
|
||||
|
||||
There are headers and code which are not just used to test the library in question, but also downstream libraries.
|
||||
@@ -253,6 +247,7 @@ To ensure that characterization testing doesn't make it harder to intentionally
|
||||
|
||||
The integration tests are defined in the Nix flake under the `hydraJobs.tests` attribute.
|
||||
These tests include everything that needs to interact with external services or run Lix in a non-trivial distributed setup.
|
||||
Because these tests are expensive and require more than what the standard github-actions setup provides, they only run on the master branch (on <https://hydra.nixos.org/jobset/nix/master>).
|
||||
|
||||
You can run them manually with `nix build .#hydraJobs.tests.{testName}` or `nix-build -A hydraJobs.tests.{testName}`
|
||||
|
||||
@@ -351,7 +346,7 @@ rg '(?:[^A-Za-z]|^)(_[A-Z][^-\[ }/:");$(]+)' -r '$1' --no-filename --only-matchi
|
||||
rg '\$\{?([A-Z][^-\[ }/:");]+)' -r '$1' --no-filename --only-matching tests | sort -u > vars.txt
|
||||
```
|
||||
|
||||
I grepped `lix/` for `get[eE]nv\("` to find the mentions in Lix code.
|
||||
I grepped `src/` for `get[eE]nv\("` to find the mentions in Lix code.
|
||||
|
||||
### Used by Lix testing support code
|
||||
|
||||
@@ -367,8 +362,8 @@ I grepped `lix/` for `get[eE]nv\("` to find the mentions in Lix code.
|
||||
|
||||
- `_NIX_FORCE_HTTP` - Forces file URIs to be treated as remote ones.
|
||||
|
||||
Used by `lix/libfetchers/git.cc`, `lix/libstore/http-binary-cache-store.cc`,
|
||||
`lix/libstore/local-binary-cache-store.cc`. Seems to be for forcing Git
|
||||
Used by `src/libfetchers/git.cc`, `src/libstore/http-binary-cache-store.cc`,
|
||||
`src/libstore/local-binary-cache-store.cc`. Seems to be for forcing Git
|
||||
clones of `git+file://` URLs, making the HTTP binary
|
||||
cache store accept `file://` URLs (presumably passing them to curl?), and
|
||||
unknown reasons for the local binary cache.
|
||||
@@ -380,7 +375,7 @@ I grepped `lix/` for `get[eE]nv\("` to find the mentions in Lix code.
|
||||
`structuredAttrs` documentation.
|
||||
- `NIX_BIN_DIR`, `NIX_STORE_DIR` (or its inconsistently-used old alias `NIX_STORE`), `NIX_DATA_DIR`,
|
||||
`NIX_LOG_DIR`, `NIX_LOG_DIR`, `NIX_STATE_DIR`, `NIX_CONF_DIR` -
|
||||
Overrides compile-time configuration of various locations used by Lix. See `lix/libstore/globals.cc`.
|
||||
Overrides compile-time configuration of various locations used by Lix. See `src/libstore/globals.cc`.
|
||||
|
||||
**Expected value**: a directory
|
||||
- `NIX_DAEMON_SOCKET_PATH` (optional) - Overrides the daemon socket path from `$NIX_STATE_DIR/daemon-socket/socket`.
|
||||
@@ -433,7 +428,6 @@ I grepped `lix/` for `get[eE]nv\("` to find the mentions in Lix code.
|
||||
- `NIX_SHOW_STATS_PATH` - Writes those statistics into a file at the given path instead of stdout. Undocumented.
|
||||
- `NIX_SHOW_SYMBOLS` - Dumps the symbol table into the show-stats json output.
|
||||
- `TERM` - If `dumb` or unset, disables ANSI colour output.
|
||||
- `FORCE_COLOR`, `CLICOLOR_FORCE` - Enables ANSI colour output if `NO_COLOR`/`NOCOLOR` not set.
|
||||
- `NO_COLOR`, `NOCOLOR` - Disables ANSI colour output.
|
||||
- `_NIX_DEVELOPER_SHOW_UNKNOWN_LOCATIONS` - Highlights unknown locations in errors.
|
||||
- `NIX_PROFILE` - Selects which profile `nix-env` will operate on. Documented elsewhere.
|
||||
@@ -455,6 +449,9 @@ I grepped `lix/` for `get[eE]nv\("` to find the mentions in Lix code.
|
||||
- `NIX_CLIENT_PACKAGE` - Runs the test suite against an alternate Nix client with the current daemon.
|
||||
|
||||
**Expected value**: something like `/nix/store/...-nix-2.18.2`
|
||||
- `NIX_TESTS_CA_BY_DEFAULT` - Pass `__contentAddressed`, `outputHashMode` and `outputHashAlgo` to builds of some input-addressed derivations in the test suite.
|
||||
|
||||
**Expected value**: 1
|
||||
- `TEST_DATA` - Not an environment variable! This is used in repl characterization tests to refer to `tests/functional/repl_characterization/data`.
|
||||
More specifically, that path is replaced with the string `$TEST_DATA` in output for reproducibility.
|
||||
- `TEST_HOME` (output) - Set to the temporary directory that is set as `$HOME` inside the tests, underneath `$TEST_ROOT`.
|
||||
|
||||
@@ -41,6 +41,12 @@
|
||||
|
||||
[realise]: #gloss-realise
|
||||
|
||||
- [content-addressed derivation]{#gloss-content-addressed-derivation}
|
||||
|
||||
A derivation which has the
|
||||
[`__contentAddressed`](./language/advanced-attributes.md#adv-attr-__contentAddressed)
|
||||
attribute set to `true`.
|
||||
|
||||
- [fixed-output derivation]{#gloss-fixed-output-derivation}
|
||||
|
||||
A derivation which includes the
|
||||
@@ -95,7 +101,7 @@
|
||||
|
||||
See [File System Object](@docroot@/architecture/file-system-object.md) for details.
|
||||
|
||||
[file system object]: #gloss-store-path
|
||||
[file system object]: #gloss-file-system-object
|
||||
|
||||
- [store object]{#gloss-store-object}
|
||||
|
||||
@@ -108,13 +114,14 @@
|
||||
- [input-addressed store object]{#gloss-input-addressed-store-object}
|
||||
|
||||
A store object produced by building a
|
||||
non-[content-addressed](#gloss-content-addressed-derivation),
|
||||
non-[fixed-output](#gloss-fixed-output-derivation)
|
||||
derivation.
|
||||
|
||||
- [output-addressed store object]{#gloss-output-addressed-store-object}
|
||||
|
||||
A [store object] whose [store path] is determined by its contents.
|
||||
This includes derivations and the outputs of [fixed-output derivations](#gloss-fixed-output-derivation).
|
||||
This includes derivations, the outputs of [content-addressed derivations](#gloss-content-addressed-derivation), and the outputs of [fixed-output derivations](#gloss-fixed-output-derivation).
|
||||
|
||||
- [substitute]{#gloss-substitute}
|
||||
|
||||
@@ -242,7 +249,7 @@
|
||||
links. NARs are generated and unpacked using `nix-store --dump`
|
||||
and `nix-store --restore`.
|
||||
|
||||
- [`∅`]{#gloss-empty-set}
|
||||
- [`∅`]{#gloss-emtpy-set}
|
||||
|
||||
The empty set symbol. In the context of profile history, this denotes a package is not present in a particular version of the profile.
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Installing a Binary Distribution
|
||||
|
||||
See <https://lix.systems/install/> for more details.
|
||||
See https://lix.systems/install/ for more details.
|
||||
|
||||
<!--
|
||||
|
||||
|
||||
@@ -60,10 +60,3 @@ Then:
|
||||
```console
|
||||
$ docker run -ti lix
|
||||
```
|
||||
|
||||
# Known issues
|
||||
|
||||
Lix in Docker is very sensitive to **functional** DNS resolution if you are running with [Pasta protections](../advanced-topics/pasta.md) which are enabled by default since Lix 2.93.0 on most distributions.
|
||||
If you notice failure to download things, double check whether your **first** DNS entry in `/etc/resolv.conf` is functional.
|
||||
|
||||
Lix with [Pasta protections](../advanced-topics/pasta.md) does not support failing over the next entries.
|
||||
|
||||
@@ -36,10 +36,7 @@ All users of the Lix daemon may do the following to bring things into the Nix st
|
||||
- Input-addressed, so they are run in the sandbox with no network access, with the following exceptions:
|
||||
|
||||
- The (poorly named, since it is not *just* about chroot) property `__noChroot` is set on the derivation and `sandbox` is set to `relaxed`.
|
||||
- On macOS, the derivation property `__darwinAllowLocalNetworking` allows network access to localhost from input-addressed derivations regardless of the `sandbox` setting value.
|
||||
This property exists with such semantics because macOS has no network namespace equivalent to isolate individual processes' localhost networking.
|
||||
- On macOS, the derivation property `__sandboxProfile` accepts extra sandbox profile S-expressions, allowing derivations to bypass arbitrary parts of the sandbox without altogether disabling it.
|
||||
This is only permitted when `sandbox` is set to `relaxed`.
|
||||
- On macOS, the derivation property `__darwinAllowLocalNetworking` allows network access to localhost from input-addressed derivations regardless of the `sandbox` setting value. This property exists with such semantics because macOS has no network namespace equivalent to isolate individual processes' localhost networking.
|
||||
- Output-addressed, so they are run with network access but their result must match an expected hash.
|
||||
|
||||
Trusted users may set any setting, including `sandbox = false`, so the sandbox state can be different at runtime from what is described in `nix.conf` for builds invoked with such settings.
|
||||
|
||||
@@ -54,6 +54,11 @@ The most current alternative to this section is to read `package.nix` and see wh
|
||||
obtained from the its repository
|
||||
<https://github.com/troglobit/editline>.
|
||||
|
||||
- The `libsodium` library for verifying cryptographic signatures
|
||||
of contents fetched from binary caches.
|
||||
It can be obtained from the official web site
|
||||
<https://libsodium.org>.
|
||||
|
||||
- Recent versions of Bison and Flex to build the parser. (This is
|
||||
because Nix needs GLR support in Bison and reentrancy support in
|
||||
Flex.) For Bison, you need version 2.6, which can be obtained from
|
||||
|
||||
@@ -148,7 +148,7 @@ paths) are set.
|
||||
|
||||
For example, the following command gets all dependencies of the
|
||||
Pan newsreader, as described by [its
|
||||
Nix expression](https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-name/pa/pan/package.nix):
|
||||
Nix expression](https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/networking/newsreaders/pan/default.nix):
|
||||
|
||||
```console
|
||||
$ nix-shell '<nixpkgs>' --attr pan
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
This section lists known issues around Lix.
|
||||
@@ -1,21 +0,0 @@
|
||||
# Limitations of non-isolated builds
|
||||
|
||||
## What are non-isolated builds?
|
||||
|
||||
In Lix, only builds done on Linux with `sandbox = true` and a functioning
|
||||
`pasta-path` are isolated from the rest of the system, all other builds are
|
||||
considered non-isolated to some degree.
|
||||
|
||||
For example, running Lix with [Pasta](@docroot@/advanced-topics/pasta.md)
|
||||
disabled makes the host network visible to fixed-output derivations, reducing
|
||||
isolation somewhat.
|
||||
|
||||
## Clean termination of non-isolated builds
|
||||
|
||||
Non-isolated builds may not terminate cleanly in all cases due to limitations in Lix's process management.
|
||||
|
||||
This occurs when a build keeps the build log file descriptor open past the end of the actual build. A common cause of this are background tasks that aren't properly terminated before the main build process exits, for example: HTTP servers run as part of a test suite.
|
||||
|
||||
See [issue #1018](https://git.lix.systems/lix-project/lix/issues/1018) for an example.
|
||||
|
||||
The only solution is to manually terminate leftover processes in your derivation, including during failure scenarios.
|
||||
@@ -209,8 +209,15 @@ Derivations can declare some infrequently used optional attributes.
|
||||
|
||||
- [`__contentAddressed`]{#adv-attr-__contentAddressed}
|
||||
> **Warning**
|
||||
> This attribute is part of a removed [experimental feature](@docroot@/contributing/experimental-features.md).
|
||||
> Setting this flag *will* cause eval errors.
|
||||
> This attribute is part of an [experimental feature](@docroot@/contributing/experimental-features.md).
|
||||
>
|
||||
> To use this attribute, you must enable the
|
||||
> [`ca-derivations`](@docroot@/contributing/experimental-features.md#xp-feature-ca-derivations) experimental feature.
|
||||
> For example, in [nix.conf](../command-ref/conf-file.md) you could add:
|
||||
>
|
||||
> ```
|
||||
> extra-experimental-features = ca-derivations
|
||||
> ```
|
||||
|
||||
If this attribute is set to `true`, then the derivation
|
||||
outputs will be stored in a content-addressed location rather than the
|
||||
@@ -254,7 +261,7 @@ Derivations can declare some infrequently used optional attributes.
|
||||
useful for very trivial derivations (such as `writeText` in Nixpkgs)
|
||||
that are cheaper to build than to substitute from a binary cache.
|
||||
|
||||
You may disable the effects of this attribute by enabling the
|
||||
You may disable the effects of this attibute by enabling the
|
||||
`always-allow-substitutes` configuration option in Lix.
|
||||
|
||||
> **Note**
|
||||
@@ -285,12 +292,6 @@ Derivations can declare some infrequently used optional attributes.
|
||||
(associative) arrays. For example, the attribute `hardening.format = true`
|
||||
ends up as the Bash associative array element `${hardening[format]}`.
|
||||
|
||||
> **Warning**
|
||||
>
|
||||
> If set to `true`, other advanced attributes such as [`allowedReferences`](#adv-attr-allowedReferences), [`allowedReferences`](#adv-attr-allowedReferences), [`allowedRequisites`](#adv-attr-allowedRequisites),
|
||||
[`disallowedReferences`](#adv-attr-disallowedReferences) and [`disallowedRequisites`](#adv-attr-disallowedRequisites), maxSize, and maxClosureSize.
|
||||
will have no effect.
|
||||
|
||||
- [`outputChecks`]{#adv-attr-outputChecks}\
|
||||
When using [structured attributes](#adv-attr-structuredAttrs), the `outputChecks`
|
||||
attribute allows defining checks per-output.
|
||||
@@ -302,6 +303,8 @@ Derivations can declare some infrequently used optional attributes.
|
||||
|
||||
- `maxSize` defines the maximum size of the resulting [store object](../glossary.md#gloss-store-object).
|
||||
- `maxClosureSize` defines the maximum size of the output's closure.
|
||||
- `ignoreSelfRefs` controls whether self-references should be considered when
|
||||
checking for allowed references/requisites.
|
||||
|
||||
Example:
|
||||
|
||||
@@ -323,6 +326,7 @@ Derivations can declare some infrequently used optional attributes.
|
||||
```
|
||||
|
||||
- [`unsafeDiscardReferences`]{#adv-attr-unsafeDiscardReferences}\
|
||||
|
||||
When using [structured attributes](#adv-attr-structuredAttrs), the
|
||||
attribute `unsafeDiscardReferences` is an attribute set with a boolean value for each output name.
|
||||
If set to `true`, it disables scanning the output for runtime dependencies.
|
||||
|
||||
@@ -4,7 +4,7 @@ These constants are built into the Nix language evaluator:
|
||||
|
||||
<dl>
|
||||
|
||||
{{#include @generated@/../../../lix/libexpr/builtin-constants.md}}
|
||||
{{#include @generated@/language/builtin-constants.md}}
|
||||
|
||||
</dl>
|
||||
|
||||
|
||||
@@ -15,6 +15,6 @@ For convenience, some built-ins can be accessed directly:
|
||||
<dd><p><var>derivation</var> is described in
|
||||
<a href="derivations.md">its own section</a>.</p></dd>
|
||||
|
||||
{{#include @generated@/../../../lix/libexpr/builtins.md}}
|
||||
{{#include @generated@/language/builtins.md}}
|
||||
|
||||
</dl>
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
builtins_md = custom_target(
|
||||
command : nix_eval_for_docs + [
|
||||
'--expr',
|
||||
'import @INPUT0@ (builtins.fromJSON (builtins.readFile @INPUT1@)).builtins',
|
||||
],
|
||||
capture : true,
|
||||
input : [
|
||||
'../../generate-builtins.nix',
|
||||
language_json,
|
||||
],
|
||||
output : 'builtins.md',
|
||||
env : nix_env_for_docs,
|
||||
)
|
||||
|
||||
builtin_constants_md = custom_target(
|
||||
command : nix_eval_for_docs + [
|
||||
'--expr',
|
||||
'import @INPUT0@ (builtins.fromJSON (builtins.readFile @INPUT1@)).constants',
|
||||
],
|
||||
capture : true,
|
||||
input : [
|
||||
'../../generate-builtin-constants.nix',
|
||||
language_json,
|
||||
],
|
||||
output : 'builtin-constants.md',
|
||||
env : nix_env_for_docs,
|
||||
)
|
||||
@@ -26,8 +26,6 @@
|
||||
| Logical conjunction (`AND`) | *bool* `&&` *bool* | left | 12 |
|
||||
| Logical disjunction (`OR`) | *bool* <code>\|\|</code> *bool* | left | 13 |
|
||||
| [Logical implication] | *bool* `->` *bool* | none | 14 |
|
||||
| \[Experimental\] [Function piping] | *expr* `\|>` *func* | left | 15 |
|
||||
| \[Experimental\] [Function piping] | *expr* `<\|` *func* | right | 16 |
|
||||
|
||||
[string]: ./values.md#type-string
|
||||
[path]: ./values.md#type-path
|
||||
@@ -61,10 +59,8 @@ The result is a [Boolean] value.
|
||||
|
||||
## Arithmetic
|
||||
|
||||
Numbers will retain their type unless mixed with other numeric types:
|
||||
Pure integer operations will always return integers, whereas any operation involving at least one floating point number returns a floating point number.
|
||||
|
||||
Integer overflow (of 64-bit signed integers) and division by zero are defined to throw an error.
|
||||
Numbers are type-compatible:
|
||||
Pure integer operations will always return integers, whereas any operation involving at least one floating point number return a floating point number.
|
||||
|
||||
See also [Comparison] and [Equality].
|
||||
|
||||
@@ -147,103 +143,21 @@ All comparison operators are implemented in terms of `<`, and the following equi
|
||||
| *a* `>` *b* | *b* `<` *a* |
|
||||
| *a* `>=` *b* | `! (` *a* `<` *b* `)` |
|
||||
|
||||
Note that the above behaviour violates IEEE 754 for floating point numbers with respect to NaN, for instance.
|
||||
This may be fixed in a future major language revision.
|
||||
|
||||
[Comparison]: #comparison-operators
|
||||
|
||||
## Equality
|
||||
|
||||
The following equality comparison rules are followed in order:
|
||||
|
||||
- Comparisons are first, sometimes, performed by identity (pointer value), and whether or not this occurs varies depending on the context in which the comparison is performed; for example, through `builtins.elem`, comparison of lists, or other cases.
|
||||
The exact instances in which this occurs, aside from direct list and attribute set comparisons as discussed below, are too dependent on implementation details to meaningfully document.
|
||||
|
||||
See [note on identity comparison](#identity-comparison) below.
|
||||
- Comparisons between a combination of integers and floating point numbers are first converted to floating point then compared as floating point.
|
||||
- Comparisons between values of differing types, besides the ones mentioned in the above rule, are unequal.
|
||||
- Strings are compared as their string values, disregarding string contexts.
|
||||
- Paths are compared as their absolute form (since they are stored as such).
|
||||
- [Functions][function] are always considered unequal, including with themselves.
|
||||
- The following are compared in the typical manner:
|
||||
- Integers
|
||||
- Floating point numbers have equality comparison per IEEE 754.
|
||||
|
||||
Note that this means that just like in most languages, floating point arithmetic results are not typically equality comparable, and should instead be compared by checking that the absolute difference is less than some error margin.
|
||||
- Booleans
|
||||
- Null
|
||||
- [Attribute sets][attribute set] are compared following these rules in order:
|
||||
- If both attribute sets have the same identity (via pointer equality), they are considered equal, regardless of whether the contents have reflexive equality (e.g. even if there are functions contained within).
|
||||
|
||||
See [note on identity comparison](#identity-comparison) below.
|
||||
- If both attribute sets have `type = "derivation"` and have an attribute `outPath` that is equal, they are considered equal.
|
||||
|
||||
This means that two results of `builtins.derivation`, regardless of other things added to their attributes via `//` afterwards (or `passthru` in nixpkgs), will compare equal if they passed the same arguments to `builtins.derivation`.
|
||||
- Otherwise, they are compared element-wise in an unspecified order.
|
||||
Although this order *may* be deterministic in some cases, this is not guaranteed, and correct code must not rely on this ordering behaviour.
|
||||
|
||||
The order determines which elements are evaluated first and thus, if there are throwing values in the attribute set, which of those get evaluated, if any, before the comparison returns an unequal result.
|
||||
- Lists are compared following these rules in order:
|
||||
- If both lists have the same identity (via pointer equality), they are considered equal, regardless of whether the contents have reflexive equality (e.g. even if there are functions contained within).
|
||||
|
||||
See [note on identity comparison](#identity-comparison) below.
|
||||
- Otherwise, they are compared element-wise in list order.
|
||||
- [Attribute sets][attribute set] and [list]s are compared recursively, and therefore are fully evaluated.
|
||||
- Comparison of [function]s always returns `false`.
|
||||
- Numbers are type-compatible, see [arithmetic] operators.
|
||||
- Floating point numbers only differ up to a limited precision.
|
||||
|
||||
[function]: ./constructs.md#functions
|
||||
|
||||
[Equality]: #equality
|
||||
|
||||
### Identity comparison
|
||||
|
||||
In the current revision of the Nix language, values are first compared by identity (pointer equality).
|
||||
This means that values that are not reflexively equal (that is, they do not satisfy `a == a`), such as functions, are nonetheless sometimes compared as equal with themselves if they are placed in attribute sets or lists, or are compared through other indirect means.
|
||||
|
||||
Whether identity comparison applies to a given usage of the language aside from direct list and attribute set comparison is strongly dependent on implementation details to the point it is not feasible to document the exact instances.
|
||||
|
||||
This is rather unfortunate behaviour which is regrettably load-bearing on nixpkgs (such as with the `type` attribute of NixOS options) and cannot be changed for the time being.
|
||||
It may be changed in a future major language revision.
|
||||
|
||||
Correct code must not rely on this behaviour.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
nix-repl> let f = x: 1; s = { func = f; }; in [ (f == f) (s == s) ]
|
||||
[ false true ]
|
||||
```
|
||||
|
||||
## Logical implication
|
||||
|
||||
Equivalent to `!`*b1* `||` *b2*.
|
||||
|
||||
[Logical implication]: #logical-implication
|
||||
|
||||
## \[Experimental\] Function piping
|
||||
|
||||
*This language feature is still experimental and may change at any time. Enable `--extra-experimental-features pipe-operator` to use it.*
|
||||
|
||||
Pipes are a dedicated operator for function application, but with reverse order and a lower binding strength.
|
||||
This allows you to chain function calls together in way that is more natural to read and requires less parentheses.
|
||||
|
||||
`a |> f b |> g` is equivalent to `g (f b a)`.
|
||||
`g <| f b <| a` is equivalent to `g (f b a)`.
|
||||
|
||||
Example code snippet:
|
||||
|
||||
```nix
|
||||
defaultPrefsFile = defaultPrefs
|
||||
|> lib.mapAttrsToList (
|
||||
key: value: ''
|
||||
// ${value.reason}
|
||||
pref("${key}", ${builtins.toJSON value.value});
|
||||
''
|
||||
)
|
||||
|> lib.concatStringsSep "\n"
|
||||
|> pkgs.writeText "nixos-default-prefs.js";
|
||||
```
|
||||
|
||||
Note how `mapAttrsToList` is called with two arguments (the lambda and `defaultPrefs`),
|
||||
but moving the last argument in front of the rest improves the reading flow.
|
||||
This is common for functions with long first argument, including all `map`-like functions.
|
||||
|
||||
[Function piping]: #experimental-function-piping
|
||||
|
||||
@@ -7,16 +7,13 @@
|
||||
*Strings* can be written in three ways.
|
||||
|
||||
The most common way is to enclose the string between double quotes,
|
||||
e.g., `"foo bar"`. Strings can span multiple lines. The backslash
|
||||
(`\`) can be used to escape characters: newlines, carriage returns
|
||||
and tabs may be written as `\n`, `\r` and `\t` respectively; any
|
||||
other characters can be preceded by a backslash to remove any
|
||||
special meaning they may have, like the special characters `"` and
|
||||
`\` and the character sequence `${`.
|
||||
e.g., `"foo bar"`. Strings can span multiple lines. The special
|
||||
characters `"` and `\` and the character sequence `${` must be
|
||||
escaped by prefixing them with a backslash (`\`). Newlines, carriage
|
||||
returns and tabs can be written as `\n`, `\r` and `\t`,
|
||||
respectively.
|
||||
|
||||
You can include the results of other expressions into a string by enclosing them in `${ }`, a feature known as [string interpolation].
|
||||
Due to a parser issue that has since come to be relied upon, the character sequence `$${` is interpreted literally and does not introduce an interpolation.
|
||||
To express a `$` character immediately followed by an interpolation, the former must be escaped.
|
||||
|
||||
[string interpolation]: ./string-interpolation.md
|
||||
|
||||
@@ -46,16 +43,16 @@
|
||||
Note that the whitespace and newline following the opening `''` is
|
||||
ignored if there is no non-whitespace text on the initial line.
|
||||
|
||||
Indented strings support [string interpolation].
|
||||
|
||||
Since `${` and `''` have special meaning in indented strings, you
|
||||
need a way to quote them. `$` can be escaped by prefixing it with
|
||||
`''` (that is, two single quotes), i.e., `''$`. `''` can be escaped
|
||||
by prefixing it with `'`, i.e., `'''`. Linefeed, carriage-return and tab
|
||||
by prefixing it with `'`, i.e., `'''`. `$` removes any special
|
||||
meaning from the following `$`. Linefeed, carriage-return and tab
|
||||
characters can be written as `''\n`, `''\r`, `''\t`, and `''\`
|
||||
escapes any other character.
|
||||
|
||||
Indented strings support [string interpolation] using `${ }` the same way regular strings do.
|
||||
`$${` is interpreted literally in indented strings as well, so the `$` character must be escaped if it is to be followed by an interpolation.
|
||||
|
||||
Indented strings are primarily useful in that they allow multi-line
|
||||
string literals to follow the indentation of the enclosing Nix
|
||||
expression, and that less escaping is typically necessary for
|
||||
@@ -77,14 +74,17 @@
|
||||
}
|
||||
```
|
||||
|
||||
Finally, as a convenience, *URIs* as defined in appendix B of
|
||||
[RFC 2396](http://www.ietf.org/rfc/rfc2396.txt) can be written *as
|
||||
is*, without quotes. For instance, the string
|
||||
`"http://example.org/foo.tar.bz2"` can also be written as
|
||||
`http://example.org/foo.tar.bz2`.
|
||||
|
||||
- <a id="type-number" href="#type-number">Number</a>
|
||||
|
||||
Numbers, which can be *integers* (like `123`) or *floating point*
|
||||
(like `123.43` or `.27e13`).
|
||||
|
||||
Integers in the Nix language are 64-bit signed integers.
|
||||
Integer overflow is defined to throw an error.
|
||||
|
||||
See [arithmetic] and [comparison] operators for semantics.
|
||||
|
||||
[arithmetic]: ./operators.md#arithmetic
|
||||
@@ -164,7 +164,7 @@ Note that lists are only lazy in values, and they are strict in length.
|
||||
|
||||
An attribute set is a collection of name-value-pairs (called *attributes*) enclosed in curly brackets (`{ }`).
|
||||
|
||||
An attribute name can be an identifier or a [string](#type-string).
|
||||
An attribute name can be an identifier or a [string](#string).
|
||||
An identifier must start with a letter (`a-z`, `A-Z`) or underscore (`_`), and can otherwise contain letters (`a-z`, `A-Z`), numbers (`0-9`), underscores (`_`), apostrophes (`'`), or dashes (`-`).
|
||||
|
||||
> *name* = *identifier* | *string* \
|
||||
|
||||
@@ -41,7 +41,7 @@ install Lix. If this is not the case for some reason, you can add it
|
||||
as follows:
|
||||
|
||||
```console
|
||||
$ nix-channel --add https://channels.nixos.org/nixpkgs-unstable
|
||||
$ nix-channel --add https://nixos.org/channels/nixpkgs-unstable
|
||||
$ nix-channel --update
|
||||
```
|
||||
|
||||
@@ -49,7 +49,7 @@ $ nix-channel --update
|
||||
>
|
||||
> On NixOS, you’re automatically subscribed to a NixOS channel
|
||||
> corresponding to your NixOS major release (e.g.
|
||||
> <https://channels.nixos.org/nixos-21.11>). A NixOS channel is identical
|
||||
> <http://nixos.org/channels/nixos-21.11>). A NixOS channel is identical
|
||||
> to the Nixpkgs channel, except that it contains only Linux binaries
|
||||
> and is updated only if a set of regression tests succeed.
|
||||
|
||||
@@ -126,7 +126,7 @@ $ nix-env --install --attr nixpkgs.subversion
|
||||
```
|
||||
|
||||
will install the package called `subversion` from `nixpkgs` channel (which is, of course, the
|
||||
[Subversion version management system](https://subversion.apache.org/)).
|
||||
[Subversion version management system](http://subversion.tigris.org/)).
|
||||
|
||||
> **Note**
|
||||
>
|
||||
|
||||
@@ -71,62 +71,3 @@ $ nix-collect-garbage -d
|
||||
```
|
||||
|
||||
is a quick and easy way to clean up your system.
|
||||
|
||||
## Garbage Collector Roots
|
||||
|
||||
### Explicit roots
|
||||
|
||||
All store paths to which there are symlinks in the directory
|
||||
`prefix/nix/var/nix/gcroots` will be used as roots by the garbage
|
||||
collector. For instance, the following command makes the path
|
||||
`/nix/store/d718ef...-foo` a root of the collector:
|
||||
|
||||
```console
|
||||
$ ln -s /nix/store/d718ef...-foo /nix/var/nix/gcroots/bar
|
||||
```
|
||||
|
||||
That is, after this command, the garbage collector will not remove
|
||||
`/nix/store/d718ef...-foo` or any of its dependencies.
|
||||
|
||||
Subdirectories of `prefix/nix/var/nix/gcroots` are also searched for
|
||||
symlinks.
|
||||
|
||||
Symlinks may also point to paths outside the nix store. If the
|
||||
destination of the symlink is itself a symlink to a store path, it
|
||||
is also considered a root. This style of GC root is called an
|
||||
"indirect root", and is created by tools like `nix-build` to avoid
|
||||
garbage-collecting paths that are being used on-the-fly rather than
|
||||
installed in profiles.
|
||||
|
||||
|
||||
### In-use roots
|
||||
|
||||
Lix will also perform a best-effort detection of paths that are in use
|
||||
by running processes when scanning for garbage collection roots, to
|
||||
avoid removing paths that are still needed by running processes.
|
||||
|
||||
Exact details vary between platforms, but the following will generally
|
||||
be taken into account:
|
||||
|
||||
- Executables in the store that are currently running;
|
||||
- Other files in the store that are mapped into a process's address space (e.g. shared libraries);
|
||||
- Files in the store to which processes have open handles;
|
||||
- Store paths found in processes' environment variables.
|
||||
|
||||
Note that this detection is susceptible to missing paths that may still be in use for multiple reasons:
|
||||
|
||||
- Time-of-check-to-time-of-use (TOCTTOU): new processes may appear
|
||||
after Lix has enumerated the currently running processes, and will
|
||||
not be taken into account;
|
||||
- Access privileges: if the garbage collection is not running as the
|
||||
root user (this is typically the case for single-user
|
||||
installations), it will not be able to scan processes belonging to
|
||||
other users;
|
||||
- Other types of references: store paths may be stored in parts of the
|
||||
filesystem (e.g. databases) or process memory (e.g. environment
|
||||
variables changed since the start of the process) that Lix does not
|
||||
scan.
|
||||
|
||||
For this reason, it is recommended to create explicit roots whenever
|
||||
using store paths that aren't obtained from some existing explicit GC
|
||||
root.
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
# Garbage Collector Roots
|
||||
|
||||
The roots of the garbage collector are all store paths to which there
|
||||
are symlinks in the directory `prefix/nix/var/nix/gcroots`. For
|
||||
instance, the following command makes the path
|
||||
`/nix/store/d718ef...-foo` a root of the collector:
|
||||
|
||||
```console
|
||||
$ ln -s /nix/store/d718ef...-foo /nix/var/nix/gcroots/bar
|
||||
```
|
||||
|
||||
That is, after this command, the garbage collector will not remove
|
||||
`/nix/store/d718ef...-foo` or any of its dependencies.
|
||||
|
||||
Subdirectories of `prefix/nix/var/nix/gcroots` are also searched for
|
||||
symlinks. Symlinks to non-store paths are followed and searched for
|
||||
roots, but symlinks to non-store paths *inside* the paths reached in
|
||||
that way are not followed to prevent infinite recursion.
|
||||
@@ -2,8 +2,18 @@
|
||||
|
||||
For historical reasons, [derivations](@docroot@/glossary.md#gloss-store-derivation) are stored on-disk in [ATerm](https://homepages.cwi.nl/~daybuild/daily-books/technology/aterm-guide/aterm-guide.html) format.
|
||||
|
||||
Derivations are serialised in the following format:
|
||||
Derivations are serialised in one of the following formats:
|
||||
|
||||
```
|
||||
Derive(...)
|
||||
```
|
||||
- ```
|
||||
Derive(...)
|
||||
```
|
||||
|
||||
For all stable derivations.
|
||||
|
||||
- ```
|
||||
DrvWithVersion(<version-string>, ...)
|
||||
```
|
||||
|
||||
The only `version-string`s that are in use today are for [experimental features](@docroot@/contributing/experimental-features.md):
|
||||
|
||||
- `"xp-dyn-drv"` for the [`dynamic-derivations`](@docroot@/contributing/experimental-features.md#xp-feature-dynamic-derivations) experimental feature.
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
- The `discard-references` feature has been stabilized.
|
||||
This means that the
|
||||
`unsafeDiscardReferences`
|
||||
[unsafeDiscardReferences](@docroot@/contributing/experimental-features.md#xp-feature-discard-references)
|
||||
attribute is no longer guarded by an experimental flag and can be used
|
||||
freely.
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user