Compare commits

..
Author SHA1 Message Date
eldritch horrors e0beb9b118 [WIP] remove boost coroutine uses
we no longer need these since sinkToSource and sourceToSink are gone.

Change-Id: Ibbf440e2cf71bf3e9f3b833af2d78a21fb1b3193
2024-06-30 21:21:58 +02:00
eldritch horrors f274bfddad [WIP] remove sinkToSource and related boehm patch
Change-Id: I1379841299713175d0225b82a67f50660f9eb5e2
2024-06-30 21:21:58 +02:00
eldritch horrors d08787e42e [WIP] remove remaining sinkToSource uses
Change-Id: Id1ee0d2ad4a3774f4bbb960d76f0f76ac4f3eff9
2024-06-30 21:21:58 +02:00
eldritch horrors 0a1520c602 [WIP] generatorize protocol serializers
this is cursed. deeply and profoundly cursed. under NO CIRCUMSTANCES
must protocol serializer helpers be applied to temporaries! doing so
will inevitably cause dangling references and cause the entire thing
to crash. we need to do this even so to get rid of boost coroutines,
and likewise to encapsulate the serializers we suffer today at least
a little bit to allow a gradual migration to an actual IPC protocol.

Change-Id: I2921ba451e04d86798752d140885d3c5cc08e146
2024-06-30 21:21:58 +02:00
eldritch horrors 5264d72846 [WIP] narFromPath as generator
Change-Id: Ifa783c2c65c06ddd1d0212016d5bfd07666ea91c
2024-06-30 21:21:58 +02:00
eldritch horrors 8fb3b89d0f [WIP] libstore: remove a sinkToSouce from old daemon protocol
this doesn't have a test because this code path is only reached by
clients that predate 2.4, and we really should not be caring about
those any more right now. even the test suite doesn't, and the few
tests that might care are disabled because they will not even work

Change-Id: Id9eb190065138fedb2c7d90c328ff9eb9d97385b
2024-06-30 21:21:58 +02:00
eldritch horrors 425f3e6964 [WIP] libstore: rewrite the nar parser as a contents generator
this is not completely necessary at this point because the parser right
now already returns a generator to pass through all input data it read,
but the nar parser *was* very lax and would accept nars that weren't in
canonical form (defined as the form dumpPath would return). nar hashing
depends on these things, and as such rewriting the parser now allows us
to reject non-canonical nars that extract to the same store contents as
their canonical counterpart, but have different nar hashes.

gcc 12 is broken and causes double frees when yielding certain types of
move-only values, so this also pins gcc to 13 for the default stdenv in
23.11-based builds.

Change-Id: Iccd319e3bd5912d8297014c84c495edc59019bb7
2024-06-30 21:21:58 +02:00
eldritch horrors e11945065b libstore: turn copyNAR into a generator
Change-Id: Id452f6a03faa1037ff13af0f63e32883966ff40d
2024-06-30 21:21:58 +02:00
eldritch horrors 2112a39d2e libstore: turn the NAR parser into a passthrough generator
this will let us turn copyNAR into a generator as well, which in turn is
necessary to turn the users of copyNAR into generators without resorting
to sinkToSource coroutines. currently this uses the SerializingTransform
in all cases, even for copyNAR where it is not necessary. should this be
a performance problem we can easily swap out the transform for one which
does not produce any bytes of its own, but that should not be necessary.

Change-Id: I7e685879318fcbb78d8b88abfddd7752360eb0ce
2024-06-30 21:21:58 +02:00
eldritch horrors 48e3637aa3 libutil: remove sourceToSink
Change-Id: I2867ba2b3a7b59af44c1ec51b08329fccba41ca1
2024-06-30 21:21:58 +02:00
eldritch horrors d658cf5a0e libutil: remove makeDecompressionSink
Change-Id: I4258227b5dbbb735a75b477d8a57007bfca305e9
2024-06-30 21:21:58 +02:00
eldritch horrors 93344a1379 libstore: make BinaryCacheStore::getFile return a source
this lets us remove the last true remaining uses of
makeDecompressionSink.

Change-Id: I146ca2bbe1a9ae9a367117a7b8a304b23a63e5e2
2024-06-30 21:21:58 +02:00
eldritch horrors 9f769794d9 libutil: rewrite RewritingSink as source
the rewriting sink was just broken. when given a rewrite set that
contained a key that is also a proper infix of another key it was
possible to produce an incorrectly rewritten result if the writer
used the wrong block size. fixing this duplicates rewriteStrings,
to avoid this we'll rewrite rewriteStrings to use RewritingSource
in a new mode that'll allow rewrites we had previously forbidden.

Change-Id: I57fa0a9a994e654e11d07172b8e31d15f0b7e8c0
2024-06-30 21:21:58 +02:00
eldritch horrors d1230c7218 libutil: remove RewritingSink match/size tracking
size tracking can be done with a LengthSink and a tee. match tracking
was defeated by never having done any match tracking, all users would
see the same (empty) set of matches at all times. match tracking with
bytes offsets alone would not be sufficient in the general case, only
because computeHashModulo uses a single rewrite would it have worked.

Change-Id: Idb214b5222e0ea24f450f5505712a342b63d7570
2024-06-30 21:21:45 +02:00
eldritch horrors 50e1364a80 libutil: turn HashModuloSink into a free function
Change-Id: I5878007502fa68c2816a0f4c61f7d0e60bdde702
2024-06-30 21:08:17 +02:00
eldritch horrors 3e29a98903 libutil: return sources from runProgram2
this much more closely mimics what is actually happening: we're reading
data from somewhere else, actively, rather than passively waiting. with
the data flow matching the underlying system interactions better we can
remove a few sinkToSource calls that merely exists to undo the mismatch
caused by not treating subprocess output as a data source to begin with

Change-Id: If4abfc2f8398fb5e88c9b91a8bdefd5504bb2d11
2024-06-30 21:05:06 +02:00
eldritch horrors 14d539a274 libutil: return a program handle from runProgram2
this will let us also return a source for the program output later,
which will in turn make sinkToSource unnecessary for program output
processing. this may also reopen a path for provigin program input,
but that still needs a proper async io framework to avoid problems.

Change-Id: Iaf93f47db99c38cfaf134bd60ed6a804d7ddf688
2024-06-30 20:58:02 +02:00
eldritch horrors a5ae26726b enable -Werror=unused-result
we do not have any of these warnings appearing at the moment, but it
seems like a good idea to enable [[nodiscard]] checking anyway. once
we start introducing more functions with must-use conditions we will
need such checking, and the rust stdlib has proven them very useful.

Change-Id: Ibb6b042ae1ec5f527f8dc2809a7816a4c1548ae2
2024-06-30 20:51:10 +02:00
eldritch horrors 5f826bc600 libutil: convert readFileSource to a generator
Change-Id: I5f92b15fd367d46eb047d74ab6e317b4f51a46d3
2024-06-30 19:29:07 +02:00
eldritch horrors f659e93c5b libstore: convert dumpPath to a generator
Change-Id: Ic4cf5562504aa29130304469936f958c0426e5ef
2024-06-30 19:29:07 +02:00
eldritch horrors 1540bdbcfc libutil: allow construction of sources from generators
Change-Id: I78ff8d0720f06bce731e26d5e1c53b1382bbd589
2024-06-30 19:29:07 +02:00
eldritch horrors 379a892afb libutil: begin porting serialization to generators
generators are a better basis for serializers than streaming into sinks
as we do currently for many reasons, such as being usable as sources if
one wishes to (without requiring an intermediate sink to serialize full
data sets into memory, or boost coroutines to turn sinks into sources),
composing more naturally (as one can just yield a sub-generator instead
of being forced to wrap entire substreams into clunky functions or even
more clunky custom types to implement operator<< on), allowing wrappers
to transform data with clear ownership semantics (removing the need for
explicit memory allocations and Source wrappers), and many other things

Change-Id: I361d89ff556354f6930d9204f55117565f2f7f20
2024-06-30 19:29:06 +02:00
eldritch horrors 5f18b52274 libutil: convert drainFD to a Bytes generator
the `*Source` name is a slight misnomer since we do also have a
Source type, but we can probably live with this for time being.

Change-Id: I54eb2e59a4009014e324797f16b80b962759c7d3
2024-06-30 17:38:11 +02:00
eldritch horrors d96601fe55 libutil: allow draining Generator<Bytes> into sinks
Change-Id: I442d03a5399096d4baca9a2618b4c4b64db36c4b
2024-06-30 17:33:28 +02:00
eldritch horrors 2521f52465 libutil: add Bytes type
not used anywhere yet, but we'll use this a lot soon for generators that
return file contents, wire protocol fragments, or indeed any byte stream

Change-Id: I01a46f9bf9d75aaf4a5d7662773b99f498862a28
2024-06-30 17:30:34 +02:00
eldritch horrors 11307e04d1 libutil: generator type with on-yield value mapping
this will be the basis of non-boost coroutines in lix. anything that is
a boost coroutine *should* be representable with a Generator coroutine,
and many things that are not currently boost coroutines but behave much
like one (such as, notably, serializers) should be as well. this allows
us to greatly simplify many things that look like iteration but aren't.

Change-Id: I2cebcefa0148b631fb30df4c8cfa92167a407e34
2024-06-30 17:23:41 +02:00
2985 changed files with 95642 additions and 145365 deletions
+3 -4
View File
@@ -4,10 +4,9 @@ AccessModifierOffset: -4
AlignAfterOpenBracket: BlockIndent
AlignEscapedNewlines: Left
AlignOperands: DontAlign
AlignTrailingComments: false
AllowShortBlocksOnASingleLine: Empty
AllowShortBlocksOnASingleLine: Always
AllowShortFunctionsOnASingleLine: Empty
AllowShortIfStatementsOnASingleLine: Never
AllowShortIfStatementsOnASingleLine: WithoutElse
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: false
@@ -36,7 +35,7 @@ BreakAfterAttributes: Always
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeBraces: Custom
BreakConstructorInitializers: BeforeComma
ColumnLimit: 110
ColumnLimit: 100
EmptyLineAfterAccessModifier: Leave
EmptyLineBeforeAccessModifier: Leave
FixNamespaceComments: false
+2 -21
View File
@@ -8,30 +8,11 @@ Checks:
- -bugprone-narrowing-conversions
# kind of nonsense
- -bugprone-easily-swappable-parameters
# too many warnings for now
- -bugprone-implicit-widening-of-multiplication-result
# Lix's exception handling is Questionable
- -bugprone-empty-catch
# many warnings
- -bugprone-unchecked-optional-access
# many warnings, seems like a questionable lint
- -bugprone-branch-clone
# 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 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
ExtraArgs: ["-Werror=unnecessary-virtual-specifier"]
-8
View File
@@ -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
-15
View File
@@ -9,10 +9,6 @@ GTAGS
# ccls
/.ccls-cache
# auto-generated compilation database
compile_commands.json
rust-project.json
result
result-*
@@ -33,14 +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
# Yeah, I've got no clue.
/subprojects/.wraplock
-5
View File
@@ -1,5 +0,0 @@
Fiona Behrens <me@kloenk.dev>
Fiona Behrens <me@kloenk.dev> <me@kloenk.de>
rootile <lix@rootile.de>
rootile <lix@rootile.de> <commentator2.0@crystal-cavern.systems>
rootile <lix@rootile.de> <lix@crystal-cavern.systems>
Generated
-83
View File
@@ -1,83 +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 = "lixutil-rs"
version = "0.0.0"
[[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"
-6
View File
@@ -1,6 +0,0 @@
[workspace]
resolver = "2"
members = ["lix/lix-doc", "lix/libutil"]
[workspace.package]
edition = "2021"
-26
View File
@@ -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=*
+2 -5
View File
@@ -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
View File
@@ -1,4 +1,3 @@
bench-*.json
bench-*.md
perf-*.json
nixpkgs
-1
View File
@@ -1 +0,0 @@
*
-237
View File
@@ -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
View File
@@ -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
+325
View File
@@ -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";
}
+22
View File
@@ -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")
+90
View File
@@ -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
+21
View File
@@ -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;
};
};
+19
View File
@@ -0,0 +1,19 @@
#include <clang-tidy/ClangTidyModule.h>
#include <clang-tidy/ClangTidyModuleRegistry.h>
#include "FixIncludes.hh"
#include "HasPrefixSuffix.hh"
namespace nix::clang_tidy {
using namespace clang;
using namespace clang::tidy;
class NixClangTidyChecks : public ClangTidyModule {
public:
void addCheckFactories(ClangTidyCheckFactories &CheckFactories) override {
CheckFactories.registerCheck<HasPrefixSuffixCheck>("lix-hasprefixsuffix");
CheckFactories.registerCheck<FixIncludesCheck>("lix-fixincludes");
}
};
static ClangTidyModuleRegistry::Add<NixClangTidyChecks> X("lix-module", "Adds lix specific checks");
};
+56
View File
@@ -0,0 +1,56 @@
# Clang tidy lints for Lix
This is a skeleton of a clang-tidy lints library for Lix.
Currently there is one check (which is already obsolete as it has served its
goal and is there as an example), `HasPrefixSuffixCheck`.
## Running fixes/checks
One file:
```
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 .. -header-filter '\.\./src/.*\.h' -fix ../src | tee -a clang-tidy-result
```
## Resources
* https://firefox-source-docs.mozilla.org/code-quality/static-analysis/writing-new/clang-query.html
* https://clang.llvm.org/docs/LibASTMatchersReference.html
* https://devblogs.microsoft.com/cppblog/exploring-clang-tooling-part-3-rewriting-code-with-clang-tidy/
## Developing new checks
Put something like so in `myquery.txt`:
```
set traversal IgnoreUnlessSpelledInSource
# ^ Ignore implicit AST nodes. May need to use AsIs depending on how you are
# working.
set bind-root true
# ^ true unless you use any .bind("foo") commands
set print-matcher true
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 src/libcmd/installables.cc`.
With this you can iterate a query before writing it in C++ and suffering from
C++.
### Tips and tricks for the C++
There is a function `dump()` on many things that will dump to stderr. Also
`llvm::errs()` lets you print to stderr.
When I wrote `HasPrefixSuffixCheck`, I was not really able to figure out how
the structured replacement system was supposed to work. In principle you can
describe the replacement with a nice DSL. Look up the Stencil system in Clang
for details.
+13
View File
@@ -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
View File
@@ -1 +0,0 @@
*
-19
View File
@@ -1,19 +0,0 @@
# Darwin: don't link liblix* into plugins (host process provides them at runtime).
# Explicitly link curl so it binds to Nix-store libcurl, not /usr/lib/libcurl.
if is_darwin
plugin_deps = [
liblix.partial_dependency(includes : true, compile_args : true),
curl,
]
else
plugin_deps = [liblix, curl]
endif
plugin_mtls_store = shared_module(
'plugin_mtls_store',
'plugin_mtls_store.cc',
dependencies : plugin_deps,
install : false,
build_by_default : true,
link_args : is_darwin ? shared_module_link_args : strict_shared_module_link_args,
)
@@ -1,14 +0,0 @@
R"(
**Store URL format**: `https+mtls://...`
This store allows a binary cache to be accessed via HTTPS with mutual TLS (client certificate authentication).
Both parameters are required:
- `tls-certificate`, a path to the TLS client certificate
- `tls-private-key`, a path to the TLS private key backing the client certificate
If you don't need mTLS, use `https://` instead.
)"
-102
View File
@@ -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 the TLS client certificate in PEM format as expected by CURLOPT_SSLCERT"
};
PathsSetting<nix::Path> tlsKey{
this,
"",
"tls-private-key",
"Path of the 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);
}
const bool haveCert = !keyring->tlsCertificate.empty();
const bool haveKey = !keyring->tlsKey.empty();
if (!(haveCert && haveKey)) {
throw Error("https+mtls requires both tls-certificate and tls-private-key");
}
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>();
}
+9 -15
View File
@@ -1,15 +1,9 @@
let
lockFile = builtins.fromJSON (builtins.readFile ./flake.lock);
flake-compat-node = lockFile.nodes.${lockFile.nodes.root.inputs.flake-compat};
flake-compat = builtins.fetchTarball {
inherit (flake-compat-node.locked) url;
sha256 = flake-compat-node.locked.narHash;
};
flake = (
import flake-compat {
src = ./.;
}
);
in
flake.defaultNix
(import (
let
lock = builtins.fromJSON (builtins.readFile ./flake.lock);
in
fetchTarball {
url = "https://github.com/edolstra/flake-compat/archive/${lock.nodes.flake-compat.locked.rev}.tar.gz";
sha256 = lock.nodes.flake-compat.locked.narHash;
}
) { src = ./.; }).defaultNix
-1
View File
@@ -1 +0,0 @@
*
+27 -14
View File
@@ -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@"
+10 -36
View File
@@ -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,
+3 -3
View File
@@ -24,8 +24,8 @@ def map_contents_recursively(transformer):
def process_command:
.[0] as $context |
.[1] as $body |
# XXX FUTURE: drop sections once mdBook is at 0.5.0 or above in nixpkgs
$body | (.items? // .sections) |= map(map_contents_recursively(if $context.renderer == "html" then transform_anchors_html else transform_anchors_strip end))
;
$body + {
sections: $body.sections | map(map_contents_recursively(if $context.renderer == "html" then transform_anchors_html else transform_anchors_strip end)),
};
process_command
+8 -8
View File
@@ -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.
@@ -22,21 +23,20 @@ fold.level = 30
# not want to disable the links preprocessor entirely though because that requires
# disabling *all* built-in preprocessors and selectively reenabling those we want.
[preprocessor.substitute]
command = "python3 substitute.py"
command = "python3 doc/manual/substitute.py"
before = ["anchors", "links"]
[preprocessor.anchors]
renderers = ["html"]
command = "jq --from-file anchors.jq"
command = "jq --from-file doc/manual/anchors.jq"
[output.markdown]
# XXX FUTURE: may be reenabled once mdBook 0.5.0 or above and matching mdbook-linkchecker are in nixpkgs
#[output.linkcheck]
[output.linkcheck]
# no Internet during the build (in the sandbox)
#follow-web-links = false
follow-web-links = false
# mdbook-linkcheck does not understand [foo]{#bar} style links, resulting in
# excessive "Potential incomplete link" warnings. No other kind of warning was
# produced at the time of writing.
#warning-policy = "ignore"
warning-policy = "ignore"
-198
View File
@@ -12,10 +12,6 @@
forgejo: rbt
github: 9999years
9p4:
display_name: Ersei Saggi
github: 9p4
Artturin:
github: Artturin
@@ -40,72 +36,22 @@ 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
blokyk:
display_name: blokyk
github: blokyk
cole-h:
display_name: Cole Helbling
github: cole-h
delan:
display_name: 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
gustavderdrache:
github: gustavderdrache
horrors:
display_name: eldritch horrors
forgejo: pennae
@@ -114,62 +60,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
k900:
display_name: K900
forgejo: K900
github: K900
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
@@ -180,63 +78,19 @@ ma27:
matthewbauer:
github: matthewbauer
mic92:
github: mic92
midnightveil:
display_name: julia
forgejo: midnightveil
github: midnightveil
milibopp:
display_name: Emilia Bopp
forgejo: milibopp
github: milibopp
nan-git:
display_name: NaN-git
github: NaN-git
ncfavier:
github: ncfavier
nkk0:
github: nkk0
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
r-vdp:
github: r-vdp
@@ -249,29 +103,6 @@ roberth:
display_name: Robert Hensing
github: roberth
rootile:
display_name: rootile (Rutile)
forgejo: rootile
seppel3210:
github: Seppel3210
sterni:
forgejo: sterni
github: sternenseemann
stevalkr:
github: stevalkr
teofilc:
forgejo: teofilc
github: TeofilC
thubrecht:
display_name: Tom Hubrecht
forgejo: tom-hubrecht
github: Tom-Hubrecht
thufschmitt:
display_name: Théophane Hufschmitt
github: thufschmitt
@@ -284,38 +115,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
xyenon:
forgejo: xyenon
github: xyenon
yorickvp:
github: yorickvp
yshui:
github: yshui
zimbatm:
github: zimbatm
+37
View File
@@ -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))
+35
View File
@@ -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
View File
@@ -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)))
+13
View File
@@ -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)))
+59 -20
View File
@@ -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')
@@ -41,13 +86,9 @@ manual = custom_target(
'-euo', 'pipefail',
'-c',
'''
@0@ @INPUT0@ @3@ > @DEPFILE@
# Needs to be in lix/doc/manual for e.g. substitute.py
pushd @3@
@1@ build . -d @2@
popd
@0@ @INPUT0@ @CURRENT_SOURCE_DIR@ > @DEPFILE@
cd @SOURCE_ROOT@
@1@ build doc/manual -d @2@ | { grep -Fv "because fragment resolution isn't implemented" || :; }
rm -rf @2@/manual
mv @2@/html @2@/manual
find @2@/manual -iname meson.build -delete
@@ -55,7 +96,6 @@ manual = custom_target(
python.full_path(),
mdbook.full_path(),
meson.current_build_dir(),
meson.current_source_dir()
),
],
input : [
@@ -66,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,
@@ -78,19 +116,20 @@ manual = custom_target(
'manual',
'markdown',
],
install : true,
install_dir : [
datadir / 'doc/nix',
false,
],
depfile : 'manual.d',
env : {
'RUST_LOG': 'info',
'MANUAL_SUBSTITUTE_SEARCH': meson.current_build_dir() / 'src',
'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',
[
+1 -1
View File
@@ -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",
-10
View File
@@ -1,10 +0,0 @@
---
synopsis: "allow setting nested attributes via `--arg`/`--argstr`"
cls: [5338]
category: "Features"
credits: [ma27]
issues: [fj#496]
---
Passing `--arg config.allowUnfree true` to e.g. `nix-build` now results in `config` with value
`{ allowUnfree = true; }` passed to the expression.
+12
View File
@@ -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.
-10
View File
@@ -1,10 +0,0 @@
---
synopsis: "libexpr: allow empty attr-names in parseAttrPath if they are quoted"
cls: [5375]
category: "Miscellany"
credits: [ma27]
---
Empty strings are now allowed in attribute paths as consumed by e.g. `nix-build`.
I.e. `nix-build -A 'foo."".bar'` works now.
The quotes are necessary, i.e. `nix-build -A foo..bar` will throw an error.
-14
View File
@@ -1,14 +0,0 @@
---
synopsis: "builtins.break doesn't break expression anymore"
issues: [1165]
cls: [5422]
category: "Fixes"
credits: [blokyk]
---
Wrapping an expression in `builtins.break` used to break some builtins like
`map` and the `is*` functions, which could modify the execution path of code
inadvertently, made debugging nix harder than it already is, and in some cases
even crashed the interpreter. Now, using `break` should be completely
transparent to whatever function receives it as an input, preventing the
above-mentioned issues.
-9
View File
@@ -1,9 +0,0 @@
---
synopsis: "flake config warnings are now printed to stderr"
issues: [1155]
cls: [5379]
category: "Fixes"
credits: [lheckemann]
---
The settings listed in a flake-config confirmation prompt are now printed to stderr rather than stdout, which allows `nix print-dev-env` to emit valid bash again even in the presence of untrusted settings.
-10
View File
@@ -1,10 +0,0 @@
---
synopsis: "Lix now requires lowdown 1.4.0 or later"
issues: []
cls: [5374]
category: Packaging
credits: [sterni]
---
Support for linking against `lowdown < 1.4.0` has been removed from Lix since
all supported Nixpkgs channels distribute lowdown 2.0.4 or later.
@@ -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.
+12
View File
@@ -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.
@@ -1,11 +0,0 @@
---
synopsis: "Shadowing internal files through the Nix search path is now an error"
issues: [998]
cls: [4632, 5370]
category: "Breaking Changes"
credits: [thubrecht, jade, horrors]
---
As Lix uses the path `<nix/fetchurl.nix>` for bootstrapping purposes, the ability to shadow it by adding `nix=/some/path` (or `/other/path` that contains a `nix` directory) to the search path is not desirable.
Lix 2.95 deprecated this behavior with a warning, Lix 2.96 now turns it into a hard error if the `nix-path-shadow` deprecated feature isn't enabled. This deprecated feature is slated to be removed in Lix 2.98.
@@ -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,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.
-18
View File
@@ -1,18 +0,0 @@
---
synopsis: "Allow moving between stack frames relative to current debugger frame"
issues: [1156]
cls: [5411]
category: "Improvements"
credits: [blokyk]
---
Debugging functional programs often involve switching between a bunch of stack
frames to get the full context of what's happening and who's calling who.
Before this change, going up or down the stack in the nix debugger with `:st`
meant remembering the absolute index of each stack frame, instead of their
positions relative to one another; this got tiring *fast*.
Now, you can prepend `:st`'s argument with a + or - sign to indicate you want to
move relative to the current stack frame. For example, typing `:st +3` when you
were on frame `10` will go frame `13`; vice-versa, typing `:st -4` on frame `6`
will go to frame `2`.
-14
View File
@@ -1,14 +0,0 @@
---
synopsis: "invalid arguments to :st now print an error"
cls: [5386]
category: "Improvements"
credits: [blokyk]
---
When using the debugger, the `:st` command used to traverse the call stack would
silently fail and put the debugger in an invalid state if the argument given to
it wasn't a valid stack frame index.
This change adds an error message warning the user if the given index wasn't a
valid frame (telling them the range of valid indices), as well as if it wasn't
even a valid integer to begin with.
+10
View File
@@ -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).
+3 -11
View File
@@ -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,18 +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.95 (2026-03-13)](release-notes/rl-2.95.md)
- [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)
@@ -41,17 +41,104 @@ contains Nix.
> If you are building via the Lix daemon (default on Linux and macOS), it is the Lix daemon user account (that is, `root`) that should have SSH access to a user (not necessarily `root`) on the remote machine.
>
> Furthermore, `root` needs to have the public host keys for the remote system in its `.ssh/known_hosts`.
> To add them to `known_hosts` for root, do `ssh-keyscan HOST | sudo tee -a ~root/.ssh/known_hosts`.
> To add them to `known_hosts` for root, do `ssh-keyscan USER@HOST | sudo tee -a ~root/.ssh/known_hosts`.
>
> If you cant or dont want to configure `root` to be able to access the remote machine, you can use a private Nix store instead by passing e.g. `--store ~/my-nix` when running a Nix command from the local machine.
## Configuration
The list of remote machines can be specified on the command line or in
the Lix configuration file. The former is convenient for testing.
Additionally, there are two supported formats to configure remote builders:
The legacy, "space"-separated format and starting with Lix 2.95.0, a TOML.
the Lix configuration file. The former is convenient for testing. For
example, the following command allows you to build a derivation for
`x86_64-darwin` on a Linux machine:
```console
$ uname
Linux
$ nix build --impure \
--expr '(with import <nixpkgs> { system = "x86_64-darwin"; }; runCommand "foo" {} "uname > $out")' \
--builders 'ssh://mac x86_64-darwin'
[1/0/1 built, 0.0 MiB DL] building foo on ssh://mac
$ cat ./result
Darwin
```
It is possible to specify multiple builders separated by a semicolon or
a newline, e.g.
```console
--builders 'ssh://mac x86_64-darwin ; ssh://beastie x86_64-freebsd'
```
Each machine specification consists of the following elements, separated
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`, 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`.
2. A comma-separated list of Nix platform type identifiers, such as
`x86_64-darwin`. It is possible for a machine to support multiple
platform types, e.g., `i686-linux,x86_64-linux`. If omitted, this
defaults to the local platform type.
3. The SSH identity file to be used to log in to the remote machine. If
omitted, SSH will use its regular identities.
4. The maximum number of builds that Lix will execute in parallel on
the machine. Typically this should be equal to the number of CPU
cores. For instance, the machine `itchy` in the example will execute
up to 8 builds in parallel.
5. The “speed factor”, indicating the relative speed of the machine. If
there are multiple machines of the right type, Lix will prefer the
fastest, taking load into account.
6. A comma-separated list of *supported features*. If a derivation has
the `requiredSystemFeatures` attribute, then Lix will only perform
the derivation on a machine that has the specified features. For
instance, the attribute
```nix
requiredSystemFeatures = [ "kvm" ];
```
will cause the build to be performed on a machine that has the `kvm`
feature.
7. A comma-separated list of *mandatory features*. A machine will only
be used to build a derivation if all of the machines mandatory
features appear in the derivations `requiredSystemFeatures`
attribute.
8. The (base64-encoded) public host key of the remote machine. If omitted, SSH
will use its regular known-hosts file. Specifically, the field is calculated
via `base64 -w0 /etc/ssh/ssh_host_ed25519_key.pub`.
For example, the machine specification
nix@scratchy.labs.cs.uu.nl i686-linux /home/nix/.ssh/id_scratchy_auto 8 1 kvm
nix@itchy.labs.cs.uu.nl i686-linux /home/nix/.ssh/id_scratchy_auto 8 2
nix@poochie.labs.cs.uu.nl i686-linux /home/nix/.ssh/id_scratchy_auto 1 2 kvm benchmark
specifies several machines that can perform `i686-linux` builds.
However, `poochie` will only do builds that have the attribute
```nix
requiredSystemFeatures = [ "benchmark" ];
```
or
```nix
requiredSystemFeatures = [ "benchmark" "kvm" ];
```
`itchy` cannot do builds that require `kvm`, but `scratchy` does support
such builds. For regular builds, `itchy` will be preferred over
`scratchy` because it has a higher speed factor.
Remote builders can also be configured in `nix.conf`, e.g.
@@ -70,180 +157,3 @@ option `builders-use-substitutes` in your local `nix.conf`.
To build only on remote builders and disable building on the local
machine, you can use the option `--max-jobs 0`.
---
Each machine specification consists of the following attributes.
How those are combined within the configuration file differs for the formats, and will be explained further down.
1. `uri` (**required**)
The URI of the remote store in the format
`ssh[-ng]://[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[-ng]://nix@mac?port=1337`. The hostname
may be an alias defined in your `~/.ssh/config`.
2. `system-types` (**optional**)
A list of Nix platform type identifiers, such as
`x86_64-darwin`. It is possible for a machine to support multiple
platform types, e.g., `i686-linux` and `x86_64-linux`.
Defaults to the local platform type
3. `ssh-key` (**optional**)
The SSH identity file to be used to log in to the remote machine.
Defaults to SSHs regular identities.
4. `jobs` (**optional**)
The maximum number of builds that Lix will execute in parallel on
the machine. Typically, this should be equal to the number of CPU
cores divided by the cores within the target machines configuration, i.e. `jobs * cores ~= cpu cores`
Defaults to 1; must be a positive integer.
5. `speed-factor`
The “speed factor”, indicating the relative speed of the machine. If
there are multiple machines of the right type, Lix will prefer the
fastest, taking load into account.
Defaults to 1; must be a positive float.
6. `supported-features` (**optional**)
A list of *supported features*. If a derivation has
the `requiredSystemFeatures` attribute, then Lix will only schedule
the derivation on a machine that has the specified features. For
example, the attribute
```nix
requiredSystemFeatures = [ "kvm" ];
```
will cause the build to be performed on a machine that has the `kvm`
feature.
Defaults to an empty list.
7. `mandatory-features` (**optional**)
A list of *mandatory features*. A machine will only
be used to build a derivation if all the machines mandatory
features appear in the derivations `requiredSystemFeatures`
attribute.
Defaults to an empty list.
8. `ssh-public-host-key` (**optional**)
The public host key of the remote machine.
Defaults to basic ssh behavior (checking contents of the known-hosts file)
### Using a TOML configuration
Each machine is configured as an attribute within the map called `machines`.
The attributes name is the machines name.
Attributes can be in any order.
For example:
```toml
version = 1
[machines.andesite]
uri = "ssh://lix@andesite.lix.systems" # toml also allows for comments
system-types = ["i686-linux"]
jobs = 8
speed-factor = 1.0
supported-features = ["kvm"]
ssh-key = "/home/deepslate/.ssh/id_ed25519"
[machines.diorite]
uri = "ssh://lix@diorite.lix.systems"
system-types = ["i686-linux"]
jobs = 8
speed-factor = 2.0
ssh-key = "/home/deepslate/.ssh/id_ed25519"
[machines.granite]
uri = "ssh://lix@granite.lix.systems"
system-types = ["i686-linux"]
jobs = 1
speed-factor = 2.0
supported-features = ["kvm", "benchmark"]
ssh-key = "/home/deepslate/.ssh/id_ed25519"
[machines.legacy]
uri = "ssh://nix@nix-15-11.nixos.org"
enable = false
```
> **Note**
>
> If the version tag is omitted (e.g. in the CLI), it defaults to the latest version.
> It is strongly recommended to always provide a version tag for configuration within files to avoid breakage.
For testing purposes, one can also define a builder ad hoc on the CLI as follows:
`--builders 'machines.andesite = {uri = "ssh://lix@andesite.lix.systems", jobs = 8}'`
#### Special handling of fields
- `enable` (**optional**)
If set to false, the declared machine will not be loaded.
This allows one to statically disable machines.
Defaults to true
### Using the legacy format
> **Warning**
>
> This format is frozen and new features / configuration options will not be backported to this format.
It is possible to specify multiple builders separated by a semicolon or
a newline, e.g.
```console
--builders 'ssh://mac x86_64-darwin ; ssh://beastie x86_64-freebsd'
```
Every machine specification consists of the elements listed in the section above, seperated by any amount of spaces or tabs.
The Attributes need to be provided **in order** and without names.
To leave a field at its default, set it to `-`.
Lists are colon seperated, without additional spaces.
```
lix@andesite.lix.systems i686-linux /home/deepslate/.ssh/id_ed25519 8 1 kvm
lix@diorite.lix.systems i686-linux /home/deepslate/.ssh/id_ed25519 8 2
lix@granite.lix.systems i686-linux /home/deepslate/.ssh/id_ed25519 1 2 kvm benchmark
```
#### Special handling of fields
- `uri`: Due to backward compatibility, the `ssh://` may be omitted for the store-uri.
- `ssh-public-host-key`: The key must be provided encoded in base64. Specifically calculated via `base64 -w0 /etc/ssh/ssh_host_ed25519_key.pub`
### Format detection
At first, the given configuration is being parsed syntactically as a toml.
If parsing fails and the given configuration contains a `"` the error is presented to the user, as those characters are necessary for TOML, but disallowed for the legacy format.
Otherwise, parsing is retried using the legacy format.
If non-syntactic errors are detected within the toml, the exception will always be shown to the user directly.
## Builder selection
The configuration(s) above specify several machines that can perform `i686-linux` builds.
However, `granite` will only do builds that have the attribute
```nix
requiredSystemFeatures = [ "benchmark" ];
```
or
```nix
requiredSystemFeatures = [ "benchmark" "kvm" ];
```
`diorite` cannot do builds that require `kvm`, but `andesite` does support
such builds. For regular builds, `diorite` will be preferred over
`andesite` because it has a higher speed factor.
-19
View File
@@ -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)
+3 -3
View File
@@ -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 |
| | | | |
+1 -7
View File
@@ -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.
+28 -15
View File
@@ -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,
)
+7 -43
View File
@@ -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
+4 -4
View File
@@ -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 -->
+1 -1
View File
@@ -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.
+9 -31
View File
@@ -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
+4 -3
View File
@@ -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 wont 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.
+1 -7
View File
@@ -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`
@@ -177,12 +177,6 @@ Most commands in Lix accept the following command-line options:
You can override this using `--arg`, e.g., `nix-env --install --attr pkgname --arg system \"i686-freebsd\"`.
(Note that since the argument is a Nix string literal, you have to escape the quotes.)
Additionally, dots are interpreted as attribute-path separators.
I.e. `nix-instantiate '<nixpkgs>' -A hello-unfree --arg config.allowUnfree true` will result in an argument `config` with value `{ allowUnfree = true; }` being passed to `<nixpkgs>`.
Please note that merging of different arguments is rejected.
I.e. `--arg config '{ cudaSupport = true; }' --arg config.allowUnfree true` will not work whereas `--arg config.cudaSupport true --arg config.allowUnfree true` is accepted.
- <span id="opt-argstr">[`--argstr`](#opt-argstr)</span> *name* *value*
This option is like `--arg`, only the value is not a Nix expression but a string.
+2 -2
View File
@@ -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}}
+24 -227
View File
@@ -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,64 +39,17 @@ $ nix-shell -A native-clangStdenvPackages
### Building from the development shell
We have a [justfile](just.systems) for extra convenient building.
It defaults to using `./build` as the build directory, and `$out` (`./outputs/out`) as the install directory.
For most cases, you can clean-build, install, and run the tests with:
```bash
$ just setup --wipe && just test
```
> **Note**
>
> The `--wipe` argument to `meson setup` conveniently works whether you have an existing build directory or not.
>
> However, it is *mostly*, but not *exactly* equivalent to deleting the build directory first.
> In particular, previously specified `-D` build options are **preserved** with `--wipe` (for some reason).
> For example, if you fetch and checkout a new version of Lix, and that new version *removes* a Meson build option from `./meson.options`, *and* a previous invocation in that build directory explicitly set that option, then `meson setup --wipe build` will error, complaining about the unknown option.
> For these cases, `just clean` will give you a well-and-truly-this-time-for-real clean build.
Because the integration tests require installation to work, `just test` automatically also calls `just install`, and Meson helpfully will automatically build any targets that need building when trying to install them.
You can override the build directory or install directory by setting the justfile [variables](https://just.systems/man/en/setting-variables-from-the-command-line.html) `outdir` and `builddir` on the command-line:
```bash
$ just builddir=build-before-bisect outdir=out-before-bisect setup
$ just builddir=build-before-bisect test
```
You'll have to set `builddir` for every target, but `outdir` only needs to be set for `setup`.
You can also run the unit tests and integration tests separately:
You can build and test Lix with just:
```bash
$ just setup
$ just test-unit
$ just test-integration
$ just build
$ just test --suite=check
$ just install
$ just test --suite=installcheck
```
Most justfile targets forward all further arguments to the underlying Meson invocation.
For example, to work on both Lix and nix-eval-jobs you can run:
```bash
$ just setup -Dnix-eval-jobs=enabled
```
Note that only targets which *don't* accept extra arguments can have other targets following them.
`just clean setup` is equivalent to `just clean && just setup`, but `just build test` runs the `build` target with the argument `test`.
This means that if you want to, for example, build with lower parallelism, and then test, you will have to do something like this:
```bash
$ just build -j4
$ just test
```
Finally, the rewrite of the integration test suite, functional2, also has its own justfile target which allows passing extra arguments to pytest.
For example, to collect and list all functional2 tests without running them, you can pass pytest's `--collect-only` argument:
```bash
$ just test-functional2 --collect-only
```
(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:
@@ -161,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:
@@ -177,59 +118,7 @@ To inspect the canonical source of truth on what the state of the buildsystem co
$ meson introspect
```
#### LLD
The development shell on Linux uses LLD by default for faster link times.
This is set using `mesonFlags`, so to override it, you can simplify re-specify the linker to Meson:
```bash
$ just setup-custom -Dc_link_args=-fuse-ld=ld -Dcpp_link_args=-fuse-ld=ld
```
While using LLD, you may find it helpful to use ThinLTO for even further improvements to link times for incremental builds:
```bash
$ just setup-custom -Db_lto=true -Db_lto_mode=thin -Db_thinlto_cache=true
```
## 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:
@@ -252,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`
@@ -287,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:
@@ -329,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 |
|----------------------------|---------------------|
@@ -356,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`.
@@ -386,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
@@ -401,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
@@ -444,21 +326,9 @@ You can build it yourself:
# xdg-open ./result/coverage/index.html
```
Or, in a dev shell, set `-Dcoverage=true` when running `meson setup`.
Coverage data goes into `build/profraw` when you run executables in the dev shell.
Then, run `ninja -C build coverage-report` to produce an HTML report of coverage in `build/coverage/index.html` alongside a LLVM `.lcov` file.
> [!NOTE]
> We use the [llvm source-based coverage], which has better precision than using clang with gcov, which is debuginfo based (but likely worse performance, which is fine).
>
> It should be noted that Meson [allegedly has coverage support][meson-coverage], but it only supports gcov-style coverage, so we don't use it.
[llvm source-based coverage]: https://clang.llvm.org/docs/SourceBasedCodeCoverage.html
[meson-coverage]: https://mesonbuild.com/Unit-tests.html#coverage
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.
@@ -527,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.
+15
View File
@@ -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',
)
+16 -18
View File
@@ -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,13 +375,10 @@ 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
- `LIX_DAEMON_SOCKET_DIR` (optional) - Overrides the daemon socket directory from `$NIX_STATE_DIR/daemon-socket`.
**Expected value**: a directory
- `NIX_DAEMON_SOCKET_PATH` (optional) - Overrides the daemon socket path from `$NIX_STATE_DIR/daemon-socket/socket`. Ignored if `LIX_DAEMON_SOCKET_DIR` is set.
- `NIX_DAEMON_SOCKET_PATH` (optional) - Overrides the daemon socket path from `$NIX_STATE_DIR/daemon-socket/socket`.
**Expected value**: path to a socket
- `NIX_LOG_FD` (output) - An FD number for logs in `internal-json` format to be sent to.
@@ -404,6 +396,7 @@ I grepped `lix/` for `get[eE]nv\("` to find the mentions in Lix code.
**Expected value**: the path to an executable shell
- `PRINT_PATH` - Undocumented. Used by `nix-prefetch-url` as an alternative form of `--print-path`. Why???
- `_NIX_IN_TEST` - If present with any value, makes `fetchClosure` accept file URLs in addition to HTTP ones. Why is this not `_NIX_FORCE_HTTP`??
Not used anywhere else.
- `NIX_ALLOW_EVAL` - Used by eval-cache tests to block evaluation if set to `0`.
@@ -435,12 +428,14 @@ 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.
- `NIX_SSHOPTS` - Options passed to `ssh(1)` when using a ssh remote store.
Incorrectly documented on `nix-copy-closure` which is *surely* not the only place they are used??
- `_NIX_TEST_NO_LSOF` - Used on non-Linux, non-macOS platforms to disable using `lsof` when finding gc roots.
Since https://git.lix.systems/lix-project/lix/issues/156 was fixed, this should probably just be removed as it was a bad workaround for a macOS issue.
- `_NIX_TEST_GC_SYNC_1` - Path to a pipe that is used to block the GC briefly to validate invariants from the test suite.
- `_NIX_TEST_GC_SYNC_2` - Path to a pipe that is used to block the GC briefly to validate invariants from the test suite.
- `_NIX_TEST_FREE_SPACE_FILE` - Path to a file containing a decimal number with the free space that the GC is to believe it has.
@@ -457,6 +452,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`.
+11 -4
View File
@@ -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
@@ -89,13 +95,13 @@
[store path]: #gloss-store-path
- [file system object]{#gloss-file-system-object}
- [file system object]{#gloss-store-object}
The Nix data model for representing simplified file system data.
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.
+1 -4
View File
@@ -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
+1 -1
View File
@@ -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.
+13 -9
View File
@@ -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.
+1 -1
View File
@@ -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>
+1 -1
View File
@@ -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>
-6
View File
@@ -17,12 +17,6 @@ the attributes of which specify the inputs of the build.
string. This is used as a symbolic name for the package by
`nix-env`, and it is appended to the output paths of the derivation.
> **Note**
>
> Names can only contain alphanumerical characters (0-9, a-z, A-Z)
> as well as `+`, `-`, `.`, `_`, `?` and `=`. Names must be neither
> `.` nor `..`, and must not start with `.-` or `..-`.
- There must be an attribute named [`builder`]{#attr-builder} that identifies the
program that is executed to perform the build. It can be either a
derivation or a source (a local file reference, e.g.,
+27
View File
@@ -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,
)
+6 -92
View File
@@ -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
+16 -16
View File
@@ -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* \
@@ -5,7 +5,7 @@
FIXME(Lix): This section does not document the most common modern practices in terms of avoiding channels, pinning, declarative software installation (see flakey-profile or home-manager or NixOS), or using flakes, etc.
It is, however, likely correct at a technical level.
For more information on modern practices, see the [resources](https://wiki.lix.systems/books/lix-users/page/nix-resources) page on the Lix site.
For more information on modern practices, see the [resources](https://lix.systems/resources) page on the Lix site.
</div>
@@ -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, youre 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**
>

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