Compare commits
178
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45623f077f | ||
|
|
f402c45cfa | ||
|
|
73507a7167 | ||
|
|
6165f21074 | ||
|
|
2d3fd6b9ab | ||
|
|
dd06f9b792 | ||
|
|
c777dcd1ae | ||
|
|
0b6d353474 | ||
|
|
862f20a4ba | ||
|
|
620de98d0c | ||
|
|
4b730f328e | ||
|
|
2041bdac2d | ||
|
|
5956f509b6 | ||
|
|
351c1a9c52 | ||
|
|
bfbcc3352b | ||
|
|
65d544b1a6 | ||
|
|
2a98ba8b97 | ||
|
|
194a1b91af | ||
|
|
99f159c536 | ||
|
|
1fa6a3e335 | ||
|
|
a4f5bb951d | ||
|
|
0b4e738944 | ||
|
|
817322fbfb | ||
|
|
a5a25894c1 | ||
|
|
5a54b0a20c | ||
|
|
e28dc26084 | ||
|
|
1da1f501fc | ||
|
|
6646b80396 | ||
|
|
9d97d1cb68 | ||
|
|
877750b7c5 | ||
|
|
6e5db5e4a2 | ||
|
|
69bfd21e20 | ||
|
|
86b954a7af | ||
|
|
f9d5079c69 | ||
|
|
236bc046ba | ||
|
|
55350bd68d | ||
|
|
5ec2efb686 | ||
|
|
62332c1250 | ||
|
|
81e50fef70 | ||
|
|
61d394e344 | ||
|
|
ae065a992d | ||
|
|
14207e1cf8 | ||
|
|
ffbad9b762 | ||
|
|
80405d0626 | ||
|
|
038daad218 | ||
|
|
edba570664 | ||
|
|
412a9c9f67 | ||
|
|
50c6feeb77 | ||
|
|
0436f4cfa6 | ||
|
|
279e30e7ef | ||
|
|
8fd02df90d | ||
|
|
aee3d639b5 | ||
|
|
8e63eca912 | ||
|
|
da22dbc333 | ||
|
|
fa3088a878 | ||
|
|
a5254186fd | ||
|
|
207d24da4e | ||
|
|
312cee142a | ||
|
|
80b66b5065 | ||
|
|
531b8d0ab8 | ||
|
|
7170e9f947 | ||
|
|
a69f6e185a | ||
|
|
73624f7d9c | ||
|
|
e1ffe56793 | ||
|
|
86881226b0 | ||
|
|
c3a5f937d3 | ||
|
|
787c4397f1 | ||
|
|
1da1aa5045 | ||
|
|
aa7653608d | ||
|
|
b525d0f20c | ||
|
|
3d065192c0 | ||
|
|
4494f9097f | ||
|
|
d3d7489571 | ||
|
|
ad8a4b380e | ||
|
|
5a1c35f907 | ||
|
|
dee6b75702 | ||
|
|
185ecf1f45 | ||
|
|
c856b82c2e | ||
|
|
3e428f2289 | ||
|
|
33da9c09c8 | ||
|
|
946fc12e4e | ||
|
|
652f52f071 | ||
|
|
8044540c42 | ||
|
|
b4d07656ff | ||
|
|
a7161b6c0f | ||
|
|
fab55aff0e | ||
|
|
22e3f0e987 | ||
|
|
5a28d70d1e | ||
|
|
d9a83886f9 | ||
|
|
4050245faa | ||
|
|
985bd5eb9f | ||
|
|
20b4a97af3 | ||
|
|
30233d87f9 | ||
|
|
81be5eb7c6 | ||
|
|
6b0020749d | ||
|
|
f38ae92a38 | ||
|
|
0f518f44e2 | ||
|
|
afb839a0c9 | ||
|
|
37c4b10c44 | ||
|
|
b3599166ad | ||
|
|
47a237f7ec | ||
|
|
86a1121d16 | ||
|
|
c39150e6bb | ||
|
|
4c072c7c5f | ||
|
|
9cf92c012d | ||
|
|
d826427f02 | ||
|
|
314f044c2b | ||
|
|
1f8b85786e | ||
|
|
2890840b96 | ||
|
|
61e21b2557 | ||
|
|
706cee5c49 | ||
|
|
32d6e58069 | ||
|
|
886a418d23 | ||
|
|
11f35afa6f | ||
|
|
3392020710 | ||
|
|
e257ff10fd | ||
|
|
3c52344300 | ||
|
|
7abbce500b | ||
|
|
0d85875c3a | ||
|
|
7d361f1a82 | ||
|
|
af066af7f3 | ||
|
|
78513b1fc8 | ||
|
|
8a8715af89 | ||
|
|
18ed6c3bdf | ||
|
|
38571c50e6 | ||
|
|
84727bebb4 | ||
|
|
9f242fae76 | ||
|
|
caded0d55e | ||
|
|
c79b5dca2a | ||
|
|
cc55da201b | ||
|
|
93cc063344 | ||
|
|
c26599b143 | ||
|
|
0278c03de5 | ||
|
|
2a8f579c53 | ||
|
|
ab5ff86917 | ||
|
|
06952cf7c4 | ||
|
|
da2f165128 | ||
|
|
1b8662b85c | ||
|
|
be2b87ed4d | ||
|
|
b06a392114 | ||
|
|
dd05106d1c | ||
|
|
df2723b972 | ||
|
|
d9367da027 | ||
|
|
f9701da8f6 | ||
|
|
50c401b4c1 | ||
|
|
36a8d151e1 | ||
|
|
529a01ade2 | ||
|
|
b072c069b7 | ||
|
|
4ad3446311 | ||
|
|
875b76d0c7 | ||
|
|
15380b4c6e | ||
|
|
1758a6ef25 | ||
|
|
95a87f2c2a | ||
|
|
45f6e3521a | ||
|
|
af515baf6e | ||
|
|
8be7030299 | ||
|
|
6432bf9197 | ||
|
|
0a4737f519 | ||
|
|
06764118ea | ||
|
|
b667b4cded | ||
|
|
71e0114708 | ||
|
|
2a84123631 | ||
|
|
bf19eebb9b | ||
|
|
1cf0fa0633 | ||
|
|
03f852b2c6 | ||
|
|
3e43f4aeff | ||
|
|
0c19e6b56c | ||
|
|
7c882a5075 | ||
|
|
34fb7a7e9d | ||
|
|
a9b813cc3b | ||
|
|
f2e11ddce1 | ||
|
|
030c8aa833 | ||
|
|
992d99592f | ||
|
|
6b11c2cd70 | ||
|
|
73cdaf44cf | ||
|
|
4dabde0485 | ||
|
|
1958152d14 | ||
|
|
6ef9d8efba |
@@ -0,0 +1,50 @@
|
||||
---
|
||||
BasedOnStyle: LLVM
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: BlockIndent
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: DontAlign
|
||||
AllowShortBlocksOnASingleLine: Always
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
AllowShortIfStatementsOnASingleLine: WithoutElse
|
||||
AlwaysBreakBeforeMultilineStrings: true
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BitFieldColonSpacing: None
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: true
|
||||
AfterControlStatement: MultiLine
|
||||
AfterEnum: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: true
|
||||
AfterUnion: true
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: false
|
||||
SplitEmptyNamespace: true
|
||||
BreakAfterAttributes: Always
|
||||
BreakBeforeBinaryOperators: NonAssignment
|
||||
BreakBeforeBraces: Custom
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
ColumnLimit: 100
|
||||
EmptyLineAfterAccessModifier: Leave
|
||||
EmptyLineBeforeAccessModifier: Leave
|
||||
FixNamespaceComments: false
|
||||
IndentWidth: 4
|
||||
InsertBraces: true
|
||||
InsertTrailingCommas: Wrapped
|
||||
LambdaBodyIndentation: Signature
|
||||
PackConstructorInitializers: CurrentLine
|
||||
PointerAlignment: Middle
|
||||
SortIncludes: Never
|
||||
SpaceAfterCStyleCast: true
|
||||
SpaceAfterTemplateKeyword: false
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
UseColor: true
|
||||
Checks:
|
||||
- -*
|
||||
- bugprone-*
|
||||
# too many warnings
|
||||
- -bugprone-assignment-in-if-condition
|
||||
# too many warnings
|
||||
- -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
|
||||
@@ -0,0 +1,9 @@
|
||||
# shellcheck shell=bash
|
||||
source_env_if_exists .envrc.local
|
||||
# TODO: `use flake .#native-clangStdenvPackages` on macOS?
|
||||
use flake ".#${LIX_SHELL_VARIANT:-default}" "${LIX_SHELL_EXTRA_ARGS[@]}"
|
||||
export MAKEFLAGS="$MAKEFLAGS -e"
|
||||
if [[ -n "$NIX_BUILD_CORES" ]]; then
|
||||
export MAKEFLAGS="$MAKEFLAGS -j $NIX_BUILD_CORES"
|
||||
fi
|
||||
export GTEST_BRIEF=1
|
||||
@@ -7,30 +7,26 @@ assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
## Describe the bug
|
||||
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
If you have a problem with a specific package or NixOS,
|
||||
you probably want to file an issue at https://github.com/NixOS/nixpkgs/issues.
|
||||
|
||||
**Steps To Reproduce**
|
||||
## Steps To Reproduce
|
||||
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
## Expected behavior
|
||||
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**`nix-env --version` output**
|
||||
## `nix --version` output
|
||||
|
||||
**Additional context**
|
||||
## Additional context
|
||||
|
||||
Add any other context about the problem here.
|
||||
|
||||
**Priorities**
|
||||
|
||||
Add :+1: to [issues you find important](https://github.com/NixOS/nix/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc).
|
||||
|
||||
@@ -7,18 +7,18 @@ assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
## Is your feature request related to a problem? Please describe.
|
||||
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
## Describe the solution you'd like
|
||||
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
## Describe alternatives you've considered
|
||||
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
## Additional context
|
||||
|
||||
Add any other context or screenshots about the feature request here.
|
||||
|
||||
**Priorities**
|
||||
|
||||
Add :+1: to [issues you find important](https://github.com/NixOS/nix/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc).
|
||||
|
||||
@@ -30,7 +30,3 @@ assignees: ''
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
## Priorities
|
||||
|
||||
Add :+1: to [issues you find important](https://github.com/NixOS/nix/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc).
|
||||
|
||||
@@ -25,7 +25,3 @@ assignees: ''
|
||||
[latest Nix manual]: https://nixos.org/manual/nix/unstable/
|
||||
[source]: https://github.com/NixOS/nix/tree/master/doc/manual/src
|
||||
[open documentation issues and pull requests]: https://github.com/NixOS/nix/labels/documentation
|
||||
|
||||
## Priorities
|
||||
|
||||
Add :+1: to [issues you find important](https://github.com/NixOS/nix/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc).
|
||||
|
||||
@@ -9,7 +9,3 @@
|
||||
<!-- Invasive change: Discuss alternative designs or approaches you considered. -->
|
||||
|
||||
<!-- Large change: Provide instructions to reviewers how to read the diff. -->
|
||||
|
||||
# Priorities
|
||||
|
||||
Add :+1: to [pull requests you find important](https://github.com/NixOS/nix/pulls?q=is%3Aopen+sort%3Areactions-%2B1-desc).
|
||||
|
||||
@@ -17,4 +17,3 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- run: bash scripts/check-hydra-status.sh
|
||||
|
||||
|
||||
@@ -146,9 +146,18 @@ result
|
||||
result-*
|
||||
|
||||
.vscode/
|
||||
.direnv/
|
||||
.envrc.local
|
||||
|
||||
# clangd and possibly more
|
||||
.cache/
|
||||
|
||||
# Mac OS
|
||||
.DS_Store
|
||||
|
||||
# ClangBuildAnalyzer output, see maintainers/buildtime_report.sh
|
||||
buildtime.bin
|
||||
|
||||
.envrc.local
|
||||
# We generate this with a Nix shell hook
|
||||
/.pre-commit-config.yaml
|
||||
|
||||
@@ -55,7 +55,7 @@ modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
@@ -111,7 +111,7 @@ modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
@@ -158,7 +158,7 @@ Library.
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
@@ -216,7 +216,7 @@ instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
@@ -267,7 +267,7 @@ Library will still fall under Section 6.)
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
@@ -329,7 +329,7 @@ restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
@@ -370,7 +370,7 @@ subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
@@ -422,7 +422,7 @@ conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
@@ -456,7 +456,7 @@ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
@@ -500,5 +500,3 @@ necessary. Here is a sample; alter the names:
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
||||
|
||||
|
||||
@@ -20,8 +20,7 @@ makefiles = \
|
||||
misc/fish/local.mk \
|
||||
misc/zsh/local.mk \
|
||||
misc/systemd/local.mk \
|
||||
misc/launchd/local.mk \
|
||||
misc/upstart/local.mk
|
||||
misc/launchd/local.mk
|
||||
endif
|
||||
|
||||
ifeq ($(ENABLE_BUILD)_$(ENABLE_TESTS), yes_yes)
|
||||
@@ -41,6 +40,7 @@ makefiles += \
|
||||
tests/functional/ca/local.mk \
|
||||
tests/functional/dyn-drv/local.mk \
|
||||
tests/functional/test-libstoreconsumer/local.mk \
|
||||
tests/functional/repl_characterization/local.mk \
|
||||
tests/functional/plugins/local.mk
|
||||
else
|
||||
makefiles += \
|
||||
@@ -60,7 +60,7 @@ endif
|
||||
OPTIMIZE = 1
|
||||
|
||||
ifeq ($(OPTIMIZE), 1)
|
||||
GLOBAL_CXXFLAGS += -O3 $(CXXLTO)
|
||||
GLOBAL_CXXFLAGS += -O2 $(CXXLTO)
|
||||
GLOBAL_LDFLAGS += $(CXXLTO)
|
||||
else
|
||||
GLOBAL_CXXFLAGS += -O0 -U_FORTIFY_SOURCE
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
BasedOnStyle: llvm
|
||||
@@ -0,0 +1,80 @@
|
||||
#include "HasPrefixSuffix.hh"
|
||||
#include <clang/AST/ASTTypeTraits.h>
|
||||
#include <clang/AST/Expr.h>
|
||||
#include <clang/AST/PrettyPrinter.h>
|
||||
#include <clang/AST/Type.h>
|
||||
#include <clang/ASTMatchers/ASTMatchers.h>
|
||||
#include <clang/Basic/Diagnostic.h>
|
||||
#include <clang/Frontend/FrontendAction.h>
|
||||
#include <clang/Frontend/FrontendPluginRegistry.h>
|
||||
#include <clang/Tooling/Transformer/SourceCode.h>
|
||||
#include <clang/Tooling/Transformer/SourceCodeBuilders.h>
|
||||
#include <iostream>
|
||||
|
||||
namespace nix::clang_tidy {
|
||||
using namespace clang::ast_matchers;
|
||||
using namespace clang;
|
||||
|
||||
void HasPrefixSuffixCheck::registerMatchers(ast_matchers::MatchFinder *Finder) {
|
||||
Finder->addMatcher(
|
||||
traverse(clang::TK_AsIs,
|
||||
callExpr(callee(functionDecl(anyOf(hasName("hasPrefix"),
|
||||
hasName("hasSuffix")))
|
||||
.bind("callee-decl")),
|
||||
optionally(hasArgument(
|
||||
0, cxxConstructExpr(
|
||||
hasDeclaration(functionDecl(hasParameter(
|
||||
0, parmVarDecl(hasType(
|
||||
asString("const char *")))))))
|
||||
.bind("implicit-cast"))))
|
||||
.bind("call")),
|
||||
this);
|
||||
}
|
||||
|
||||
void HasPrefixSuffixCheck::check(
|
||||
const ast_matchers::MatchFinder::MatchResult &Result) {
|
||||
|
||||
const auto *CalleeDecl = Result.Nodes.getNodeAs<FunctionDecl>("callee-decl");
|
||||
auto FuncName = std::string(CalleeDecl->getName());
|
||||
std::string NewName;
|
||||
if (FuncName == "hasPrefix") {
|
||||
NewName = "starts_with";
|
||||
} else if (FuncName == "hasSuffix") {
|
||||
NewName = "ends_with";
|
||||
} else {
|
||||
llvm_unreachable("nix-has-prefix: invalid callee");
|
||||
}
|
||||
|
||||
const auto *MatchedDecl = Result.Nodes.getNodeAs<CallExpr>("call");
|
||||
const auto *ImplicitConvertArg =
|
||||
Result.Nodes.getNodeAs<CXXConstructExpr>("implicit-cast");
|
||||
|
||||
const auto *Lhs = MatchedDecl->getArg(0);
|
||||
const auto *Rhs = MatchedDecl->getArg(1);
|
||||
auto Diag = diag(MatchedDecl->getExprLoc(), FuncName + " is deprecated");
|
||||
|
||||
std::string Text = "";
|
||||
|
||||
// Form possible cast to string_view, or nothing.
|
||||
if (ImplicitConvertArg) {
|
||||
Text = "std::string_view(";
|
||||
Text.append(tooling::getText(*Lhs, *Result.Context));
|
||||
Text.append(").");
|
||||
} else {
|
||||
Text.append(*tooling::buildAccess(*Lhs, *Result.Context));
|
||||
}
|
||||
|
||||
// Call .starts_with.
|
||||
Text.append(NewName);
|
||||
Text.push_back('(');
|
||||
Text.append(tooling::getText(*Rhs, *Result.Context));
|
||||
Text.push_back(')');
|
||||
|
||||
Diag << FixItHint::CreateReplacement(MatchedDecl->getSourceRange(), Text);
|
||||
|
||||
// for (const auto *arg : MatchedDecl->arguments()) {
|
||||
// arg->dumpColor();
|
||||
// arg->getType().dump();
|
||||
// }
|
||||
}
|
||||
}; // namespace nix::clang_tidy
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
///@file
|
||||
/// This is an example of a clang-tidy automated refactoring against the Nix
|
||||
/// codebase. The refactoring has been completed in
|
||||
/// https://gerrit.lix.systems/c/lix/+/565 so this code is around as
|
||||
/// an example.
|
||||
|
||||
#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;
|
||||
using namespace llvm;
|
||||
|
||||
class HasPrefixSuffixCheck : public ClangTidyCheck {
|
||||
public:
|
||||
HasPrefixSuffixCheck(StringRef Name, ClangTidyContext *Context)
|
||||
: ClangTidyCheck(Name, Context) {}
|
||||
void registerMatchers(ast_matchers::MatchFinder *Finder) override;
|
||||
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
|
||||
};
|
||||
}; // namespace nix::clang_tidy
|
||||
@@ -0,0 +1,17 @@
|
||||
#include <clang-tidy/ClangTidyModule.h>
|
||||
#include <clang-tidy/ClangTidyModuleRegistry.h>
|
||||
#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>("nix-hasprefixsuffix");
|
||||
}
|
||||
};
|
||||
|
||||
static ClangTidyModuleRegistry::Add<NixClangTidyChecks> X("nix-module", "Adds nix specific checks");
|
||||
};
|
||||
@@ -0,0 +1,56 @@
|
||||
# Clang tidy lints for Nix
|
||||
|
||||
This is a skeleton of a clang-tidy lints library for Nix.
|
||||
|
||||
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='-*,nix-*' --load=build/libnix-clang-tidy.so -p ../compile_commands.json --fix ../src/libcmd/installables.cc
|
||||
```
|
||||
|
||||
Several files, in parallel:
|
||||
|
||||
```
|
||||
ninja -C build && run-clang-tidy -checks='-*,nix-*' -load=build/libnix-clang-tidy.so -p .. -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.
|
||||
@@ -0,0 +1,8 @@
|
||||
project('nix-clang-tidy', ['cpp', 'c'],
|
||||
version : '0.1',
|
||||
default_options : ['warning_level=3', 'cpp_std=c++20'])
|
||||
|
||||
llvm = dependency('Clang', version: '>= 14', modules: ['libclang'])
|
||||
sources = ['HasPrefixSuffix.cc', 'NixClangTidyChecks.cc']
|
||||
shared_module('nix-clang-tidy', sources,
|
||||
dependencies: llvm)
|
||||
@@ -342,6 +342,13 @@ AC_SUBST(doc_generate)
|
||||
# Look for lowdown library.
|
||||
PKG_CHECK_MODULES([LOWDOWN], [lowdown >= 0.9.0], [CXXFLAGS="$LOWDOWN_CFLAGS $CXXFLAGS"])
|
||||
|
||||
# Look for toml11, a required dependency.
|
||||
AC_ARG_VAR([TOML11_HEADERS], [include path of toml11 headers])
|
||||
AC_LANG_PUSH(C++)
|
||||
[CXXFLAGS="-I $TOML11_HEADERS $CXXFLAGS"]
|
||||
AC_CHECK_HEADER([toml.hpp], [], [AC_MSG_ERROR([toml11 is not found.])])
|
||||
AC_LANG_POP(C++)
|
||||
|
||||
# Setuid installations.
|
||||
AC_CHECK_FUNCS([setresuid setreuid lchown])
|
||||
|
||||
|
||||
Executable → Regular
+12
-49
@@ -39,67 +39,30 @@ dummy-env = env -i \
|
||||
|
||||
nix-eval = $(dummy-env) $(doc_nix) eval --experimental-features nix-command -I nix/corepkgs=corepkgs --store dummy:// --impure --raw
|
||||
|
||||
# re-implement mdBook's include directive to make it usable for terminal output and for proper @docroot@ substitution
|
||||
define process-includes
|
||||
while read -r line; do \
|
||||
set -euo pipefail; \
|
||||
filename="$$(dirname $(1))/$$(sed 's/{{#include \(.*\)}}/\1/'<<< $$line)"; \
|
||||
test -f "$$filename" || ( echo "#include-d file '$$filename' does not exist." >&2; exit 1; ); \
|
||||
matchline="$$(sed 's|/|\\/|g' <<< $$line)"; \
|
||||
sed -i "/$$matchline/r $$filename" $(2); \
|
||||
sed -i "s/$$matchline//" $(2); \
|
||||
done < <(grep '{{#include' $(1))
|
||||
endef
|
||||
|
||||
$(d)/nix-env-%.1: $(d)/src/command-ref/nix-env/%.md
|
||||
@printf "Title: %s\n\n" "$(subst nix-env-,nix-env --,$$(basename "$@" .1))" > $^.tmp
|
||||
$(render-subcommand)
|
||||
$(trace-gen) doc/manual/render-manpage.sh \
|
||||
--unescape-dashes "$(subst nix-env-,nix-env --,$$(basename "$@" .1))" 1 $^ $^.tmp $@
|
||||
|
||||
$(d)/nix-store-%.1: $(d)/src/command-ref/nix-store/%.md
|
||||
@printf -- 'Title: %s\n\n' "$(subst nix-store-,nix-store --,$$(basename "$@" .1))" > $^.tmp
|
||||
$(render-subcommand)
|
||||
|
||||
# FIXME: there surely is some more deduplication to be achieved here with even darker Make magic
|
||||
define render-subcommand
|
||||
@cat $^ >> $^.tmp
|
||||
@$(call process-includes,$^,$^.tmp)
|
||||
$(trace-gen) lowdown -sT man --nroff-nolinks -M section=1 $^.tmp -o $@
|
||||
@# fix up `lowdown`'s automatic escaping of `--`
|
||||
@# https://github.com/kristapsdz/lowdown/blob/edca6ce6d5336efb147321a43c47a698de41bb7c/entity.c#L202
|
||||
@sed -i 's/\e\[u2013\]/--/' $@
|
||||
@rm $^.tmp
|
||||
endef
|
||||
$(trace-gen) doc/manual/render-manpage.sh \
|
||||
--unescape-dashes "$(subst nix-store-,nix-store --,$$(basename "$@" .1))" 1 $^ $^.tmp $@
|
||||
|
||||
|
||||
$(d)/%.1: $(d)/src/command-ref/%.md
|
||||
@printf "Title: %s\n\n" "$$(basename $@ .1)" > $^.tmp
|
||||
@cat $^ >> $^.tmp
|
||||
@$(call process-includes,$^,$^.tmp)
|
||||
$(trace-gen) lowdown -sT man --nroff-nolinks -M section=1 $^.tmp -o $@
|
||||
@rm $^.tmp
|
||||
$(trace-gen) doc/manual/render-manpage.sh "$$(basename $@ .1)" 1 $^ $^.tmp $@
|
||||
|
||||
$(d)/%.8: $(d)/src/command-ref/%.md
|
||||
@printf "Title: %s\n\n" "$$(basename $@ .8)" > $^.tmp
|
||||
@cat $^ >> $^.tmp
|
||||
$(trace-gen) lowdown -sT man --nroff-nolinks -M section=8 $^.tmp -o $@
|
||||
@rm $^.tmp
|
||||
$(trace-gen) doc/manual/render-manpage.sh "$$(basename $@ .8)" 8 $^ $^.tmp $@
|
||||
|
||||
$(d)/nix.conf.5: $(d)/src/command-ref/conf-file.md
|
||||
@printf "Title: %s\n\n" "$$(basename $@ .5)" > $^.tmp
|
||||
@cat $^ >> $^.tmp
|
||||
@$(call process-includes,$^,$^.tmp)
|
||||
$(trace-gen) lowdown -sT man --nroff-nolinks -M section=5 $^.tmp -o $@
|
||||
@rm $^.tmp
|
||||
$(trace-gen) doc/manual/render-manpage.sh "$$(basename $@ .5)" 5 $^ $^.tmp $@
|
||||
|
||||
$(d)/nix-profiles.5: $(d)/src/command-ref/files/profiles.md
|
||||
@printf "Title: %s\n\n" "$$(basename $@ .5)" > $^.tmp
|
||||
@cat $^ >> $^.tmp
|
||||
$(trace-gen) lowdown -sT man --nroff-nolinks -M section=5 $^.tmp -o $@
|
||||
@rm $^.tmp
|
||||
$(trace-gen) doc/manual/render-manpage.sh "$$(basename $@ .5)" 5 $^ $^.tmp $@
|
||||
|
||||
$(d)/src/SUMMARY.md: $(d)/src/SUMMARY.md.in $(d)/src/SUMMARY-rl-next.md $(d)/src/command-ref/new-cli $(d)/src/contributing/experimental-feature-descriptions.md
|
||||
@cp $< $@
|
||||
@$(call process-includes,$@,$@)
|
||||
@doc/manual/process-includes.sh $@ $@
|
||||
|
||||
$(d)/src/command-ref/new-cli: $(d)/nix.json $(d)/utils.nix $(d)/generate-manpage.nix $(doc_nix)
|
||||
@rm -rf $@ $@.tmp
|
||||
@@ -151,9 +114,9 @@ $(d)/language.json: $(doc_nix)
|
||||
|
||||
# Generate "Upcoming release" notes (or clear it and remove from menu)
|
||||
$(d)/src/release-notes/rl-next.md: $(d)/rl-next $(d)/rl-next/*
|
||||
@if type -p changelog-d > /dev/null; then \
|
||||
@if type -p build-release-notes > /dev/null; then \
|
||||
echo " GEN " $@; \
|
||||
changelog-d doc/manual/rl-next > $@; \
|
||||
build-release-notes doc/manual/rl-next > $@; \
|
||||
else \
|
||||
echo " NULL " $@; \
|
||||
true > $@; \
|
||||
@@ -201,7 +164,7 @@ $(docdir)/manual/index.html: $(MANUAL_SRCS) $(d)/book.toml $(d)/anchors.jq $(d)/
|
||||
tmp="$$(mktemp -d)"; \
|
||||
cp -r doc/manual "$$tmp"; \
|
||||
find "$$tmp" -name '*.md' | while read -r file; do \
|
||||
$(call process-includes,$$file,$$file); \
|
||||
doc/manual/process-includes.sh $$file $$file; \
|
||||
done; \
|
||||
find "$$tmp" -name '*.md' | while read -r file; do \
|
||||
docroot="$$(realpath --relative-to="$$(dirname "$$file")" $$tmp/manual/src)"; \
|
||||
|
||||
@@ -0,0 +1,290 @@
|
||||
nix_env_for_docs = {
|
||||
'HOME': '/dummy',
|
||||
'NIX_CONF_DIR': '/dummy',
|
||||
'NIX_SSL_CERT_FILE': '/dummy/no-ca-bundle.crt',
|
||||
'NIX_STATE_DIR': '/dummy',
|
||||
'NIX_CONFIG': 'cores = 0',
|
||||
}
|
||||
|
||||
nix_for_docs = [ nix, '--experimental-features', 'nix-command' ]
|
||||
nix_eval_for_docs = nix_for_docs + [
|
||||
'eval',
|
||||
'-I', 'nix/corepkgs=corepkgs',
|
||||
'--store', 'dummy://',
|
||||
'--impure',
|
||||
'--raw',
|
||||
]
|
||||
|
||||
nix_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',
|
||||
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-prefix.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',
|
||||
)
|
||||
nix_exp_feature_shortlist = custom_target(
|
||||
command : nix_eval_for_docs + [
|
||||
'--expr',
|
||||
'import @INPUT0@ (builtins.fromJSON (builtins.readFile @INPUT1@))',
|
||||
],
|
||||
input : [
|
||||
'generate-xp-features-shortlist.nix',
|
||||
nix_exp_features_json,
|
||||
],
|
||||
output : 'experimental-features-shortlist.md',
|
||||
capture : true,
|
||||
env : nix_env_for_docs,
|
||||
)
|
||||
|
||||
nix_nested_manpages = [
|
||||
[ 'nix-env',
|
||||
[
|
||||
'delete-generations',
|
||||
'install',
|
||||
'list-generations',
|
||||
'query',
|
||||
'rollback',
|
||||
'set-flag',
|
||||
'set',
|
||||
'switch-generation',
|
||||
'switch-profile',
|
||||
'uninstall',
|
||||
'upgrade',
|
||||
],
|
||||
],
|
||||
[ 'nix-store',
|
||||
[
|
||||
'add-fixed',
|
||||
'add',
|
||||
'delete',
|
||||
'dump-db',
|
||||
'dump',
|
||||
'export',
|
||||
'gc',
|
||||
'generate-binary-cache-key',
|
||||
'import',
|
||||
'load-db',
|
||||
'optimise',
|
||||
'print-env',
|
||||
'query',
|
||||
'read-log',
|
||||
'realise',
|
||||
'repair-path',
|
||||
'restore',
|
||||
'serve',
|
||||
'verify',
|
||||
'verify-path',
|
||||
],
|
||||
],
|
||||
]
|
||||
|
||||
foreach command : nix_nested_manpages
|
||||
foreach page : command[1]
|
||||
custom_target(
|
||||
command : [
|
||||
'./render-manpage.sh',
|
||||
'--unescape-dashes',
|
||||
command[0] + ' --' + page,
|
||||
'1',
|
||||
'@INPUT@',
|
||||
'@OUTPUT@.tmp',
|
||||
'@OUTPUT@',
|
||||
],
|
||||
input : 'src/command-ref' / command[0] / (page + '.md'),
|
||||
output : command[0] + '-' + page + '.1',
|
||||
install : true,
|
||||
install_dir : mandir / 'man1',
|
||||
)
|
||||
endforeach
|
||||
endforeach
|
||||
|
||||
nix3_cli_json = custom_target(
|
||||
command : [ nix, '__dump-cli' ],
|
||||
capture : true,
|
||||
output : 'nix.json',
|
||||
)
|
||||
nix3_cli_files = custom_target(
|
||||
command : nix_eval_for_docs + [
|
||||
'--write-to', '@OUTPUT@',
|
||||
'--expr',
|
||||
'import @INPUT1@ true (builtins.readFile @INPUT0@)',
|
||||
],
|
||||
input : [
|
||||
nix3_cli_json,
|
||||
'generate-manpage.nix',
|
||||
'utils.nix',
|
||||
],
|
||||
output : 'new-cli',
|
||||
)
|
||||
|
||||
nix3_manpages = [
|
||||
'nix3-build',
|
||||
'nix3-bundle',
|
||||
'nix3-copy',
|
||||
'nix3-daemon',
|
||||
'nix3-derivation-add',
|
||||
'nix3-derivation',
|
||||
'nix3-derivation-show',
|
||||
'nix3-develop',
|
||||
'nix3-doctor',
|
||||
'nix3-edit',
|
||||
'nix3-eval',
|
||||
'nix3-flake-archive',
|
||||
'nix3-flake-check',
|
||||
'nix3-flake-clone',
|
||||
'nix3-flake-info',
|
||||
'nix3-flake-init',
|
||||
'nix3-flake-lock',
|
||||
'nix3-flake',
|
||||
'nix3-flake-metadata',
|
||||
'nix3-flake-new',
|
||||
'nix3-flake-prefetch',
|
||||
'nix3-flake-show',
|
||||
'nix3-flake-update',
|
||||
'nix3-fmt',
|
||||
'nix3-hash-file',
|
||||
'nix3-hash',
|
||||
'nix3-hash-path',
|
||||
'nix3-hash-to-base16',
|
||||
'nix3-hash-to-base32',
|
||||
'nix3-hash-to-base64',
|
||||
'nix3-hash-to-sri',
|
||||
'nix3-help',
|
||||
'nix3-help-stores',
|
||||
'nix3-key-convert-secret-to-public',
|
||||
'nix3-key-generate-secret',
|
||||
'nix3-key',
|
||||
'nix3-log',
|
||||
'nix3-nar-cat',
|
||||
'nix3-nar-dump-path',
|
||||
'nix3-nar-ls',
|
||||
'nix3-nar',
|
||||
'nix3-path-info',
|
||||
'nix3-print-dev-env',
|
||||
'nix3-profile-diff-closures',
|
||||
'nix3-profile-history',
|
||||
'nix3-profile-install',
|
||||
'nix3-profile-list',
|
||||
'nix3-profile',
|
||||
'nix3-profile-remove',
|
||||
'nix3-profile-rollback',
|
||||
'nix3-profile-upgrade',
|
||||
'nix3-profile-wipe-history',
|
||||
'nix3-realisation-info',
|
||||
'nix3-realisation',
|
||||
'nix3-registry-add',
|
||||
'nix3-registry-list',
|
||||
'nix3-registry',
|
||||
'nix3-registry-pin',
|
||||
'nix3-registry-remove',
|
||||
'nix3-repl',
|
||||
'nix3-run',
|
||||
'nix3-search',
|
||||
'nix3-shell',
|
||||
'nix3-show-config',
|
||||
'nix3-store-add-file',
|
||||
'nix3-store-add-path',
|
||||
'nix3-store-cat',
|
||||
'nix3-store-copy-log',
|
||||
'nix3-store-copy-sigs',
|
||||
'nix3-store-delete',
|
||||
'nix3-store-diff-closures',
|
||||
'nix3-store-dump-path',
|
||||
'nix3-store-gc',
|
||||
'nix3-store-ls',
|
||||
'nix3-store-make-content-addressed',
|
||||
'nix3-store',
|
||||
'nix3-store-optimise',
|
||||
'nix3-store-path-from-hash-part',
|
||||
'nix3-store-ping',
|
||||
'nix3-store-prefetch-file',
|
||||
'nix3-store-repair',
|
||||
'nix3-store-sign',
|
||||
'nix3-store-verify',
|
||||
'nix3-upgrade-nix',
|
||||
'nix3-why-depends',
|
||||
'nix',
|
||||
]
|
||||
|
||||
foreach page : nix3_manpages
|
||||
custom_target(
|
||||
command : [
|
||||
'./render-manpage.sh',
|
||||
page,
|
||||
'1',
|
||||
'@INPUT0@/' + page + '.md',
|
||||
'@OUTPUT@.tmp',
|
||||
'@OUTPUT@',
|
||||
],
|
||||
input : nix3_cli_files,
|
||||
output : page + '.1',
|
||||
install : true,
|
||||
install_dir : mandir / 'man1',
|
||||
)
|
||||
endforeach
|
||||
|
||||
nix_manpages = [
|
||||
[ 'nix-env', 1 ],
|
||||
[ 'nix-store', 1 ],
|
||||
[ 'nix-build', 1 ],
|
||||
[ 'nix-shell', 1 ],
|
||||
[ 'nix-instantiate', 1 ],
|
||||
[ 'nix-collect-garbage', 1 ],
|
||||
[ 'nix-prefetch-url', 1 ],
|
||||
[ 'nix-channel', 1 ],
|
||||
[ 'nix-hash', 1 ],
|
||||
[ 'nix-copy-closure', 1 ],
|
||||
[ 'nix.conf', 5, nix_conf_file_md, nix_exp_feature_shortlist ],
|
||||
[ 'nix-daemon', 8 ],
|
||||
[ 'nix-profiles', 5, 'src/command-ref/files/profiles.md', nix_exp_feature_shortlist ],
|
||||
]
|
||||
|
||||
foreach entry : nix_manpages
|
||||
custom_target(
|
||||
command : [
|
||||
'./render-manpage.sh',
|
||||
entry[0],
|
||||
entry[1].to_string(),
|
||||
'@INPUT0@',
|
||||
'@OUTPUT@.tmp',
|
||||
'@OUTPUT@',
|
||||
meson.current_build_dir(),
|
||||
],
|
||||
input : [
|
||||
entry.get(2, 'src/command-ref' / (entry[0] + '.md')),
|
||||
entry.get(3, []),
|
||||
],
|
||||
output : '@0@.@1@'.format(entry[0], entry[1]),
|
||||
install : true,
|
||||
install_dir : mandir / 'man@0@'.format(entry[1]),
|
||||
)
|
||||
endforeach
|
||||
Executable
+32
@@ -0,0 +1,32 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
infile="$1"
|
||||
outfile="$2"
|
||||
shift 2
|
||||
|
||||
# set a search path for includes. the old makefile-based system splorked
|
||||
# everything into the source tree and was thus able to not have a search
|
||||
# path, but the meson system generates intermediate files into dedicated
|
||||
# directories separate from the source. we still retain the implicit old
|
||||
# behavior for now as the base search path, once meson is the default we
|
||||
# can revisit this and remove the implicit search path entry. it's fine.
|
||||
set -- "$(dirname "$infile")" "$@"
|
||||
|
||||
# re-implement mdBook's include directive to make it usable for terminal output and for proper @docroot@ substitution
|
||||
(grep '{{#include' "$infile" || true) | while read -r line; do
|
||||
found=false
|
||||
include="$(printf "$line" | sed 's/{{#include \(.*\)}}/\1/')"
|
||||
for path in "$@"; do
|
||||
filename="$path/$include"
|
||||
if [ -e "$filename" ]; then
|
||||
found=true
|
||||
matchline="$(printf "$line" | sed 's|/|\\/|g')"
|
||||
sed -i "/$matchline/r $filename" "$outfile"
|
||||
sed -i "s/$matchline//" "$outfile"
|
||||
break
|
||||
fi
|
||||
done
|
||||
$found || ( echo "#include-d file '$filename' does not exist." >&2; exit 1; )
|
||||
done
|
||||
Executable
+27
@@ -0,0 +1,27 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
unescape_dashes=
|
||||
|
||||
if [ "$1" = --unescape-dashes ]; then
|
||||
unescape_dashes=yes
|
||||
shift
|
||||
fi
|
||||
|
||||
title="$1"
|
||||
section="$2"
|
||||
infile="$3"
|
||||
tmpfile="$4"
|
||||
outfile="$5"
|
||||
|
||||
printf "Title: %s\n\n" "$title" > "$tmpfile"
|
||||
cat "$infile" >> "$tmpfile"
|
||||
"$(dirname "$0")"/process-includes.sh "$infile" "$tmpfile"
|
||||
lowdown -sT man --nroff-nolinks -M section="$section" "$tmpfile" -o "$outfile"
|
||||
if [ -n "$unescape_dashes" ]; then
|
||||
# fix up `lowdown`'s automatic escaping of `--`
|
||||
# https://github.com/kristapsdz/lowdown/blob/edca6ce6d5336efb147321a43c47a698de41bb7c/entity.c#L202
|
||||
sed -i 's/\e\[u2013\]/--/' "$outfile"
|
||||
fi
|
||||
rm "$tmpfile"
|
||||
@@ -0,0 +1,15 @@
|
||||
---
|
||||
synopsis: Clang build timing analysis
|
||||
cls: 587
|
||||
---
|
||||
|
||||
We now have Clang build profiling available, which generates Chrome
|
||||
tracing files for each compilation unit. To enable it, run `meson configure
|
||||
build -Dprofile-build=enabled` then rerun the compilation.
|
||||
|
||||
If you want to make the build go faster, do a clang build with meson, then run
|
||||
`maintainers/buildtime_report.sh build`, then contemplate how to improve the
|
||||
build time.
|
||||
|
||||
You can also look at individual object files' traces in
|
||||
<https://ui.perfetto.dev>.
|
||||
@@ -37,4 +37,3 @@ error:
|
||||
|
||||
error: uh oh!
|
||||
```
|
||||
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
organization: NixOS
|
||||
repository: nix
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
synopsis: "`--debugger` can now access bindings from `let` expressions"
|
||||
prs: 9918
|
||||
issues: 8827.
|
||||
issues: 8827
|
||||
---
|
||||
|
||||
Breakpoints and errors in the bindings of a `let` expression can now access
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
---
|
||||
synopsis: Enter the `--debugger` when `builtins.trace` is called if `debugger-on-trace` is set
|
||||
prs: 9914
|
||||
---
|
||||
|
||||
If the `debugger-on-trace` option is set and `--debugger` is given,
|
||||
`builtins.trace` calls will behave similarly to `builtins.break` and will enter
|
||||
the debug REPL. This is useful for determining where warnings are being emitted
|
||||
from.
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
synopsis: Stop vendoring toml11
|
||||
cls: 675
|
||||
---
|
||||
|
||||
We don't apply any patches to it, and vendoring it locks users into
|
||||
bugs (it hasn't been updated since its introduction in late 2021).
|
||||
@@ -0,0 +1,22 @@
|
||||
---
|
||||
synopsis: Duplicate attribute reports are more accurate
|
||||
cls: 557
|
||||
---
|
||||
|
||||
Duplicate attribute errors are now more accurate, showing the path at which an error was detected rather than the full, possibly longer, path that caused the error.
|
||||
Error reports are now
|
||||
```ShellSession
|
||||
$ nix eval --expr '{ a.b = 1; a.b.c.d = 1; }'
|
||||
error: attribute 'a.b' already defined at «string»:1:3
|
||||
at «string»:1:12:
|
||||
1| { a.b = 1; a.b.c.d = 1;
|
||||
| ^
|
||||
```
|
||||
instead of
|
||||
```ShellSession
|
||||
$ nix eval --expr '{ a.b = 1; a.b.c.d = 1; }'
|
||||
error: attribute 'a.b.c.d' already defined at «string»:1:3
|
||||
at «string»:1:12:
|
||||
1| { a.b = 1; a.b.c.d = 1;
|
||||
| ^
|
||||
```
|
||||
@@ -1,8 +1,6 @@
|
||||
---
|
||||
synopsis: Disallow empty search regex in `nix search`
|
||||
prs: #9481
|
||||
description: {
|
||||
prs: 9481
|
||||
---
|
||||
|
||||
[`nix search`](@docroot@/command-ref/new-cli/nix3-search.md) now requires a search regex to be passed. To show all packages, use `^`.
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
synopsis: consistent order of lambda formals in printed expressions
|
||||
prs: 9874
|
||||
---
|
||||
|
||||
Always print lambda formals in lexicographic order rather than the internal, creation-time based symbol order.
|
||||
This makes printed formals independent of the context they appear in.
|
||||
@@ -0,0 +1,6 @@
|
||||
---
|
||||
synopsis: fix duplicate attribute error positions for `inherit`
|
||||
prs: 9874
|
||||
---
|
||||
|
||||
When an inherit caused a duplicate attribute error the position of the error was not reported correctly, placing the error with the inherit itself or at the start of the bindings block instead of the offending attribute name.
|
||||
@@ -0,0 +1,7 @@
|
||||
---
|
||||
synopsis: "`inherit (x) ...` evaluates `x` only once"
|
||||
prs: 9847
|
||||
---
|
||||
|
||||
`inherit (x) a b ...` now evaluates the expression `x` only once for all inherited attributes rather than once for each inherited attribute.
|
||||
This does not usually have a measurable impact, but side-effects (such as `builtins.trace`) would be duplicated and expensive expressions (such as derivations) could cause a measurable slowdown.
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
synopsis: "`Overhaul `nix flake update` and `nix flake lock` UX"
|
||||
prs: 8817
|
||||
---
|
||||
|
||||
The interface for creating and updating lock files has been overhauled:
|
||||
|
||||
- [`nix flake lock`](@docroot@/command-ref/new-cli/nix3-flake-lock.md) only creates lock files and adds missing inputs now.
|
||||
It will *never* update existing inputs.
|
||||
|
||||
- [`nix flake update`](@docroot@/command-ref/new-cli/nix3-flake-update.md) does the same, but *will* update inputs.
|
||||
- Passing no arguments will update all inputs of the current flake, just like it already did.
|
||||
- Passing input names as arguments will ensure only those are updated. This replaces the functionality of `nix flake lock --update-input`
|
||||
- To operate on a flake outside the current directory, you must now pass `--flake path/to/flake`.
|
||||
|
||||
- The flake-specific flags `--recreate-lock-file` and `--update-input` have been removed from all commands operating on installables.
|
||||
They are superceded by `nix flake update`.
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
synopsis: "`builtins.nixVersion` now returns a fixed value \"2.18.3-lix\""
|
||||
cls: 558
|
||||
---
|
||||
|
||||
`builtins.nixVersion` now returns a fixed value `"2.18.3-lix"`. This prevents
|
||||
feature detection assuming that features that exist in Nix post-Lix-branch-off
|
||||
might exist, even though the Lix version is greater than the Nix version.
|
||||
|
||||
In the future, check for builtins for feature detection. If a feature cannot be
|
||||
detected by *those* means, please file a Lix bug.
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
synopsis: Coercion errors include the failing value
|
||||
issues: #561
|
||||
prs: #9754
|
||||
issues: 561
|
||||
prs: 9754
|
||||
---
|
||||
|
||||
The `error: cannot coerce a <TYPE> to a string` message now includes the value
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
synopsis: Type errors include the failing value
|
||||
issues: #561
|
||||
prs: #9753
|
||||
issues: 561
|
||||
prs: 9753
|
||||
---
|
||||
|
||||
In errors like `value is an integer while a list was expected`, the message now
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
synopsis: reintroduce shortened `-E` form for `--expr` to new CLI
|
||||
cls: 605
|
||||
---
|
||||
|
||||
In the past, it was possible to supply a shorter `-E` flag instead of fully
|
||||
specifying `--expr` every time you wished to provide an expression that would
|
||||
be evaluated to produce the given command's input. This was retained for the
|
||||
`--file` flag when the new CLI utilities were written with `-f`, but `-E` was
|
||||
dropped.
|
||||
|
||||
We now restore the `-E` short form for better UX. This is most useful for
|
||||
`nix eval` but most any command that takes an Installable argument should benefit
|
||||
from it as well.
|
||||
@@ -0,0 +1,8 @@
|
||||
---
|
||||
synopsis: Upstart scripts removed
|
||||
cls: 574
|
||||
---
|
||||
|
||||
Upstart scripts have been removed from Lix, since Upstart is obsolete and has
|
||||
not been shipped by any major distributions for many years. If these are
|
||||
necessary to your use case, please back port them to your packaging.
|
||||
@@ -27,4 +27,3 @@
|
||||
/package-management/channels* /command-ref/nix-channel 301!
|
||||
|
||||
/package-management/s3-substituter* /command-ref/new-cli/nix3-help-stores#s3-binary-cache-store 301!
|
||||
|
||||
|
||||
@@ -112,4 +112,3 @@ Build inputs used as instructions to a build task are marked accordingly:
|
||||
| |
|
||||
+--------------------------------------------------------------------+
|
||||
```
|
||||
|
||||
|
||||
@@ -67,4 +67,3 @@ Configuration options can be set on the command line, overriding the values set
|
||||
The `extra-` prefix is supported for settings that take a list of items (e.g. `--extra-trusted users alice` or `--option extra-trusted-users alice`).
|
||||
|
||||
# Available settings
|
||||
|
||||
|
||||
@@ -184,4 +184,3 @@ channel:
|
||||
```console
|
||||
$ nix-env --file https://github.com/NixOS/nixpkgs/archive/nixos-14.12.tar.gz --install --attr firefox
|
||||
```
|
||||
|
||||
|
||||
@@ -30,4 +30,3 @@ $ nix-env --list-generations
|
||||
97 2004-02-06 16:22:45
|
||||
98 2004-02-06 16:24:33 (current)
|
||||
```
|
||||
|
||||
|
||||
@@ -212,4 +212,3 @@ To show all packages in the latest revision of the Nixpkgs repository:
|
||||
```console
|
||||
$ nix-env --file https://github.com/NixOS/nixpkgs/archive/master.tar.gz --query --available
|
||||
```
|
||||
|
||||
|
||||
@@ -79,4 +79,3 @@ To make files from `binutils` take precedence over files from `gcc`:
|
||||
$ nix-env --set-flag priority 5 binutils
|
||||
$ nix-env --set-flag priority 10 gcc
|
||||
```
|
||||
|
||||
|
||||
@@ -27,4 +27,3 @@ contain just Firefox:
|
||||
```console
|
||||
$ nix-env --profile /nix/var/nix/profiles/browser --set firefox
|
||||
```
|
||||
|
||||
|
||||
@@ -30,4 +30,3 @@ Switching will fail if the specified generation does not exist.
|
||||
$ nix-env --switch-generation 42
|
||||
switching from generation 50 to 42
|
||||
```
|
||||
|
||||
|
||||
@@ -138,4 +138,3 @@ This is illustrated by the following examples:
|
||||
2.3a < 2.3c
|
||||
2.3pre1 < 2.3c
|
||||
2.3pre1 < 2.3q
|
||||
|
||||
|
||||
@@ -32,4 +32,3 @@ This operation has the following options:
|
||||
$ nix-store --add-fixed sha256 ./hello-2.10.tar.gz
|
||||
/nix/store/3x7dwzq014bblazs7kq20p9hyzz0qh8g-hello-2.10.tar.gz
|
||||
```
|
||||
|
||||
|
||||
@@ -69,4 +69,3 @@ To delete at least 100 MiBs of unreachable paths:
|
||||
```console
|
||||
$ nix-store --gc --max-freed $((100 * 1024 * 1024))
|
||||
```
|
||||
|
||||
|
||||
@@ -33,4 +33,3 @@ The following options are allowed for all `nix-store` operations, but may not al
|
||||
If there are multiple results, then multiple symlinks will be
|
||||
created by sequentially numbering symlinks beyond the first one
|
||||
(e.g., `foo`, `foo-2`, `foo-3`, and so on).
|
||||
|
||||
|
||||
@@ -37,4 +37,3 @@ hashing files in `/nix/store/qhqx7l2f1kmwihc9bnxs7rc159hsxnf3-gcc-4.1.1'
|
||||
541838819 bytes (516.74 MiB) freed by hard-linking 54143 files;
|
||||
there are 114486 files with equal contents out of 215894 files in total
|
||||
```
|
||||
|
||||
|
||||
@@ -28,4 +28,3 @@ export stdenv; stdenv='/nix/store/7c8asx3yfrg5dg1gzhzyq2236zfgibnn-stdenv'
|
||||
export system; system='x86_64-linux'
|
||||
export _args; _args='-e /nix/store/9krlzvny65gdc8s7kpb6lkx8cd02c25c-default-builder.sh'
|
||||
```
|
||||
|
||||
|
||||
@@ -225,4 +225,3 @@ $ nix-store --query --roots $(which svn)
|
||||
/nix/var/nix/profiles/default-82-link
|
||||
/home/eelco/.local/state/nix/profiles/profile-97-link
|
||||
```
|
||||
|
||||
|
||||
@@ -35,4 +35,3 @@ ktorrent-2.2.1/
|
||||
ktorrent-2.2.1/NEWS
|
||||
...
|
||||
```
|
||||
|
||||
|
||||
@@ -32,4 +32,3 @@ $ nix-store --repair-path /nix/store/dj7a81wsm1ijwwpkks3725661h3263p5-glibc-2.13
|
||||
fetching path `/nix/store/d7a81wsm1ijwwpkks3725661h3263p5-glibc-2.13'...
|
||||
…
|
||||
```
|
||||
|
||||
|
||||
@@ -35,4 +35,3 @@ $ cat <<EOF >>/root/.ssh/authorized_keys
|
||||
command="nice -n20 nix-store --serve --write" ssh-rsa AAAAB3NzaC1yc2EAAAA...
|
||||
EOF
|
||||
```
|
||||
|
||||
|
||||
@@ -26,4 +26,3 @@ To verify the integrity of the `svn` command and all its dependencies:
|
||||
```console
|
||||
$ nix-store --verify-path $(nix-store --query --requisites $(which svn))
|
||||
```
|
||||
|
||||
|
||||
@@ -340,9 +340,6 @@ Significant changes should add the following header, which moves them to the top
|
||||
significance: significant
|
||||
```
|
||||
|
||||
<!-- Keep an eye on https://codeberg.org/fgaz/changelog-d/issues/1 -->
|
||||
See also the [format documentation](https://github.com/haskell/cabal/blob/master/CONTRIBUTING.md#changelog).
|
||||
|
||||
### Build process
|
||||
|
||||
Releases have a precomputed `rl-MAJOR.MINOR.md`, and no `rl-next.md`.
|
||||
|
||||
@@ -289,4 +289,3 @@ search/replaced in it for each new build.
|
||||
The installer now supports a `--tarball-url-prefix` flag which _may_ have
|
||||
solved this need?
|
||||
-->
|
||||
|
||||
|
||||
@@ -145,4 +145,3 @@ which you may remove.
|
||||
> complete. macOS (Catalina+) directly controls root directories and its
|
||||
> read-only root will prevent you from manually deleting the empty `/nix`
|
||||
> mountpoint.
|
||||
|
||||
|
||||
@@ -161,4 +161,3 @@ All comparison operators are implemented in terms of `<`, and the following equi
|
||||
Equivalent to `!`*b1* `||` *b2*.
|
||||
|
||||
[Logical implication]: #logical-implication
|
||||
|
||||
|
||||
Generated
+91
-7
@@ -3,11 +3,11 @@
|
||||
"flake-compat": {
|
||||
"flake": false,
|
||||
"locked": {
|
||||
"lastModified": 1673956053,
|
||||
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
|
||||
"lastModified": 1696426674,
|
||||
"narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
|
||||
"owner": "edolstra",
|
||||
"repo": "flake-compat",
|
||||
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
|
||||
"rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -16,13 +16,52 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1710146030,
|
||||
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"gitignore": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"pre-commit-hooks",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1709087332,
|
||||
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "hercules-ci",
|
||||
"repo": "gitignore.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1709884566,
|
||||
"narHash": "sha256-NSYJg2sfdO/XS3L8XN/59Zhzn0dqWm7XtVnKI2mHq3w=",
|
||||
"lastModified": 1711481231,
|
||||
"narHash": "sha256-J/fW3Xhm3WsJPNd8ksZmfMnol5aOG2qEMDPbOnNNdTQ=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "2be119add7b37dc535da2dd4cba68e2cf8d1517e",
|
||||
"rev": "9d6ddb13cee3cc1192e4430277708c732685f38a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
@@ -48,11 +87,56 @@
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"pre-commit-hooks": {
|
||||
"inputs": {
|
||||
"flake-compat": [
|
||||
"flake-compat"
|
||||
],
|
||||
"flake-utils": "flake-utils",
|
||||
"gitignore": "gitignore",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"nixpkgs-stable": [
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1711562502,
|
||||
"narHash": "sha256-SLo1yf/lfozph818VME9Y56uhaZWY0juZcj/qJZPPrs=",
|
||||
"owner": "9999years",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "d2f6f9376c38fb0c48526720793a17f10cd3ac10",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "9999years",
|
||||
"ref": "add-default-pre-commit-hooks",
|
||||
"repo": "git-hooks.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat",
|
||||
"nixpkgs": "nixpkgs",
|
||||
"nixpkgs-regression": "nixpkgs-regression"
|
||||
"nixpkgs-regression": "nixpkgs-regression",
|
||||
"pre-commit-hooks": "pre-commit-hooks"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,11 +1,23 @@
|
||||
{
|
||||
description = "The purely functional package manager";
|
||||
|
||||
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11-small";
|
||||
inputs.nixpkgs-regression.url = "github:NixOS/nixpkgs/215d4d0fd80ca5163643b03a33fde804a29cc1e2";
|
||||
inputs.flake-compat = { url = "github:edolstra/flake-compat"; flake = false; };
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-23.11-small";
|
||||
nixpkgs-regression.url = "github:NixOS/nixpkgs/215d4d0fd80ca5163643b03a33fde804a29cc1e2";
|
||||
pre-commit-hooks = {
|
||||
# Can go back to `cachix/git-hooks.nix` when this is merged:
|
||||
# https://github.com/cachix/git-hooks.nix/pull/401
|
||||
url = "github:9999years/git-hooks.nix/add-default-pre-commit-hooks";
|
||||
inputs = {
|
||||
flake-compat.follows = "flake-compat";
|
||||
nixpkgs.follows = "nixpkgs";
|
||||
nixpkgs-stable.follows = "nixpkgs";
|
||||
};
|
||||
};
|
||||
flake-compat = { url = "github:edolstra/flake-compat"; flake = false; };
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs, nixpkgs-regression, flake-compat }:
|
||||
outputs = { self, nixpkgs, nixpkgs-regression, pre-commit-hooks, flake-compat }:
|
||||
|
||||
let
|
||||
inherit (nixpkgs) lib;
|
||||
@@ -48,50 +60,6 @@
|
||||
})
|
||||
stdenvs);
|
||||
|
||||
baseFiles =
|
||||
# .gitignore has already been processed, so any changes in it are irrelevant
|
||||
# at this point. It is not represented verbatim for test purposes because
|
||||
# that would interfere with repo semantics.
|
||||
fileset.fileFilter (f: f.name != ".gitignore") ./.;
|
||||
|
||||
configureFiles = fileset.unions [
|
||||
./.version
|
||||
./configure.ac
|
||||
./m4
|
||||
# TODO: do we really need README.md? It doesn't seem used in the build.
|
||||
./README.md
|
||||
];
|
||||
|
||||
topLevelBuildFiles = fileset.unions [
|
||||
./local.mk
|
||||
./Makefile
|
||||
./Makefile.config.in
|
||||
./mk
|
||||
];
|
||||
|
||||
functionalTestFiles = fileset.unions [
|
||||
./tests/functional
|
||||
./tests/unit
|
||||
(fileset.fileFilter (f: lib.strings.hasPrefix "nix-profile" f.name) ./scripts)
|
||||
];
|
||||
|
||||
nixSrc = fileset.toSource {
|
||||
root = ./.;
|
||||
fileset = fileset.intersection baseFiles (fileset.unions [
|
||||
configureFiles
|
||||
topLevelBuildFiles
|
||||
./boehmgc-coroutine-sp-fallback.diff
|
||||
./doc
|
||||
./misc
|
||||
./precompiled-headers.h
|
||||
./src
|
||||
./unit-test-data
|
||||
./COPYING
|
||||
./scripts/local.mk
|
||||
functionalTestFiles
|
||||
]);
|
||||
};
|
||||
|
||||
# Memoize nixpkgs for different platforms for efficiency.
|
||||
nixpkgsFor = forAllSystems
|
||||
(system: let
|
||||
@@ -118,14 +86,97 @@
|
||||
cross = forAllCrossSystems (crossSystem: make-pkgs crossSystem "stdenv");
|
||||
});
|
||||
|
||||
commonDeps =
|
||||
{ pkgs
|
||||
, isStatic ? pkgs.stdenv.hostPlatform.isStatic
|
||||
}:
|
||||
with pkgs; rec {
|
||||
# Use "busybox-sandbox-shell" if present,
|
||||
# if not (legacy) fallback and hope it's sufficient.
|
||||
sh = pkgs.busybox-sandbox-shell or (busybox.override {
|
||||
testNixVersions = pkgs: client: daemon: let
|
||||
nix = pkgs.callPackage ./package.nix {
|
||||
pname =
|
||||
"nix-tests"
|
||||
+ lib.optionalString
|
||||
(lib.versionAtLeast daemon.version "2.4pre20211005" &&
|
||||
lib.versionAtLeast client.version "2.4pre20211005")
|
||||
"-${client.version}-against-${daemon.version}";
|
||||
|
||||
inherit fileset;
|
||||
};
|
||||
in nix.overrideAttrs (prevAttrs: {
|
||||
NIX_DAEMON_PACKAGE = daemon;
|
||||
NIX_CLIENT_PACKAGE = client;
|
||||
|
||||
dontBuild = true;
|
||||
doInstallCheck = true;
|
||||
|
||||
configureFlags = prevAttrs.configureFlags ++ [
|
||||
# We don't need the actual build here.
|
||||
"--disable-build"
|
||||
];
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out
|
||||
'';
|
||||
|
||||
installCheckPhase = lib.optionalString pkgs.stdenv.hostPlatform.isDarwin ''
|
||||
export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
|
||||
'' + ''
|
||||
mkdir -p src/nix-channel
|
||||
make installcheck -j$NIX_BUILD_CORES -l$NIX_BUILD_CORES
|
||||
'';
|
||||
});
|
||||
|
||||
binaryTarball = nix: pkgs:
|
||||
let
|
||||
inherit (pkgs) buildPackages;
|
||||
installerClosureInfo = buildPackages.closureInfo { rootPaths = [ nix ]; };
|
||||
in
|
||||
|
||||
buildPackages.runCommand "nix-binary-tarball-${version}"
|
||||
{ #nativeBuildInputs = lib.optional (system != "aarch64-linux") shellcheck;
|
||||
meta.description = "Distribution-independent Nix bootstrap binaries for ${pkgs.system}";
|
||||
}
|
||||
''
|
||||
cp ${installerClosureInfo}/registration $TMPDIR/reginfo
|
||||
|
||||
dir=nix-${version}-${pkgs.system}
|
||||
fn=$out/$dir.tar.xz
|
||||
mkdir -p $out/nix-support
|
||||
echo "file binary-dist $fn" >> $out/nix-support/hydra-build-products
|
||||
tar cvfJ $fn \
|
||||
--owner=0 --group=0 --mode=u+rw,uga+r \
|
||||
--mtime='1970-01-01' \
|
||||
--absolute-names \
|
||||
--hard-dereference \
|
||||
--transform "s,$TMPDIR/reginfo,$dir/.reginfo," \
|
||||
--transform "s,$NIX_STORE,$dir/store,S" \
|
||||
$TMPDIR/reginfo \
|
||||
$(cat ${installerClosureInfo}/store-paths)
|
||||
'';
|
||||
|
||||
overlayFor = getStdenv: final: prev:
|
||||
let
|
||||
currentStdenv = getStdenv final;
|
||||
comDeps = with final; commonDeps {
|
||||
inherit pkgs;
|
||||
inherit (currentStdenv.hostPlatform) isStatic;
|
||||
};
|
||||
in {
|
||||
nixStable = prev.nix;
|
||||
|
||||
# Forward from the previous stage as we don’t want it to pick the lowdown override
|
||||
nixUnstable = prev.nixUnstable;
|
||||
|
||||
build-release-notes =
|
||||
final.buildPackages.callPackage ./maintainers/build-release-notes.nix { };
|
||||
clangbuildanalyzer = final.buildPackages.callPackage ./misc/clangbuildanalyzer.nix { };
|
||||
boehmgc-nix = (final.boehmgc.override {
|
||||
enableLargeConfig = true;
|
||||
}).overrideAttrs (o: {
|
||||
patches = (o.patches or [ ]) ++ [
|
||||
./boehmgc-coroutine-sp-fallback.diff
|
||||
|
||||
# https://github.com/ivmai/bdwgc/pull/586
|
||||
./boehmgc-traceable_allocator-public.diff
|
||||
];
|
||||
});
|
||||
|
||||
default-busybox-sandbox-shell = final.busybox.override {
|
||||
useMusl = true;
|
||||
enableStatic = true;
|
||||
enableMinimal = true;
|
||||
@@ -147,349 +198,14 @@
|
||||
CONFIG_ASH_PRINTF y
|
||||
CONFIG_ASH_TEST y
|
||||
'';
|
||||
});
|
||||
|
||||
configureFlags =
|
||||
lib.optionals stdenv.isLinux [
|
||||
"--with-boost=${boost}/lib"
|
||||
"--with-sandbox-shell=${sh}/bin/busybox"
|
||||
]
|
||||
++ lib.optionals (stdenv.isLinux && !(isStatic && stdenv.system == "aarch64-linux")) [
|
||||
"LDFLAGS=-fuse-ld=gold"
|
||||
];
|
||||
|
||||
testConfigureFlags = [
|
||||
"RAPIDCHECK_HEADERS=${lib.getDev rapidcheck}/extras/gtest/include"
|
||||
];
|
||||
|
||||
internalApiDocsConfigureFlags = [
|
||||
"--enable-internal-api-docs"
|
||||
];
|
||||
|
||||
changelog-d = pkgs.buildPackages.callPackage ./misc/changelog-d.nix { };
|
||||
|
||||
nativeBuildDeps =
|
||||
[
|
||||
buildPackages.bison
|
||||
buildPackages.flex
|
||||
(lib.getBin buildPackages.lowdown)
|
||||
buildPackages.mdbook
|
||||
buildPackages.mdbook-linkcheck
|
||||
buildPackages.autoconf-archive
|
||||
buildPackages.autoreconfHook
|
||||
buildPackages.pkg-config
|
||||
|
||||
# Tests
|
||||
buildPackages.git
|
||||
buildPackages.mercurial # FIXME: remove? only needed for tests
|
||||
buildPackages.jq # Also for custom mdBook preprocessor.
|
||||
]
|
||||
++ lib.optionals stdenv.hostPlatform.isLinux [(buildPackages.util-linuxMinimal or buildPackages.utillinuxMinimal)]
|
||||
# Official releases don't have rl-next, so we don't need to compile a changelog
|
||||
++ lib.optional (!officialRelease && buildUnreleasedNotes) changelog-d
|
||||
;
|
||||
|
||||
buildDeps =
|
||||
[ curl
|
||||
bzip2 xz brotli editline
|
||||
openssl sqlite
|
||||
libarchive
|
||||
boost
|
||||
lowdown
|
||||
libsodium
|
||||
]
|
||||
++ lib.optionals stdenv.isLinux [libseccomp]
|
||||
++ lib.optional stdenv.hostPlatform.isx86_64 libcpuid;
|
||||
|
||||
checkDeps = [
|
||||
gtest
|
||||
rapidcheck
|
||||
];
|
||||
|
||||
internalApiDocsDeps = [
|
||||
buildPackages.doxygen
|
||||
];
|
||||
|
||||
awsDeps = lib.optional (stdenv.isLinux || stdenv.isDarwin)
|
||||
(aws-sdk-cpp.override {
|
||||
apis = ["s3" "transfer"];
|
||||
customMemoryManagement = false;
|
||||
});
|
||||
|
||||
propagatedDeps =
|
||||
[ ((boehmgc.override {
|
||||
enableLargeConfig = true;
|
||||
}).overrideAttrs(o: {
|
||||
patches = (o.patches or []) ++ [
|
||||
./boehmgc-coroutine-sp-fallback.diff
|
||||
|
||||
# https://github.com/ivmai/bdwgc/pull/586
|
||||
./boehmgc-traceable_allocator-public.diff
|
||||
];
|
||||
})
|
||||
)
|
||||
nlohmann_json
|
||||
];
|
||||
};
|
||||
|
||||
installScriptFor = systems:
|
||||
with nixpkgsFor.x86_64-linux.native;
|
||||
runCommand "installer-script"
|
||||
{ buildInputs = [ nix ];
|
||||
}
|
||||
''
|
||||
mkdir -p $out/nix-support
|
||||
|
||||
# Converts /nix/store/50p3qk8k...-nix-2.4pre20201102_550e11f/bin/nix to 50p3qk8k.../bin/nix.
|
||||
tarballPath() {
|
||||
# Remove the store prefix
|
||||
local path=''${1#${builtins.storeDir}/}
|
||||
# Get the path relative to the derivation root
|
||||
local rest=''${path#*/}
|
||||
# Get the derivation hash
|
||||
local drvHash=''${path%%-*}
|
||||
echo "$drvHash/$rest"
|
||||
}
|
||||
|
||||
substitute ${./scripts/install.in} $out/install \
|
||||
${pkgs.lib.concatMapStrings
|
||||
(system: let
|
||||
tarball = if builtins.elem system crossSystems then self.hydraJobs.binaryTarballCross.x86_64-linux.${system} else self.hydraJobs.binaryTarball.${system};
|
||||
in '' \
|
||||
--replace '@tarballHash_${system}@' $(nix --experimental-features nix-command hash-file --base16 --type sha256 ${tarball}/*.tar.xz) \
|
||||
--replace '@tarballPath_${system}@' $(tarballPath ${tarball}/*.tar.xz) \
|
||||
''
|
||||
)
|
||||
systems
|
||||
} --replace '@nixVersion@' ${version}
|
||||
|
||||
echo "file installer $out/install" >> $out/nix-support/hydra-build-products
|
||||
'';
|
||||
|
||||
testNixVersions = pkgs: client: daemon: with commonDeps { inherit pkgs; }; with pkgs.lib; pkgs.stdenv.mkDerivation {
|
||||
NIX_DAEMON_PACKAGE = daemon;
|
||||
NIX_CLIENT_PACKAGE = client;
|
||||
name =
|
||||
"nix-tests"
|
||||
+ optionalString
|
||||
(versionAtLeast daemon.version "2.4pre20211005" &&
|
||||
versionAtLeast client.version "2.4pre20211005")
|
||||
"-${client.version}-against-${daemon.version}";
|
||||
inherit version;
|
||||
|
||||
src = fileset.toSource {
|
||||
root = ./.;
|
||||
fileset = fileset.intersection baseFiles (fileset.unions [
|
||||
configureFiles
|
||||
topLevelBuildFiles
|
||||
functionalTestFiles
|
||||
]);
|
||||
};
|
||||
|
||||
VERSION_SUFFIX = versionSuffix;
|
||||
|
||||
nativeBuildInputs = nativeBuildDeps;
|
||||
buildInputs = buildDeps ++ awsDeps ++ checkDeps;
|
||||
propagatedBuildInputs = propagatedDeps;
|
||||
|
||||
enableParallelBuilding = true;
|
||||
|
||||
configureFlags =
|
||||
testConfigureFlags # otherwise configure fails
|
||||
++ [ "--disable-build" ];
|
||||
dontBuild = true;
|
||||
doInstallCheck = true;
|
||||
|
||||
installPhase = ''
|
||||
mkdir -p $out
|
||||
'';
|
||||
|
||||
installCheckPhase = (optionalString pkgs.stdenv.hostPlatform.isDarwin ''
|
||||
export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
|
||||
'') + ''
|
||||
mkdir -p src/nix-channel
|
||||
make installcheck -j$NIX_BUILD_CORES -l$NIX_BUILD_CORES
|
||||
'';
|
||||
};
|
||||
|
||||
binaryTarball = nix: pkgs:
|
||||
let
|
||||
inherit (pkgs) buildPackages;
|
||||
inherit (pkgs) cacert;
|
||||
installerClosureInfo = buildPackages.closureInfo { rootPaths = [ nix cacert ]; };
|
||||
in
|
||||
|
||||
buildPackages.runCommand "nix-binary-tarball-${version}"
|
||||
{ #nativeBuildInputs = lib.optional (system != "aarch64-linux") shellcheck;
|
||||
meta.description = "Distribution-independent Nix bootstrap binaries for ${pkgs.system}";
|
||||
}
|
||||
''
|
||||
cp ${installerClosureInfo}/registration $TMPDIR/reginfo
|
||||
cp ${./scripts/create-darwin-volume.sh} $TMPDIR/create-darwin-volume.sh
|
||||
substitute ${./scripts/install-nix-from-closure.sh} $TMPDIR/install \
|
||||
--subst-var-by nix ${nix} \
|
||||
--subst-var-by cacert ${cacert}
|
||||
|
||||
substitute ${./scripts/install-darwin-multi-user.sh} $TMPDIR/install-darwin-multi-user.sh \
|
||||
--subst-var-by nix ${nix} \
|
||||
--subst-var-by cacert ${cacert}
|
||||
substitute ${./scripts/install-systemd-multi-user.sh} $TMPDIR/install-systemd-multi-user.sh \
|
||||
--subst-var-by nix ${nix} \
|
||||
--subst-var-by cacert ${cacert}
|
||||
substitute ${./scripts/install-multi-user.sh} $TMPDIR/install-multi-user \
|
||||
--subst-var-by nix ${nix} \
|
||||
--subst-var-by cacert ${cacert}
|
||||
|
||||
if type -p shellcheck; then
|
||||
# SC1090: Don't worry about not being able to find
|
||||
# $nix/etc/profile.d/nix.sh
|
||||
shellcheck --exclude SC1090 $TMPDIR/install
|
||||
shellcheck $TMPDIR/create-darwin-volume.sh
|
||||
shellcheck $TMPDIR/install-darwin-multi-user.sh
|
||||
shellcheck $TMPDIR/install-systemd-multi-user.sh
|
||||
|
||||
# SC1091: Don't panic about not being able to source
|
||||
# /etc/profile
|
||||
# SC2002: Ignore "useless cat" "error", when loading
|
||||
# .reginfo, as the cat is a much cleaner
|
||||
# implementation, even though it is "useless"
|
||||
# SC2116: Allow ROOT_HOME=$(echo ~root) for resolving
|
||||
# root's home directory
|
||||
shellcheck --external-sources \
|
||||
--exclude SC1091,SC2002,SC2116 $TMPDIR/install-multi-user
|
||||
fi
|
||||
|
||||
chmod +x $TMPDIR/install
|
||||
chmod +x $TMPDIR/create-darwin-volume.sh
|
||||
chmod +x $TMPDIR/install-darwin-multi-user.sh
|
||||
chmod +x $TMPDIR/install-systemd-multi-user.sh
|
||||
chmod +x $TMPDIR/install-multi-user
|
||||
dir=nix-${version}-${pkgs.system}
|
||||
fn=$out/$dir.tar.xz
|
||||
mkdir -p $out/nix-support
|
||||
echo "file binary-dist $fn" >> $out/nix-support/hydra-build-products
|
||||
tar cvfJ $fn \
|
||||
--owner=0 --group=0 --mode=u+rw,uga+r \
|
||||
--mtime='1970-01-01' \
|
||||
--absolute-names \
|
||||
--hard-dereference \
|
||||
--transform "s,$TMPDIR/install,$dir/install," \
|
||||
--transform "s,$TMPDIR/create-darwin-volume.sh,$dir/create-darwin-volume.sh," \
|
||||
--transform "s,$TMPDIR/reginfo,$dir/.reginfo," \
|
||||
--transform "s,$NIX_STORE,$dir/store,S" \
|
||||
$TMPDIR/install \
|
||||
$TMPDIR/create-darwin-volume.sh \
|
||||
$TMPDIR/install-darwin-multi-user.sh \
|
||||
$TMPDIR/install-systemd-multi-user.sh \
|
||||
$TMPDIR/install-multi-user \
|
||||
$TMPDIR/reginfo \
|
||||
$(cat ${installerClosureInfo}/store-paths)
|
||||
'';
|
||||
|
||||
overlayFor = getStdenv: final: prev:
|
||||
let currentStdenv = getStdenv final; in
|
||||
{
|
||||
nixStable = prev.nix;
|
||||
|
||||
nix =
|
||||
with final;
|
||||
with commonDeps {
|
||||
inherit pkgs;
|
||||
inherit (currentStdenv.hostPlatform) isStatic;
|
||||
};
|
||||
let
|
||||
canRunInstalled = currentStdenv.buildPlatform.canExecute currentStdenv.hostPlatform;
|
||||
in currentStdenv.mkDerivation (finalAttrs: {
|
||||
name = "nix-${version}";
|
||||
inherit version;
|
||||
|
||||
src = nixSrc;
|
||||
VERSION_SUFFIX = versionSuffix;
|
||||
|
||||
outputs = [ "out" "dev" "doc" ];
|
||||
|
||||
nativeBuildInputs = nativeBuildDeps;
|
||||
buildInputs = buildDeps
|
||||
# There have been issues building these dependencies
|
||||
++ lib.optionals (currentStdenv.hostPlatform == currentStdenv.buildPlatform) awsDeps
|
||||
++ lib.optionals finalAttrs.doCheck checkDeps;
|
||||
|
||||
propagatedBuildInputs = propagatedDeps;
|
||||
|
||||
disallowedReferences = [ boost ];
|
||||
|
||||
preConfigure = lib.optionalString (! currentStdenv.hostPlatform.isStatic)
|
||||
''
|
||||
# Copy libboost_context so we don't get all of Boost in our closure.
|
||||
# https://github.com/NixOS/nixpkgs/issues/45462
|
||||
mkdir -p $out/lib
|
||||
cp -pd ${boost}/lib/{libboost_context*,libboost_thread*,libboost_system*} $out/lib
|
||||
rm -f $out/lib/*.a
|
||||
${lib.optionalString currentStdenv.hostPlatform.isLinux ''
|
||||
chmod u+w $out/lib/*.so.*
|
||||
patchelf --set-rpath $out/lib:${currentStdenv.cc.cc.lib}/lib $out/lib/libboost_thread.so.*
|
||||
''}
|
||||
${lib.optionalString currentStdenv.hostPlatform.isDarwin ''
|
||||
for LIB in $out/lib/*.dylib; do
|
||||
chmod u+w $LIB
|
||||
install_name_tool -id $LIB $LIB
|
||||
install_name_tool -delete_rpath ${boost}/lib/ $LIB || true
|
||||
done
|
||||
install_name_tool -change ${boost}/lib/libboost_system.dylib $out/lib/libboost_system.dylib $out/lib/libboost_thread.dylib
|
||||
''}
|
||||
'';
|
||||
|
||||
configureFlags = configureFlags ++
|
||||
[ "--sysconfdir=/etc" ] ++
|
||||
lib.optional stdenv.hostPlatform.isStatic "--enable-embedded-sandbox-shell" ++
|
||||
[ (lib.enableFeature finalAttrs.doCheck "tests") ] ++
|
||||
lib.optionals finalAttrs.doCheck testConfigureFlags ++
|
||||
lib.optional (!canRunInstalled) "--disable-doc-gen";
|
||||
|
||||
enableParallelBuilding = true;
|
||||
|
||||
makeFlags = "profiledir=$(out)/etc/profile.d PRECOMPILE_HEADERS=1";
|
||||
|
||||
doCheck = true;
|
||||
|
||||
installFlags = "sysconfdir=$(out)/etc";
|
||||
|
||||
postInstall = ''
|
||||
mkdir -p $doc/nix-support
|
||||
echo "doc manual $doc/share/doc/nix/manual" >> $doc/nix-support/hydra-build-products
|
||||
${lib.optionalString currentStdenv.hostPlatform.isStatic ''
|
||||
mkdir -p $out/nix-support
|
||||
echo "file binary-dist $out/bin/nix" >> $out/nix-support/hydra-build-products
|
||||
''}
|
||||
${lib.optionalString currentStdenv.isDarwin ''
|
||||
install_name_tool \
|
||||
-change ${boost}/lib/libboost_context.dylib \
|
||||
$out/lib/libboost_context.dylib \
|
||||
$out/lib/libnixutil.dylib
|
||||
''}
|
||||
'';
|
||||
|
||||
doInstallCheck = finalAttrs.doCheck;
|
||||
installCheckFlags = "sysconfdir=$(out)/etc";
|
||||
installCheckTarget = "installcheck"; # work around buggy detection in stdenv
|
||||
|
||||
preInstallCheck = lib.optionalString stdenv.hostPlatform.isDarwin ''
|
||||
export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
|
||||
'';
|
||||
|
||||
separateDebugInfo = !currentStdenv.hostPlatform.isStatic;
|
||||
|
||||
strictDeps = true;
|
||||
|
||||
hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie";
|
||||
|
||||
passthru.perl-bindings = final.callPackage ./perl {
|
||||
inherit fileset;
|
||||
nix = final.callPackage ./package.nix {
|
||||
inherit versionSuffix fileset;
|
||||
stdenv = currentStdenv;
|
||||
boehmgc = final.boehmgc-nix;
|
||||
busybox-sandbox-shell = final.busybox-sandbox-shell or final.default-busybox-sandbox-shell;
|
||||
};
|
||||
|
||||
meta.platforms = lib.platforms.unix;
|
||||
});
|
||||
};
|
||||
|
||||
in {
|
||||
@@ -502,43 +218,53 @@
|
||||
# Binary package for various platforms.
|
||||
build = forAllSystems (system: self.packages.${system}.nix);
|
||||
|
||||
# FIXME(Qyriad): remove this when the migration to Meson has been completed.
|
||||
# NOTE: mesonBuildClang depends on mesonBuild depends on build to avoid OOMs
|
||||
# on aarch64 builders caused by too many parallel compiler/linker processes.
|
||||
mesonBuild = forAllSystems (system:
|
||||
(self.packages.${system}.nix.override {
|
||||
buildWithMeson = true;
|
||||
}).overrideAttrs (prev: {
|
||||
buildInputs = prev.buildInputs ++ [ self.packages.${system}.nix ];
|
||||
}));
|
||||
mesonBuildClang = forAllSystems (system:
|
||||
(nixpkgsFor.${system}.stdenvs.clangStdenvPackages.nix.override {
|
||||
buildWithMeson = true;
|
||||
}).overrideAttrs (prev: {
|
||||
buildInputs = prev.buildInputs ++ [ self.hydraJobs.mesonBuild.${system} ];
|
||||
})
|
||||
);
|
||||
|
||||
# Perl bindings for various platforms.
|
||||
perlBindings = forAllSystems (system: nixpkgsFor.${system}.native.nix.perl-bindings);
|
||||
|
||||
# Binary tarball for various platforms, containing a Nix store
|
||||
# with the closure of 'nix' package, and the second half of
|
||||
# the installation script.
|
||||
# with the closure of 'nix' package.
|
||||
binaryTarball = forAllSystems (system: binaryTarball nixpkgsFor.${system}.native.nix nixpkgsFor.${system}.native);
|
||||
|
||||
# docker image with Nix inside
|
||||
dockerImage = lib.genAttrs linux64BitSystems (system: self.packages.${system}.dockerImage);
|
||||
|
||||
# API docs for Nix's unstable internal C++ interfaces.
|
||||
internal-api-docs =
|
||||
with nixpkgsFor.x86_64-linux.native;
|
||||
with commonDeps { inherit pkgs; };
|
||||
internal-api-docs = let
|
||||
nixpkgs = nixpkgsFor.x86_64-linux.native;
|
||||
inherit (nixpkgs) pkgs;
|
||||
|
||||
stdenv.mkDerivation {
|
||||
pname = "nix-internal-api-docs";
|
||||
inherit version;
|
||||
|
||||
src = nixSrc;
|
||||
|
||||
configureFlags = testConfigureFlags ++ internalApiDocsConfigureFlags;
|
||||
|
||||
nativeBuildInputs = nativeBuildDeps;
|
||||
buildInputs = buildDeps ++ propagatedDeps
|
||||
++ awsDeps ++ checkDeps ++ internalApiDocsDeps;
|
||||
|
||||
dontBuild = true;
|
||||
|
||||
installTargets = [ "internal-api-html" ];
|
||||
|
||||
postInstall = ''
|
||||
mkdir -p $out/nix-support
|
||||
echo "doc internal-api-docs $out/share/doc/nix/internal-api/html" >> $out/nix-support/hydra-build-products
|
||||
'';
|
||||
nix = pkgs.callPackage ./package.nix {
|
||||
inherit versionSuffix fileset officialRelease buildUnreleasedNotes;
|
||||
inherit (pkgs) build-release-notes;
|
||||
internalApiDocs = true;
|
||||
boehmgc = pkgs.boehmgc-nix;
|
||||
busybox-sandbox-shell = pkgs.busybox-sandbox-shell;
|
||||
};
|
||||
in
|
||||
nix.overrideAttrs (prev: {
|
||||
# This Hydra job is just for the internal API docs.
|
||||
# We don't need the build artifacts here.
|
||||
dontBuild = true;
|
||||
doCheck = false;
|
||||
doInstallCheck = false;
|
||||
});
|
||||
|
||||
# System tests.
|
||||
tests = import ./tests/nixos { inherit lib nixpkgs nixpkgsFor; } // {
|
||||
@@ -552,7 +278,7 @@
|
||||
type -p nix-env
|
||||
# Note: we're filtering out nixos-install-tools because https://github.com/NixOS/nixpkgs/pull/153594#issuecomment-1020530593.
|
||||
time nix-env --store dummy:// -f ${nixpkgs-regression} -qaP --drv-path | sort | grep -v nixos-install-tools > packages
|
||||
[[ $(sha1sum < packages | cut -c1-40) = ff451c521e61e4fe72bdbe2d0ca5d1809affa733 ]]
|
||||
[[ $(sha1sum < packages | cut -c1-40) = 402242fca90874112b34718b8199d844e8b03d12 ]]
|
||||
mkdir $out
|
||||
'';
|
||||
|
||||
@@ -565,31 +291,66 @@
|
||||
);
|
||||
};
|
||||
|
||||
installTests = forAllSystems (system:
|
||||
let pkgs = nixpkgsFor.${system}.native; in
|
||||
pkgs.runCommand "install-tests" {
|
||||
againstSelf = testNixVersions pkgs pkgs.nix pkgs.pkgs.nix;
|
||||
againstCurrentUnstable =
|
||||
# FIXME: temporarily disable this on macOS because of #3605.
|
||||
if system == "x86_64-linux"
|
||||
then testNixVersions pkgs pkgs.nix pkgs.nixUnstable
|
||||
else null;
|
||||
# Disabled because the latest stable version doesn't handle
|
||||
# `NIX_DAEMON_SOCKET_PATH` which is required for the tests to work
|
||||
# againstLatestStable = testNixVersions pkgs pkgs.nix pkgs.nixStable;
|
||||
} "touch $out");
|
||||
pre-commit = builtins.mapAttrs (system: pre-commit-lib: pre-commit-lib.run {
|
||||
src = self;
|
||||
hooks = {
|
||||
no-commit-to-branch = {
|
||||
enable = true;
|
||||
settings.branch = ["main"];
|
||||
};
|
||||
check-case-conflicts.enable = true;
|
||||
check-executables-have-shebangs = {
|
||||
enable = true;
|
||||
stages = [ "commit" ];
|
||||
};
|
||||
check-shebang-scripts-are-executable = {
|
||||
enable = true;
|
||||
stages = [ "commit" ];
|
||||
};
|
||||
check-symlinks = {
|
||||
enable = true;
|
||||
excludes = [ "^tests/functional/lang/symlink-resolution/broken$" ];
|
||||
};
|
||||
check-merge-conflicts.enable = true;
|
||||
end-of-file-fixer = {
|
||||
enable = true;
|
||||
excludes = [
|
||||
"\\.drv$"
|
||||
"^tests/functional/lang/"
|
||||
];
|
||||
};
|
||||
mixed-line-endings = {
|
||||
enable = true;
|
||||
excludes = [ "^tests/functional/lang/" ];
|
||||
};
|
||||
# TODO: Once the test suite is nicer, clean up and start
|
||||
# enforcing trailing whitespace on tests that don't explicitly
|
||||
# check for it.
|
||||
trim-trailing-whitespace = {
|
||||
enable = true;
|
||||
stages = [ "commit" ];
|
||||
excludes = [ "^tests/functional/lang/" ];
|
||||
};
|
||||
};
|
||||
}) pre-commit-hooks.lib;
|
||||
};
|
||||
|
||||
checks = forAllSystems (system: {
|
||||
checks = forAllSystems (system: let
|
||||
rl-next-check = name: dir:
|
||||
let pkgs = nixpkgsFor.${system}.native;
|
||||
in pkgs.buildPackages.runCommand "test-${name}-release-notes" { } ''
|
||||
LANG=C.UTF-8 ${lib.getExe pkgs.build-release-notes} ${dir} >$out
|
||||
'';
|
||||
in {
|
||||
# FIXME(Qyriad): remove this when the migration to Meson has been completed.
|
||||
mesonBuild = self.hydraJobs.mesonBuild.${system};
|
||||
mesonBuildClang = self.hydraJobs.mesonBuildClang.${system};
|
||||
binaryTarball = self.hydraJobs.binaryTarball.${system};
|
||||
perlBindings = self.hydraJobs.perlBindings.${system};
|
||||
installTests = self.hydraJobs.installTests.${system};
|
||||
nixpkgsLibTests = self.hydraJobs.tests.nixpkgsLibTests.${system};
|
||||
rl-next =
|
||||
let pkgs = nixpkgsFor.${system}.native;
|
||||
in pkgs.buildPackages.runCommand "test-rl-next-release-notes" { } ''
|
||||
LANG=C.UTF-8 ${(commonDeps { inherit pkgs; }).changelog-d}/bin/changelog-d ${./doc/manual/rl-next} >$out
|
||||
'';
|
||||
rl-next = rl-next-check "rl-next" ./doc/manual/rl-next;
|
||||
rl-next-dev = rl-next-check "rl-next-dev" ./doc/manual/rl-next-dev;
|
||||
pre-commit = self.hydraJobs.pre-commit.${system};
|
||||
} // (lib.optionalAttrs (builtins.elem system linux64BitSystems)) {
|
||||
dockerImage = self.hydraJobs.dockerImage.${system};
|
||||
});
|
||||
@@ -629,44 +390,60 @@
|
||||
devShells = let
|
||||
makeShell = pkgs: stdenv:
|
||||
let
|
||||
canRunInstalled = stdenv.buildPlatform.canExecute stdenv.hostPlatform;
|
||||
nix = pkgs.callPackage ./package.nix {
|
||||
inherit stdenv versionSuffix fileset;
|
||||
boehmgc = pkgs.boehmgc-nix;
|
||||
busybox-sandbox-shell = pkgs.busybox-sandbox-shell or pkgs.default-busybox-sandbox;
|
||||
forDevShell = true;
|
||||
};
|
||||
pre-commit = self.hydraJobs.pre-commit.${pkgs.system} or {};
|
||||
in
|
||||
with commonDeps { inherit pkgs; };
|
||||
stdenv.mkDerivation {
|
||||
name = "nix";
|
||||
|
||||
outputs = [ "out" "dev" "doc" ];
|
||||
|
||||
nativeBuildInputs = nativeBuildDeps
|
||||
(nix.override {
|
||||
buildUnreleasedNotes = true;
|
||||
officialRelease = false;
|
||||
}).overrideAttrs (prev: {
|
||||
# Required for clang-tidy checks
|
||||
buildInputs = prev.buildInputs
|
||||
++ [ pkgs.just ]
|
||||
++ lib.optional (pre-commit ? enabledPackages) pre-commit.enabledPackages
|
||||
++ lib.optionals (stdenv.cc.isClang) [ pkgs.llvmPackages.llvm pkgs.llvmPackages.clang-unwrapped.dev ];
|
||||
nativeBuildInputs = prev.nativeBuildInputs
|
||||
++ lib.optional (stdenv.cc.isClang && !stdenv.buildPlatform.isDarwin) pkgs.buildPackages.bear
|
||||
# Required for clang-tidy checks
|
||||
++ lib.optionals (stdenv.cc.isClang) [ pkgs.buildPackages.cmake pkgs.buildPackages.ninja pkgs.buildPackages.llvmPackages.llvm.dev ]
|
||||
++ lib.optional
|
||||
(stdenv.cc.isClang && stdenv.hostPlatform == stdenv.buildPlatform)
|
||||
pkgs.buildPackages.clang-tools
|
||||
# We want changelog-d in the shell even if the current build doesn't need it
|
||||
++ lib.optional (officialRelease || ! buildUnreleasedNotes) changelog-d
|
||||
;
|
||||
# for some reason that seems accidental and was changed in
|
||||
# NixOS 24.05-pre, clang-tools is pinned to LLVM 14 when
|
||||
# default LLVM is newer.
|
||||
(pkgs.buildPackages.clang-tools.override { inherit (pkgs.buildPackages) llvmPackages; })
|
||||
++ [
|
||||
# FIXME(Qyriad): remove once the migration to Meson is complete.
|
||||
pkgs.buildPackages.meson
|
||||
pkgs.buildPackages.ninja
|
||||
|
||||
buildInputs = buildDeps ++ propagatedDeps
|
||||
++ awsDeps ++ checkDeps ++ internalApiDocsDeps;
|
||||
pkgs.buildPackages.clangbuildanalyzer
|
||||
];
|
||||
|
||||
configureFlags = configureFlags
|
||||
++ testConfigureFlags ++ internalApiDocsConfigureFlags
|
||||
++ lib.optional (!canRunInstalled) "--disable-doc-gen";
|
||||
|
||||
enableParallelBuilding = true;
|
||||
src = null;
|
||||
|
||||
installFlags = "sysconfdir=$(out)/etc";
|
||||
strictDeps = false;
|
||||
|
||||
shellHook =
|
||||
''
|
||||
shellHook = ''
|
||||
PATH=$prefix/bin:$PATH
|
||||
unset PYTHONPATH
|
||||
export MANPATH=$out/share/man:$MANPATH
|
||||
|
||||
# Make bash completion work.
|
||||
XDG_DATA_DIRS+=:$out/share
|
||||
|
||||
${lib.optionalString (pre-commit ? shellHook) pre-commit.shellHook}
|
||||
'';
|
||||
};
|
||||
} // lib.optionalAttrs (stdenv.buildPlatform.isLinux && pkgs.glibcLocales != null) {
|
||||
# Required to make non-NixOS Linux not complain about missing locale files during configure in a dev shell
|
||||
LOCALE_ARCHIVE = "${lib.getLib pkgs.glibcLocales}/lib/locale/locale-archive";
|
||||
});
|
||||
in
|
||||
forAllSystems (system:
|
||||
let
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
# https://just.systems/man/en/
|
||||
|
||||
clean:
|
||||
rm -rf build
|
||||
|
||||
setup:
|
||||
meson setup build --prefix="$PWD/outputs/out"
|
||||
|
||||
build:
|
||||
meson compile -C build
|
||||
|
||||
compile:
|
||||
just build
|
||||
|
||||
install:
|
||||
meson install -C build
|
||||
|
||||
test *OPTIONS:
|
||||
meson test -C build --print-errorlogs --quiet {{ OPTIONS }}
|
||||
@@ -1,4 +1,11 @@
|
||||
GLOBAL_CXXFLAGS += -Wno-deprecated-declarations -Werror=switch
|
||||
# 2024-03-24: jade benchmarked the default sanitize reporting in clang and got
|
||||
# a regression of about 10% on hackage-packages.nix with clang. So we are trapping instead.
|
||||
#
|
||||
# This has an overhead of 0-4% on gcc and unmeasurably little on clang, in
|
||||
# Nix evaluation benchmarks.
|
||||
DEFAULT_SANITIZE_FLAGS = -fsanitize=signed-integer-overflow -fsanitize-undefined-trap-on-error
|
||||
GLOBAL_CXXFLAGS += -Wno-deprecated-declarations -Werror=switch $(DEFAULT_SANITIZE_FLAGS)
|
||||
GLOBAL_LDFLAGS += $(DEFAULT_SANITIZE_FLAGS)
|
||||
# Allow switch-enum to be overridden for files that do not support it, usually because of dependency headers.
|
||||
ERROR_SWITCH_ENUM = -Werror=switch-enum
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
{ lib, python3, writeShellScriptBin }:
|
||||
|
||||
writeShellScriptBin "build-release-notes" ''
|
||||
exec ${lib.getExe (python3.withPackages (p: [ p.python-frontmatter ]))} \
|
||||
${./build-release-notes.py} "$@"
|
||||
''
|
||||
@@ -0,0 +1,66 @@
|
||||
import frontmatter
|
||||
import sys
|
||||
import pathlib
|
||||
import textwrap
|
||||
|
||||
GH_BASE = "https://github.com/NixOS/nix"
|
||||
FORGEJO_BASE = "https://git.lix.systems/lix-project/lix"
|
||||
GERRIT_BASE = "https://gerrit.lix.systems/c/lix/+"
|
||||
|
||||
SIGNIFICANCECES = {
|
||||
None: 0,
|
||||
'significant': 10,
|
||||
}
|
||||
|
||||
def format_link(ident: str, gh_part: str, fj_part: str) -> str:
|
||||
# FIXME: deprecate github as default
|
||||
if ident.isdigit():
|
||||
num, link, base = int(ident), f"#{ident}", f"{GH_BASE}/{gh_part}"
|
||||
elif ident.startswith("gh#"):
|
||||
num, link, base = int(ident[3:]), ident, f"{GH_BASE}/{gh_part}"
|
||||
elif ident.startswith("fj#"):
|
||||
num, link, base = int(ident[3:]), ident, f"{FORGEJO_BASE}/{fj_part}"
|
||||
else:
|
||||
raise Exception("unrecognized reference format", ident)
|
||||
return f"[{link}]({base}/{num})"
|
||||
|
||||
def format_issue(issue: str) -> str:
|
||||
return format_link(issue, "issues", "issues")
|
||||
def format_pr(pr: str) -> str:
|
||||
return format_link(pr, "pull", "pulls")
|
||||
def format_cl(cl: str) -> str:
|
||||
clid = int(cl)
|
||||
return f"[cl/{clid}]({GERRIT_BASE}/{clid})"
|
||||
|
||||
paths = pathlib.Path(sys.argv[1]).glob('*.md')
|
||||
entries = []
|
||||
for p in paths:
|
||||
try:
|
||||
e = frontmatter.load(p)
|
||||
if 'synopsis' not in e.metadata:
|
||||
raise Exception('missing synposis')
|
||||
unknownKeys = set(e.metadata.keys()) - set(('synopsis', 'cls', 'issues', 'prs', 'significance'))
|
||||
if unknownKeys:
|
||||
raise Exception('unknown keys', unknownKeys)
|
||||
entries.append((p, e))
|
||||
except Exception as e:
|
||||
e.add_note(f"in {p}")
|
||||
raise
|
||||
|
||||
for p, entry in sorted(entries, key=lambda e: (-SIGNIFICANCECES[e[1].metadata.get('significance')], e[0])):
|
||||
try:
|
||||
header = entry.metadata['synopsis']
|
||||
links = []
|
||||
links += map(format_issue, str(entry.metadata.get('issues', "")).split())
|
||||
links += map(format_pr, str(entry.metadata.get('prs', "")).split())
|
||||
links += map(format_cl, str(entry.metadata.get('cls', "")).split())
|
||||
if links != []:
|
||||
header += " " + " ".join(links)
|
||||
if header:
|
||||
print(f"- {header}")
|
||||
print()
|
||||
print(textwrap.indent(entry.content, ' '))
|
||||
print()
|
||||
except Exception as e:
|
||||
e.add_note(f"in {p}")
|
||||
raise
|
||||
Executable
+20
@@ -0,0 +1,20 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Generates a report of build time based on a meson build using -ftime-trace in
|
||||
# Clang.
|
||||
if [ $# -lt 1 ]; then
|
||||
echo "usage: $0 BUILD-DIR [filename]" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
scriptdir=$(cd "$(dirname -- "$0")" || exit ; pwd -P)
|
||||
filename=${2:-$scriptdir/../buildtime.bin}
|
||||
|
||||
if [ "$(meson introspect "$1" --buildoptions | jq -r '.[] | select(.name == "profile-build") | .value')" != enabled ]; then
|
||||
echo 'This build was not done with profile-build enabled, so cannot generate a report' >&2
|
||||
# shellcheck disable=SC2016
|
||||
echo 'Run `meson configure build -Dprofile-build=enabled` then rebuild, first' >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ClangBuildAnalyzer --all "$1" "$filename" && ClangBuildAnalyzer --analyze "$filename"
|
||||
@@ -0,0 +1,148 @@
|
||||
import requests
|
||||
import textwrap
|
||||
import dataclasses
|
||||
import logging
|
||||
import re
|
||||
import os
|
||||
|
||||
API_BASE = 'https://git.lix.systems/api/v1'
|
||||
API_KEY = os.environ['FORGEJO_API_KEY']
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
log.setLevel(logging.INFO)
|
||||
|
||||
fmt = logging.Formatter('{asctime} {levelname} {name}: {message}',
|
||||
datefmt='%b %d %H:%M:%S',
|
||||
style='{')
|
||||
|
||||
if not any(isinstance(h, logging.StreamHandler) for h in log.handlers):
|
||||
hand = logging.StreamHandler()
|
||||
hand.setFormatter(fmt)
|
||||
log.addHandler(hand)
|
||||
|
||||
# These are erring in the direction of re-triage, rather than necessarily
|
||||
# mapping all metadata of the issue
|
||||
LABEL_MAPPING = {
|
||||
'lix-import': 153, # 'imported',
|
||||
'contributor-experience': 148, # 'devx',
|
||||
'bug': 150, # 'bug',
|
||||
'UX': 149, # 'ux',
|
||||
'error-messages': 149, # 'ux',
|
||||
'lix-stability': 146, # 'stability',
|
||||
'performance': 147, # 'performance',
|
||||
'tests': 121, # 'tests',
|
||||
}
|
||||
|
||||
def api(method, endpoint: str, resp_json=True, **kwargs):
|
||||
log.info('http %s %s', method, endpoint)
|
||||
if not endpoint.startswith('https'):
|
||||
endpoint = API_BASE + endpoint
|
||||
resp = requests.request(method,
|
||||
endpoint,
|
||||
headers={'Authorization': f'Bearer {API_KEY}'},
|
||||
**kwargs)
|
||||
resp.raise_for_status()
|
||||
if resp_json:
|
||||
return resp.json()
|
||||
else:
|
||||
return resp
|
||||
|
||||
def paginate(method: str, url: str):
|
||||
while True:
|
||||
resp = api(method, url, resp_json=False)
|
||||
yield from resp.json()
|
||||
next_one = resp.links.get('next')
|
||||
if not next_one:
|
||||
return
|
||||
url = next_one.get('url')
|
||||
if not url:
|
||||
return
|
||||
|
||||
class DataClassUnpack:
|
||||
"""Taken from: https://stackoverflow.com/a/72164665"""
|
||||
classFieldCache = {}
|
||||
|
||||
@classmethod
|
||||
def instantiate(cls, classToInstantiate, argDict):
|
||||
if classToInstantiate not in cls.classFieldCache:
|
||||
cls.classFieldCache[classToInstantiate] = {
|
||||
f.name
|
||||
for f in getattr(classToInstantiate, dataclasses._FIELDS).values() if f._field_type is not dataclasses._FIELD_CLASSVAR # type: ignore
|
||||
}
|
||||
|
||||
fieldSet = cls.classFieldCache[classToInstantiate]
|
||||
filteredArgDict = {k: v for k, v in argDict.items() if k in fieldSet}
|
||||
return classToInstantiate(**filteredArgDict)
|
||||
|
||||
@dataclasses.dataclass
|
||||
class Label:
|
||||
name: str
|
||||
description: str
|
||||
|
||||
@dataclasses.dataclass
|
||||
class Issue:
|
||||
number: int
|
||||
url: str
|
||||
html_url: str
|
||||
title: str
|
||||
body: str
|
||||
labels: dataclasses.InitVar[list[dict]]
|
||||
labels_clean: list[Label] = dataclasses.field(init=False)
|
||||
|
||||
def __post_init__(self, labels):
|
||||
self.labels_clean = [DataClassUnpack.instantiate(Label, l) for l in labels]
|
||||
|
||||
def issues_to_import():
|
||||
yield from paginate('GET', '/repos/nixos/nix/issues?state=open&labels=lix-import')
|
||||
|
||||
def issues_already_imported():
|
||||
yield from paginate('GET', '/repos/lix-project/lix/issues?state=all&labels=imported')
|
||||
|
||||
|
||||
UPSTREAM_ISSUE_RE = re.compile(r'^Upstream-Issue: https://git\.lix\.systems/NixOS/nix/issues/(\d+)$', re.MULTILINE)
|
||||
|
||||
def make_already_imported():
|
||||
d = {}
|
||||
for issue in issues_already_imported():
|
||||
iss = DataClassUnpack.instantiate(Issue, issue)
|
||||
print(iss)
|
||||
match = UPSTREAM_ISSUE_RE.search(iss.body)
|
||||
if match:
|
||||
d[int(match.group(1))] = iss
|
||||
|
||||
return d
|
||||
|
||||
def new_issue(title, body, labels):
|
||||
api('POST', '/repos/lix-project/lix/issues', resp_json=True, json={
|
||||
'labels': labels,
|
||||
'body': body,
|
||||
'title': title,
|
||||
'dont_notify': True,
|
||||
})
|
||||
|
||||
already_imported = make_already_imported()
|
||||
|
||||
def import_issue(iss: Issue):
|
||||
if iss.number in already_imported:
|
||||
log.info('Skipping already imported %d', iss.number)
|
||||
return
|
||||
new_body = textwrap.dedent('''
|
||||
Upstream-Issue: {iss}
|
||||
|
||||
{original_body}
|
||||
''').format(iss=iss.html_url, original_body=iss.body)
|
||||
|
||||
new_labels = [LABEL_MAPPING[l.name] for l in iss.labels_clean if l.name in LABEL_MAPPING]
|
||||
|
||||
new_title = '[Nix#{num}] {title}'.format(num=iss.number, title=iss.title)
|
||||
|
||||
log.info('%s', f'create issue with: {new_labels} {new_title} {new_body}')
|
||||
new_issue(new_title, new_body, new_labels)
|
||||
|
||||
def go():
|
||||
log.info('Importing issues!')
|
||||
for issue in issues_to_import():
|
||||
import_issue(DataClassUnpack.instantiate(Issue, issue))
|
||||
|
||||
if __name__ == '__main__':
|
||||
go()
|
||||
@@ -152,7 +152,7 @@ section_title="Release $version_full ($DATE)"
|
||||
# TODO add minor number, and append?
|
||||
echo "# $section_title"
|
||||
echo
|
||||
changelog-d doc/manual/rl-next | sed -e 's/ *$//'
|
||||
build-release-notes doc/manual/rl-next
|
||||
) | tee -a $file
|
||||
|
||||
log "Wrote $file"
|
||||
|
||||
@@ -193,4 +193,3 @@ release:
|
||||
## Recovering from mistakes
|
||||
|
||||
`upload-release.pl` should be idempotent. For instance a wrong `IS_LATEST` value can be fixed that way, by running the script on the actual latest release.
|
||||
|
||||
|
||||
+365
@@ -0,0 +1,365 @@
|
||||
#
|
||||
# OUTLINE:
|
||||
#
|
||||
# The top-level meson.build file (this file) handles general logic for build options,
|
||||
# generation of config.h (which is put in the build directory, not the source root
|
||||
# like the previous, autoconf-based build system did), the mechanism for header
|
||||
# generation, and the few global C++ compiler arguments that are added to all targets in Lix.
|
||||
#
|
||||
# src/meson.build coordinates each of Lix's subcomponents (the lib dirs in ./src),
|
||||
# which each have their own meson.build. Lix's components depend on each other,
|
||||
# so each of `src/lib{util,store,fetchers,expr,main,cmd}/meson.build` rely on variables
|
||||
# set in earlier `meson.build` files. Each of these also defines the install targets for
|
||||
# their headers.
|
||||
#
|
||||
# src/meson.build also collects the miscellaneous source files that are in further subdirectories
|
||||
# that become part of the final Nix command (things like `src/nix-build/*.cc`).
|
||||
#
|
||||
# Finally, src/nix/meson.build defines the Nix command itself, relying on all prior meson files.
|
||||
#
|
||||
# Unit tests are setup in tests/unit/meson.build, under the test suite "check".
|
||||
#
|
||||
# Functional tests are a bit more complicated. Generally they're defined in
|
||||
# tests/functional/meson.build, and rely on helper scripts meson/setup-functional-tests.py
|
||||
# and meson/run-test.py. Scattered around also are configure_file() invocations, which must
|
||||
# be placed in specific directories' meson.build files to create the right directory tree
|
||||
# in the build directory.
|
||||
|
||||
project('lix', 'cpp',
|
||||
version : run_command('bash', '-c', 'echo -n $(cat ./.version)$VERSION_SUFFIX', check : true).stdout().strip(),
|
||||
default_options : [
|
||||
'cpp_std=c++2a',
|
||||
# TODO(Qyriad): increase the warning level
|
||||
'warning_level=1',
|
||||
'debug=true',
|
||||
'optimization=2',
|
||||
'errorlogs=true', # Please print logs for tests that fail
|
||||
],
|
||||
)
|
||||
|
||||
fs = import('fs')
|
||||
|
||||
prefix = get_option('prefix')
|
||||
# For each of these paths, assume that it is relative to the prefix unless
|
||||
# it is already an absolute path (which is the default for store-dir, state-dir, and log-dir).
|
||||
path_opts = [
|
||||
# Meson built-ins.
|
||||
'datadir',
|
||||
'sysconfdir',
|
||||
'bindir',
|
||||
'mandir',
|
||||
'libdir',
|
||||
'includedir',
|
||||
'libexecdir',
|
||||
# Homecooked Lix directories.
|
||||
'store-dir',
|
||||
'state-dir',
|
||||
'log-dir',
|
||||
]
|
||||
# For your grepping pleasure, this loop sets the following variables that aren't mentioned
|
||||
# literally above:
|
||||
# store_dir
|
||||
# state_dir
|
||||
# log_dir
|
||||
foreach optname : path_opts
|
||||
varname = optname.replace('-', '_')
|
||||
path = get_option(optname)
|
||||
if fs.is_absolute(path)
|
||||
set_variable(varname, path)
|
||||
else
|
||||
set_variable(varname, prefix / path)
|
||||
endif
|
||||
endforeach
|
||||
|
||||
|
||||
enable_tests = get_option('enable-tests')
|
||||
|
||||
tests_args = []
|
||||
|
||||
if get_option('tests-color')
|
||||
tests_args += '--gtest_color=yes'
|
||||
endif
|
||||
|
||||
if get_option('tests-brief')
|
||||
tests_args += '--gtest_brief=1'
|
||||
endif
|
||||
|
||||
|
||||
cxx = meson.get_compiler('cpp')
|
||||
|
||||
host_system = host_machine.cpu_family() + '-' + host_machine.system()
|
||||
message('canonical Nix system name:', host_system)
|
||||
|
||||
is_linux = host_machine.system() == 'linux'
|
||||
is_x64 = host_machine.cpu_family() == 'x86_64'
|
||||
|
||||
deps = [ ]
|
||||
configdata = { }
|
||||
|
||||
#
|
||||
# Dependencies
|
||||
#
|
||||
|
||||
boehm = dependency('bdw-gc', required : get_option('gc'))
|
||||
if boehm.found()
|
||||
deps += boehm
|
||||
endif
|
||||
configdata += {
|
||||
'HAVE_BOEHMGC': boehm.found().to_int(),
|
||||
}
|
||||
|
||||
boost = dependency('boost', required : true, modules : ['context', 'coroutine', 'container'])
|
||||
deps += boost
|
||||
|
||||
# cpuid only makes sense on x86_64
|
||||
cpuid_required = is_x64 ? get_option('cpuid') : false
|
||||
cpuid = dependency('libcpuid', 'cpuid', required : cpuid_required)
|
||||
configdata += {
|
||||
'HAVE_LIBCPUID': cpuid.found().to_int(),
|
||||
}
|
||||
deps += cpuid
|
||||
|
||||
# seccomp only makes sense on Linux
|
||||
seccomp_required = is_linux ? get_option('seccomp-sandboxing') : false
|
||||
seccomp = dependency('libseccomp', 'seccomp', required : seccomp_required)
|
||||
configdata += {
|
||||
'HAVE_SECCOMP': seccomp.found().to_int(),
|
||||
}
|
||||
|
||||
libarchive = dependency('libarchive', required : true)
|
||||
deps += libarchive
|
||||
|
||||
brotli = [
|
||||
dependency('libbrotlicommon', required : true),
|
||||
dependency('libbrotlidec', required : true),
|
||||
dependency('libbrotlienc', required : true),
|
||||
]
|
||||
deps += brotli
|
||||
|
||||
openssl = dependency('libcrypto', 'openssl', required : true)
|
||||
deps += openssl
|
||||
|
||||
aws_sdk = dependency('aws-cpp-sdk-core', required : false)
|
||||
if aws_sdk.found()
|
||||
# The AWS pkg-config adds -std=c++11.
|
||||
# https://github.com/aws/aws-sdk-cpp/issues/2673
|
||||
aws_sdk = aws_sdk.partial_dependency(
|
||||
compile_args : false,
|
||||
includes : true,
|
||||
link_args : true,
|
||||
links : true,
|
||||
sources : true,
|
||||
)
|
||||
deps += aws_sdk
|
||||
s = aws_sdk.version().split('.')
|
||||
configdata += {
|
||||
'AWS_VERSION_MAJOR': s[0].to_int(),
|
||||
'AWS_VERSION_MINOR': s[1].to_int(),
|
||||
'AWS_VERSION_PATCH': s[2].to_int(),
|
||||
}
|
||||
aws_sdk_transfer = dependency('aws-cpp-sdk-transfer', required : true).partial_dependency(
|
||||
compile_args : false,
|
||||
includes : true,
|
||||
link_args : true,
|
||||
links : true,
|
||||
sources : true,
|
||||
)
|
||||
endif
|
||||
|
||||
aws_s3 = dependency('aws-cpp-sdk-s3', required : false)
|
||||
if aws_s3.found()
|
||||
# The AWS pkg-config adds -std=c++11.
|
||||
# https://github.com/aws/aws-sdk-cpp/issues/2673
|
||||
aws_s3 = aws_s3.partial_dependency(
|
||||
compile_args : false,
|
||||
includes : true,
|
||||
link_args : true,
|
||||
links : true,
|
||||
sources : true,
|
||||
)
|
||||
deps += aws_s3
|
||||
endif
|
||||
|
||||
configdata += {
|
||||
'ENABLE_S3': aws_s3.found().to_int(),
|
||||
}
|
||||
|
||||
sqlite = dependency('sqlite3', 'sqlite', version : '>=3.6.19', required : true)
|
||||
deps += sqlite
|
||||
|
||||
sodium = dependency('libsodium', 'sodium', required : true)
|
||||
deps += sodium
|
||||
|
||||
curl = dependency('libcurl', 'curl', required : true)
|
||||
deps += curl
|
||||
|
||||
editline = dependency('libeditline', 'editline', version : '>=1.14', required : true)
|
||||
deps += editline
|
||||
|
||||
lowdown = dependency('lowdown', version : '>=0.9.0', required : true)
|
||||
deps += lowdown
|
||||
|
||||
# HACK(Qyriad): rapidcheck's pkg-config doesn't include the libs lol
|
||||
rapidcheck_meson = dependency('rapidcheck', required : enable_tests)
|
||||
rapidcheck = declare_dependency(dependencies : rapidcheck_meson, link_args : ['-lrapidcheck'])
|
||||
deps += rapidcheck
|
||||
|
||||
gtest = [
|
||||
dependency('gtest', required : enable_tests),
|
||||
dependency('gtest_main', required : enable_tests),
|
||||
dependency('gmock', required : enable_tests),
|
||||
dependency('gmock_main', required : enable_tests),
|
||||
]
|
||||
deps += gtest
|
||||
|
||||
toml11 = dependency('toml11', version : '>=3.7.0', required : true)
|
||||
deps += toml11
|
||||
|
||||
nlohmann_json = dependency('nlohmann_json', required : true)
|
||||
deps += nlohmann_json
|
||||
|
||||
#
|
||||
# Build-time tools
|
||||
#
|
||||
bash = find_program('bash')
|
||||
coreutils = find_program('coreutils')
|
||||
dot = find_program('dot', required : false)
|
||||
pymod = import('python')
|
||||
python = pymod.find_installation('python3')
|
||||
|
||||
# Used to workaround https://github.com/mesonbuild/meson/issues/2320 in src/nix/meson.build.
|
||||
installcmd = find_program('install')
|
||||
|
||||
sandbox_shell = get_option('sandbox-shell')
|
||||
# Consider it required if we're on Linux and the user explicitly specified a non-default value.
|
||||
sandbox_shell_required = sandbox_shell != 'busybox' and host_machine.system() == 'linux'
|
||||
# NOTE(Qyriad): package.nix puts busybox in buildInputs for Linux.
|
||||
# Most builds should not require setting this.
|
||||
busybox = find_program(sandbox_shell, required : sandbox_shell_required, native : false)
|
||||
if not busybox.found() and host_machine.system() == 'linux' and sandbox_shell_required
|
||||
warning('busybox not found and other sandbox shell was specified')
|
||||
warning('a sandbox shell is recommended on Linux -- configure with -Dsandbox-shell=/path/to/shell to set')
|
||||
endif
|
||||
# FIXME(Qyriad): the autoconf system checks that busybox has the "standalone" feature, indicating
|
||||
# that busybox sh won't run busybox applets as builtins (which would break our sandbox).
|
||||
|
||||
lsof = find_program('lsof')
|
||||
bison = find_program('bison')
|
||||
flex = find_program('flex')
|
||||
|
||||
# This is how Nix does generated headers...
|
||||
# other instances of header generation use a very similar command.
|
||||
# FIXME(Qyriad): do we really need to use the shell for this?
|
||||
gen_header_sh = 'echo \'R"__NIX_STR(\' | cat - @INPUT@ && echo \')__NIX_STR"\''
|
||||
gen_header = generator(
|
||||
bash,
|
||||
arguments : [ '-c', gen_header_sh ],
|
||||
capture : true,
|
||||
output : '@PLAINNAME@.gen.hh',
|
||||
)
|
||||
|
||||
#
|
||||
# Configuration
|
||||
#
|
||||
|
||||
run_command('ln', '-s',
|
||||
meson.project_build_root() / '__nothing_link_target',
|
||||
meson.project_build_root() / '__nothing_symlink',
|
||||
check : true,
|
||||
)
|
||||
can_link_symlink = run_command('ln',
|
||||
meson.project_build_root() / '__nothing_symlink',
|
||||
meson.project_build_root() / '__nothing_hardlink',
|
||||
check : false,
|
||||
).returncode() == 0
|
||||
run_command('rm', '-f',
|
||||
meson.project_build_root() / '__nothing_symlink',
|
||||
meson.project_build_root() / '__nothing_hardlink',
|
||||
check : true,
|
||||
)
|
||||
summary('can hardlink to symlink', can_link_symlink, bool_yn : true)
|
||||
configdata += { 'CAN_LINK_SYMLINK': can_link_symlink.to_int() }
|
||||
|
||||
|
||||
# Check for each of these functions, and create a define like `#define HAVE_LCHOWN 1`.
|
||||
check_funcs = [
|
||||
'lchown',
|
||||
'lutimes',
|
||||
'pipe2',
|
||||
'posix_fallocate',
|
||||
'statvfs',
|
||||
'strsignal',
|
||||
'sysconf',
|
||||
]
|
||||
foreach funcspec : check_funcs
|
||||
define_name = 'HAVE_' + funcspec.underscorify().to_upper()
|
||||
define_value = cxx.has_function(funcspec).to_int()
|
||||
configdata += {
|
||||
define_name: define_value,
|
||||
}
|
||||
endforeach
|
||||
|
||||
config_h = configure_file(
|
||||
configuration : {
|
||||
'PACKAGE_NAME': '"' + meson.project_name() + '"',
|
||||
'PACKAGE_VERSION': '"' + meson.project_version() + '"',
|
||||
'PACKAGE_TARNAME': '"' + meson.project_name() + '"',
|
||||
'PACKAGE_STRING': '"' + meson.project_name() + ' ' + meson.project_version() + '"',
|
||||
'HAVE_STRUCT_DIRENT_D_TYPE': 1, # FIXME: actually check this for solaris
|
||||
'SYSTEM': '"' + host_system + '"',
|
||||
} + configdata,
|
||||
output : 'config.h',
|
||||
)
|
||||
|
||||
install_headers(config_h, subdir : 'nix')
|
||||
|
||||
add_project_arguments(
|
||||
# TODO(Qyriad): Yes this is how the autoconf+Make system did it.
|
||||
# It would be nice for our headers to be idempotent instead.
|
||||
'-include', 'config.h',
|
||||
'-Wno-deprecated-declarations',
|
||||
'-Wimplicit-fallthrough',
|
||||
'-Werror=switch',
|
||||
'-Werror=switch-enum',
|
||||
language : 'cpp',
|
||||
)
|
||||
|
||||
if cxx.get_id() in ['gcc', 'clang']
|
||||
# 2024-03-24: jade benchmarked the default sanitize reporting in clang and got
|
||||
# a regression of about 10% on hackage-packages.nix with clang. So we are trapping instead.
|
||||
#
|
||||
# This has an overhead of 0-4% on gcc and unmeasurably little on clang, in
|
||||
# Nix evaluation benchmarks.
|
||||
#
|
||||
# N.B. Meson generates a completely nonsense warning here:
|
||||
# https://github.com/mesonbuild/meson/issues/9822
|
||||
# Both of these args cannot be written in the default meson configuration.
|
||||
# b_sanitize=signed-integer-overflow is ignored, and
|
||||
# -fsanitize-undefined-trap-on-error is not representable.
|
||||
sanitize_args = ['-fsanitize=signed-integer-overflow', '-fsanitize-undefined-trap-on-error']
|
||||
add_project_arguments(sanitize_args, language: 'cpp')
|
||||
add_project_link_arguments(sanitize_args, language: 'cpp')
|
||||
endif
|
||||
|
||||
add_project_link_arguments('-pthread', language : 'cpp')
|
||||
if cxx.get_linker_id() in ['ld.bfd', 'ld.gold']
|
||||
add_project_link_arguments('-Wl,--no-copy-dt-needed-entries', language : 'cpp')
|
||||
endif
|
||||
|
||||
# Generate Chromium tracing files for each compiled file, which enables
|
||||
# maintainers/buildtime_report.sh BUILD-DIR to simply work in clang builds.
|
||||
#
|
||||
# They can also be manually viewed at https://ui.perfetto.dev
|
||||
if get_option('profile-build').require(meson.get_compiler('cpp').get_id() == 'clang').enabled()
|
||||
add_project_arguments('-ftime-trace', language: 'cpp')
|
||||
endif
|
||||
|
||||
subdir('src')
|
||||
subdir('scripts')
|
||||
subdir('misc')
|
||||
subdir('doc/manual')
|
||||
|
||||
if enable_tests
|
||||
subdir('tests/unit')
|
||||
subdir('tests/functional')
|
||||
endif
|
||||
@@ -0,0 +1,48 @@
|
||||
# vim: filetype=meson
|
||||
option('gc', type : 'feature',
|
||||
description : 'enable garbage collection in the Nix expression evaluator (requires Boehm GC)',
|
||||
)
|
||||
# TODO(Qyriad): is this feature maintained?
|
||||
option('embedded-sandbox-shell', type : 'feature',
|
||||
description : 'include the sandbox shell in the Nix binary',
|
||||
)
|
||||
|
||||
option('cpuid', type : 'feature',
|
||||
description : 'determine microarchitecture levels with libcpuid (only relevant on x86_64)',
|
||||
)
|
||||
|
||||
option('seccomp-sandboxing', type : 'feature',
|
||||
description : 'build support for seccomp sandboxing (recommended unless your arch doesn\'t support libseccomp, only relevant on Linux)',
|
||||
)
|
||||
|
||||
option('sandbox-shell', type : 'string', value : 'busybox',
|
||||
description : 'path to a statically-linked shell to use as /bin/sh in sandboxes (usually busybox)',
|
||||
)
|
||||
|
||||
option('enable-tests', type : 'boolean', value : true,
|
||||
description : 'whether to enable tests or not (requires rapidcheck and gtest)',
|
||||
)
|
||||
|
||||
option('tests-color', type : 'boolean', value : true,
|
||||
description : 'set to false to disable color output in gtest',
|
||||
)
|
||||
|
||||
option('tests-brief', type : 'boolean', value : false,
|
||||
description : 'set to true for shorter tests output',
|
||||
)
|
||||
|
||||
option('profile-build', type : 'feature', value: 'disabled',
|
||||
description : 'whether to enable -ftime-trace in clang builds, allowing for speeding up the build.'
|
||||
)
|
||||
|
||||
option('store-dir', type : 'string', value : '/nix/store',
|
||||
description : 'path of the Nix store',
|
||||
)
|
||||
|
||||
option('state-dir', type : 'string', value : '/nix/var',
|
||||
description : 'path to store state in for Nix',
|
||||
)
|
||||
|
||||
option('log-dir', type : 'string', value : '/nix/var/log',
|
||||
description : 'path to store logs in for Nix',
|
||||
)
|
||||
Executable
+50
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/env bash
|
||||
# Meson will call this with an absolute path to Bash.
|
||||
# The shebang is just for convenience.
|
||||
|
||||
# The parser and lexer tab are generated via custom Meson targets in src/libexpr/meson.build,
|
||||
# but Meson doesn't support marking only part of a target for install. The generation creates
|
||||
# both headers (parser-tab.hh, lexer-tab.hh) and source files (parser-tab.cc, lexer-tab.cc),
|
||||
# and we definitely want the former installed, but not the latter. This script is added to
|
||||
# Meson's install steps to correct this, as the logic for it is just complex enough to
|
||||
# warrant separate and careful handling, because both Meson's configured include directory
|
||||
# may or may not be an absolute path, and DESTDIR may or may not be set at all, but can't be
|
||||
# manipulated in Meson logic.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
echo "cleanup-install: removing Meson-placed C++ sources from dest includedir"
|
||||
|
||||
if [[ "${1/--help/}" != "$1" ]]; then
|
||||
echo "cleanup-install: this script should only be called from the Meson build system"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Ensure the includedir was passed as the first argument
|
||||
# (set -u will make this fail otherwise).
|
||||
includedir="$1"
|
||||
# And then ensure that first argument is a directory that exists.
|
||||
if ! [[ -d "$1" ]]; then
|
||||
echo "cleanup-install: this script should only be called from the Meson build system"
|
||||
echo "argv[1] (${1@Q}) is not a directory"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# If DESTDIR environment variable is set, prepend it to the include dir.
|
||||
# Unfortunately, we cannot do this on the Meson side. We do have an environment variable
|
||||
# `MESON_INSTALL_DESTDIR_PREFIX`, but that will not refer to the include directory if
|
||||
# includedir has been set separately, which Lix's split-output derivation does.
|
||||
# We also cannot simply do an inline bash conditional like "${DESTDIR:=}" or similar,
|
||||
# because we need to specifically *join* DESTDIR and includedir with a slash, and *not*
|
||||
# have a slash if DESTDIR isn't set at all, since $includedir could be a relative directory.
|
||||
# Finally, DESTDIR is only available to us as an environment variable in these install scripts,
|
||||
# not in Meson logic.
|
||||
# Therefore, our best option is to have Meson pass this script the configured includedir,
|
||||
# and perform this dance with it and $DESTDIR.
|
||||
if [[ -n "${DESTDIR:-}" ]]; then
|
||||
includedir="$DESTDIR/$includedir"
|
||||
fi
|
||||
|
||||
# Intentionally not using -f.
|
||||
# If these files don't exist then our assumptions have been violated and we should fail.
|
||||
rm -v "$includedir/nix/parser-tab.cc" "$includedir/nix/lexer-tab.cc"
|
||||
Executable
+86
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
This script is a helper for this project's Meson buildsystem to run Lix's
|
||||
functional tests. It is an analogue to mk/run-test.sh in the autoconf+Make
|
||||
buildsystem.
|
||||
|
||||
These tests are run in the installCheckPhase in Lix's derivation, and as such
|
||||
expect to be run after the project has already been "installed" to some extent.
|
||||
Look at meson/setup-functional-tests.py for more details.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
name = 'run-test.py'
|
||||
|
||||
if 'MESON_BUILD_ROOT' not in os.environ:
|
||||
raise ValueError(f'{name}: this script must be run from the Meson build system')
|
||||
|
||||
def main():
|
||||
|
||||
tests_dir = Path(os.path.join(os.environ['MESON_BUILD_ROOT'], 'tests/functional'))
|
||||
|
||||
parser = argparse.ArgumentParser(name)
|
||||
parser.add_argument('target', help='the script path relative to tests/functional to run')
|
||||
args = parser.parse_args()
|
||||
|
||||
target = Path(args.target)
|
||||
# The test suite considers the test's name to be the path to the test relative to
|
||||
# `tests/functional`, but without the file extension.
|
||||
# e.g. for `tests/functional/flakes/develop.sh`, the test name is `flakes/develop`
|
||||
test_name = target.with_suffix('').as_posix()
|
||||
if not target.is_absolute():
|
||||
target = tests_dir.joinpath(target).resolve()
|
||||
|
||||
assert target.exists(), f'{name}: test {target} does not exist; did you run `meson install`?'
|
||||
|
||||
bash = os.environ.get('BASH', shutil.which('bash'))
|
||||
if bash is None:
|
||||
raise ValueError(f'{name}: bash executable not found and BASH environment variable not set')
|
||||
|
||||
test_environment = os.environ | {
|
||||
'TEST_NAME': test_name,
|
||||
# mk/run-test.sh did this, but I don't know if it has any effect since it seems
|
||||
# like the tests that interact with remote stores set it themselves?
|
||||
'NIX_REMOTE': '',
|
||||
}
|
||||
|
||||
# Initialize testing.
|
||||
init_result = subprocess.run([bash, '-e', 'init.sh'], cwd=tests_dir, env=test_environment)
|
||||
if init_result.returncode != 0:
|
||||
print(f'{name}: internal error initializing {args.target}', file=sys.stderr)
|
||||
print('[ERROR]')
|
||||
# Meson interprets exit code 99 as indicating an *error* in the testing process.
|
||||
return 99
|
||||
|
||||
# Run the test itself.
|
||||
test_result = subprocess.run([bash, '-e', target.name], cwd=target.parent, env=test_environment)
|
||||
|
||||
if test_result.returncode == 0:
|
||||
print('[PASS]')
|
||||
elif test_result.returncode == 99:
|
||||
print('[SKIP]')
|
||||
# Meson interprets exit code 77 as indicating a skipped test.
|
||||
return 77
|
||||
else:
|
||||
print('[FAIL]')
|
||||
|
||||
return test_result.returncode
|
||||
|
||||
try:
|
||||
sys.exit(main())
|
||||
except AssertionError as e:
|
||||
# This should mean that this test was run not-from-Meson, probably without
|
||||
# having run `meson install` first, which is not an bug in this script.
|
||||
print(e, file=sys.stderr)
|
||||
sys.exit(99)
|
||||
except Exception as e:
|
||||
print(f'{name}: INTERNAL ERROR running test ({sys.argv}): {e}', file=sys.stderr)
|
||||
print(f'this is a bug in {name}')
|
||||
sys.exit(99)
|
||||
Executable
+105
@@ -0,0 +1,105 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""
|
||||
So like. This script is cursed.
|
||||
It's a helper for this project's Meson buildsystem for Lix's functional tests.
|
||||
The functional tests are a bunch of bash scripts, that each expect to be run from the
|
||||
directory from the directory that that script is in, and also expect modifications to have
|
||||
happened to the source tree, and even splork files around. The last is against the spirit
|
||||
of Meson (and personally annoying), to have build processes that aren't self-contained in the
|
||||
out-of-source build directory, but more problematically we need configured files in the test
|
||||
tree.
|
||||
So. We copy the tests tree into the build directory.
|
||||
Meson doesn't have a good way of doing this natively -- the best you could do is subdir()
|
||||
into every directory in the tests tree and configure_file(copy : true) on every file,
|
||||
but this won't copy symlinks as symlinks, which we need since the test suite has, well,
|
||||
tests on symlinks.
|
||||
However, the functional tests are normally run during Lix's derivation's installCheckPhase,
|
||||
after Lix has already been "installed" somewhere. So in Meson we setup add this file as an
|
||||
install script and copy everything in tests/functional to the build directory, preserving
|
||||
things like symlinks, even broken ones (which are intentional).
|
||||
|
||||
TODO(Qyriad): when we remove the old build system entirely, we can instead fix the tests.
|
||||
"""
|
||||
|
||||
from pathlib import Path
|
||||
import os, os.path
|
||||
import shutil
|
||||
import sys
|
||||
import traceback
|
||||
|
||||
name = 'setup-functional-tests.py'
|
||||
|
||||
if 'MESON_SOURCE_ROOT' not in os.environ or 'MESON_BUILD_ROOT' not in os.environ:
|
||||
raise ValueError(f'{name}: this script must be run from the Meson build system')
|
||||
|
||||
print(f'{name}: mirroring tests/functional to build directory')
|
||||
|
||||
tests_source = Path(os.environ['MESON_SOURCE_ROOT']) / 'tests/functional'
|
||||
tests_build = Path(os.environ['MESON_BUILD_ROOT']) / 'tests/functional'
|
||||
|
||||
def main():
|
||||
|
||||
os.chdir(tests_build)
|
||||
|
||||
for src_dirpath, src_dirnames, src_filenames in os.walk(tests_source):
|
||||
src_dirpath = Path(src_dirpath)
|
||||
assert src_dirpath.is_absolute(), f'{src_dirpath=} is not absolute'
|
||||
|
||||
# os.walk() gives us the absolute path to the directory we're currently in as src_dirpath.
|
||||
# We want to mirror from the perspective of `tests_source`.
|
||||
rel_subdir = src_dirpath.relative_to(tests_source)
|
||||
assert (not rel_subdir.is_absolute()), f'{rel_subdir=} is not relative'
|
||||
|
||||
# And then join that relative path on `tests_build` to get the absolute
|
||||
# path in the build directory that corresponds to `src_dirpath`.
|
||||
build_dirpath = tests_build / rel_subdir
|
||||
assert build_dirpath.is_absolute(), f'{build_dirpath=} is not absolute'
|
||||
|
||||
# More concretely, for the test file tests/functional/ca/build.sh:
|
||||
# - src_dirpath is `$MESON_SOURCE_ROOT/tests/functional/ca`
|
||||
# - rel_subidr is `ca`
|
||||
# - build_dirpath is `$MESON_BUILD_ROOT/tests/functional/ca`
|
||||
|
||||
# `src_dirname` are directories underneath `src_dirpath`, and will be relative
|
||||
# to `src_dirpath`.
|
||||
for src_dirname in src_dirnames:
|
||||
# Take the name of the directory in the tests source and join it on `src_dirpath`
|
||||
# to get the full path to this specific directory in the tests source.
|
||||
src = src_dirpath / src_dirname
|
||||
# If there isn't *something* here, then our logic is wrong.
|
||||
# Path.exists(follow_symlinks=False) wasn't added until Python 3.12, so we use
|
||||
# os.path.lexists() here.
|
||||
assert os.path.lexists(src), f'{src=} does not exist'
|
||||
|
||||
# Take the name of this directory and join it on `build_dirpath` to get the full
|
||||
# path to the directory in `build/tests/functional` that we need to create.
|
||||
dest = build_dirpath / src_dirname
|
||||
if src.is_symlink():
|
||||
src_target = src.readlink()
|
||||
dest.unlink(missing_ok=True)
|
||||
dest.symlink_to(src_target)
|
||||
else:
|
||||
dest.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
for src_filename in src_filenames:
|
||||
# os.walk() should be giving us relative filenames.
|
||||
# If it isn't, our path joins will be veeeery wrong.
|
||||
assert (not Path(src_filename).is_absolute()), f'{src_filename=} is not relative'
|
||||
|
||||
src = src_dirpath / src_filename
|
||||
dst = build_dirpath / src_filename
|
||||
# Mildly misleading name -- unlink removes ordinary files as well as symlinks.
|
||||
dst.unlink(missing_ok=True)
|
||||
# shutil.copy2() best-effort preserves metadata.
|
||||
shutil.copy2(src, dst, follow_symlinks=False)
|
||||
|
||||
|
||||
try:
|
||||
sys.exit(main())
|
||||
except Exception as e:
|
||||
# Any error is likely a bug in this script.
|
||||
print(f'{name}: INTERNAL ERROR setting up functional tests: {e}', file=sys.stderr)
|
||||
print(traceback.format_exc())
|
||||
print(f'this is a bug in {name}')
|
||||
sys.exit(1)
|
||||
@@ -0,0 +1,8 @@
|
||||
configure_file(
|
||||
input : 'completion.sh',
|
||||
output : 'nix',
|
||||
install : true,
|
||||
install_dir : datadir / 'bash-completion/completions',
|
||||
install_mode : 'rw-r--r--',
|
||||
copy : true,
|
||||
)
|
||||
@@ -1,31 +0,0 @@
|
||||
{ mkDerivation, aeson, base, bytestring, cabal-install-parsers
|
||||
, Cabal-syntax, containers, directory, filepath, frontmatter
|
||||
, generic-lens-lite, lib, mtl, optparse-applicative, parsec, pretty
|
||||
, regex-applicative, text, pkgs
|
||||
}:
|
||||
let rev = "f30f6969e9cd8b56242309639d58acea21c99d06";
|
||||
in
|
||||
mkDerivation {
|
||||
pname = "changelog-d";
|
||||
version = "0.1";
|
||||
src = pkgs.fetchurl {
|
||||
name = "changelog-d-${rev}.tar.gz";
|
||||
url = "https://codeberg.org/roberth/changelog-d/archive/${rev}.tar.gz";
|
||||
hash = "sha256-8a2+i5u7YoszAgd5OIEW0eYUcP8yfhtoOIhLJkylYJ4=";
|
||||
} // { inherit rev; };
|
||||
isLibrary = false;
|
||||
isExecutable = true;
|
||||
libraryHaskellDepends = [
|
||||
aeson base bytestring cabal-install-parsers Cabal-syntax containers
|
||||
directory filepath frontmatter generic-lens-lite mtl parsec pretty
|
||||
regex-applicative text
|
||||
];
|
||||
executableHaskellDepends = [
|
||||
base bytestring Cabal-syntax directory filepath
|
||||
optparse-applicative
|
||||
];
|
||||
doHaddock = false;
|
||||
description = "Concatenate changelog entries into a single one";
|
||||
license = lib.licenses.gpl3Plus;
|
||||
mainProgram = "changelog-d";
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
# Taken temporarily from <nixpkgs/pkgs/by-name/ch/changelog-d/package.nix>
|
||||
{
|
||||
callPackage,
|
||||
lib,
|
||||
haskell,
|
||||
haskellPackages,
|
||||
}:
|
||||
|
||||
let
|
||||
hsPkg = haskellPackages.callPackage ./changelog-d.cabal.nix { };
|
||||
|
||||
addCompletions = haskellPackages.generateOptparseApplicativeCompletions ["changelog-d"];
|
||||
|
||||
haskellModifications =
|
||||
lib.flip lib.pipe [
|
||||
addCompletions
|
||||
haskell.lib.justStaticExecutables
|
||||
];
|
||||
|
||||
mkDerivationOverrides = finalAttrs: oldAttrs: {
|
||||
|
||||
version = oldAttrs.version + "-git-${lib.strings.substring 0 7 oldAttrs.src.rev}";
|
||||
|
||||
meta = oldAttrs.meta // {
|
||||
homepage = "https://codeberg.org/roberth/changelog-d";
|
||||
maintainers = [ lib.maintainers.roberth ];
|
||||
};
|
||||
|
||||
};
|
||||
in
|
||||
(haskellModifications hsPkg).overrideAttrs mkDerivationOverrides
|
||||
@@ -0,0 +1,27 @@
|
||||
# Upstreaming here, can be deleted once it's upstreamed:
|
||||
# https://github.com/NixOS/nixpkgs/pull/297102
|
||||
{ stdenv, lib, cmake, fetchFromGitHub }:
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "clangbuildanalyzer";
|
||||
version = "1.5.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "aras-p";
|
||||
repo = "ClangBuildAnalyzer";
|
||||
rev = "v${finalAttrs.version}";
|
||||
sha256 = "sha256-kmgdk634zM0W0OoRoP/RzepArSipa5bNqdVgdZO9gxo=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
cmake
|
||||
];
|
||||
|
||||
meta = {
|
||||
description = "Tool for analyzing Clang's -ftrace-time files";
|
||||
homepage = "https://github.com/aras-p/ClangBuildAnalyzer";
|
||||
maintainers = with lib.maintainers; [ lf- ];
|
||||
license = lib.licenses.unlicense;
|
||||
platforms = lib.platforms.unix;
|
||||
mainProgram = "ClangBuildAnalyzer";
|
||||
};
|
||||
})
|
||||
@@ -0,0 +1,8 @@
|
||||
configure_file(
|
||||
input : 'completion.fish',
|
||||
output : 'nix.fish',
|
||||
install : true,
|
||||
install_dir : datadir / 'fish/vendor_completions.d',
|
||||
install_mode : 'rw-r--r--',
|
||||
copy : true,
|
||||
)
|
||||
@@ -0,0 +1,5 @@
|
||||
subdir('bash')
|
||||
subdir('fish')
|
||||
subdir('zsh')
|
||||
|
||||
subdir('systemd')
|
||||
@@ -0,0 +1,25 @@
|
||||
foreach config : [ 'nix-daemon.socket', 'nix-daemon.service' ]
|
||||
configure_file(
|
||||
input : config + '.in',
|
||||
output : config,
|
||||
install : true,
|
||||
install_dir : prefix / 'lib/systemd/system',
|
||||
install_mode : 'rw-r--r--',
|
||||
configuration : {
|
||||
'storedir' : store_dir,
|
||||
'localstatedir' : state_dir,
|
||||
'bindir' : bindir,
|
||||
},
|
||||
)
|
||||
endforeach
|
||||
|
||||
configure_file(
|
||||
input : 'nix-daemon.conf.in',
|
||||
output : 'nix-daemon.conf',
|
||||
install : true,
|
||||
install_dir : prefix / 'lib/tmpfiles.d',
|
||||
install_mode : 'rw-r--r--',
|
||||
configuration : {
|
||||
'localstatedir' : state_dir,
|
||||
},
|
||||
)
|
||||
@@ -1,7 +0,0 @@
|
||||
ifdef HOST_LINUX
|
||||
|
||||
$(foreach n, nix-daemon.conf, $(eval $(call install-file-in, $(d)/$(n), $(sysconfdir)/init, 0644)))
|
||||
|
||||
clean-files += $(d)/nix-daemon.conf
|
||||
|
||||
endif
|
||||
@@ -1,5 +0,0 @@
|
||||
description "Nix Daemon"
|
||||
start on filesystem
|
||||
stop on shutdown
|
||||
respawn
|
||||
exec @bindir@/nix-daemon --daemon
|
||||
@@ -0,0 +1,10 @@
|
||||
foreach script : [ [ 'completion.zsh', '_nix' ], [ 'run-help-nix' ] ]
|
||||
configure_file(
|
||||
input : script[0],
|
||||
output : script.get(1, script[0]),
|
||||
install : true,
|
||||
install_dir : datadir / 'zsh/site-functions',
|
||||
install_mode : 'rw-r--r--',
|
||||
copy : true,
|
||||
)
|
||||
endforeach
|
||||
@@ -1,5 +1,5 @@
|
||||
%.gen.hh: %
|
||||
@echo 'R"foo(' >> $@.tmp
|
||||
@echo 'R"__NIX_STR(' >> $@.tmp
|
||||
$(trace-gen) cat $< >> $@.tmp
|
||||
@echo ')foo"' >> $@.tmp
|
||||
@echo ')__NIX_STR"' >> $@.tmp
|
||||
@mv $@.tmp $@
|
||||
|
||||
+1
-5
@@ -78,11 +78,7 @@ define build-library
|
||||
$(1)_LDFLAGS += -undefined suppress -flat_namespace
|
||||
endif
|
||||
else
|
||||
ifndef HOST_DARWIN
|
||||
ifndef HOST_CYGWIN
|
||||
$(1)_LDFLAGS += -Wl,-z,defs
|
||||
endif
|
||||
endif
|
||||
# -Wl,-z,defs is broken with sanitizers on Linux/clang at least.
|
||||
endif
|
||||
|
||||
ifndef HOST_DARWIN
|
||||
|
||||
+4
-1
@@ -6,6 +6,9 @@ programs-list :=
|
||||
# - $(1)_NAME: the name of the program (e.g. ‘foo’); defaults to
|
||||
# $(1).
|
||||
#
|
||||
# - $(1)_ENV: environment variables to set when running the program
|
||||
# from the Makefile using the $(1)_RUN target.
|
||||
#
|
||||
# - $(1)_DIR: the directory where the (non-installed) program will be
|
||||
# placed.
|
||||
#
|
||||
@@ -87,6 +90,6 @@ define build-program
|
||||
# Phony target to run this program (typically as a dependency of 'check').
|
||||
.PHONY: $(1)_RUN
|
||||
$(1)_RUN: $$($(1)_PATH)
|
||||
$(trace-test) $$(UNIT_TEST_ENV) $$($(1)_PATH)
|
||||
$(trace-test) $$($(1)_ENV) $$($(1)_PATH)
|
||||
|
||||
endef
|
||||
|
||||
+321
@@ -0,0 +1,321 @@
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
stdenv,
|
||||
autoconf-archive,
|
||||
autoreconfHook,
|
||||
aws-sdk-cpp,
|
||||
boehmgc,
|
||||
nlohmann_json,
|
||||
bison,
|
||||
build-release-notes,
|
||||
boost,
|
||||
brotli,
|
||||
bzip2,
|
||||
cmake,
|
||||
curl,
|
||||
doxygen,
|
||||
editline,
|
||||
fileset,
|
||||
flex,
|
||||
git,
|
||||
gtest,
|
||||
jq,
|
||||
libarchive,
|
||||
libcpuid,
|
||||
libseccomp,
|
||||
libsodium,
|
||||
lsof,
|
||||
lowdown,
|
||||
mdbook,
|
||||
mdbook-linkcheck,
|
||||
mercurial,
|
||||
meson,
|
||||
ninja,
|
||||
openssl,
|
||||
pkg-config,
|
||||
rapidcheck,
|
||||
sqlite,
|
||||
toml11,
|
||||
util-linuxMinimal ? utillinuxMinimal,
|
||||
utillinuxMinimal ? null,
|
||||
xz,
|
||||
|
||||
busybox-sandbox-shell,
|
||||
|
||||
pname ? "nix",
|
||||
versionSuffix ? "",
|
||||
officialRelease ? true,
|
||||
# Set to true to build the release notes for the next release.
|
||||
buildUnreleasedNotes ? false,
|
||||
internalApiDocs ? false,
|
||||
# Avoid setting things that would interfere with a functioning devShell
|
||||
forDevShell ? false,
|
||||
|
||||
# FIXME(Qyriad): build Lix using Meson instead of autoconf and make.
|
||||
# This flag will be removed when the migration to Meson is complete.
|
||||
buildWithMeson ? false,
|
||||
|
||||
# Not a real argument, just the only way to approximate let-binding some
|
||||
# stuff for argument defaults.
|
||||
__forDefaults ? {
|
||||
canRunInstalled = stdenv.buildPlatform.canExecute stdenv.hostPlatform;
|
||||
},
|
||||
}: let
|
||||
inherit (__forDefaults) canRunInstalled;
|
||||
|
||||
version = lib.fileContents ./.version + versionSuffix;
|
||||
|
||||
aws-sdk-cpp-nix = aws-sdk-cpp.override {
|
||||
apis = [ "s3" "transfer" ];
|
||||
customMemoryManagement = false;
|
||||
};
|
||||
|
||||
testConfigureFlags = [
|
||||
"RAPIDCHECK_HEADERS=${lib.getDev rapidcheck}/extras/gtest/include"
|
||||
];
|
||||
|
||||
# The internal API docs need these for the build, but if we're not building
|
||||
# Nix itself, then these don't need to be propagated.
|
||||
maybePropagatedInputs = [
|
||||
boehmgc
|
||||
nlohmann_json
|
||||
];
|
||||
|
||||
# .gitignore has already been processed, so any changes in it are irrelevant
|
||||
# at this point. It is not represented verbatim for test purposes because
|
||||
# that would interfere with repo semantics.
|
||||
baseFiles = fileset.fileFilter (f: f.name != ".gitignore") ./.;
|
||||
|
||||
configureFiles = fileset.unions [
|
||||
./.version
|
||||
./configure.ac
|
||||
./m4
|
||||
# TODO: do we really need README.md? It doesn't seem used in the build.
|
||||
./README.md
|
||||
];
|
||||
|
||||
topLevelBuildFiles = fileset.unions ([
|
||||
./local.mk
|
||||
./Makefile
|
||||
./Makefile.config.in
|
||||
./mk
|
||||
] ++ lib.optionals buildWithMeson [
|
||||
./meson.build
|
||||
./meson.options
|
||||
./meson
|
||||
./scripts/meson.build
|
||||
]);
|
||||
|
||||
functionalTestFiles = fileset.unions [
|
||||
./tests/functional
|
||||
./tests/unit
|
||||
(fileset.fileFilter (f: lib.strings.hasPrefix "nix-profile" f.name) ./scripts)
|
||||
];
|
||||
|
||||
in stdenv.mkDerivation (finalAttrs: {
|
||||
inherit pname version;
|
||||
|
||||
src = fileset.toSource {
|
||||
root = ./.;
|
||||
fileset = fileset.intersection baseFiles (fileset.unions ([
|
||||
configureFiles
|
||||
topLevelBuildFiles
|
||||
functionalTestFiles
|
||||
] ++ lib.optionals (!finalAttrs.dontBuild || internalApiDocs) [
|
||||
./boehmgc-coroutine-sp-fallback.diff
|
||||
./doc
|
||||
./misc
|
||||
./precompiled-headers.h
|
||||
./src
|
||||
./COPYING
|
||||
./scripts/local.mk
|
||||
]));
|
||||
};
|
||||
|
||||
VERSION_SUFFIX = versionSuffix;
|
||||
|
||||
outputs = [ "out" ]
|
||||
++ lib.optionals (!finalAttrs.dontBuild) [ "dev" "doc" ];
|
||||
|
||||
dontBuild = false;
|
||||
|
||||
# FIXME(Qyriad): see if this is still needed once the migration to Meson is completed.
|
||||
mesonFlags = lib.optionals (buildWithMeson && stdenv.hostPlatform.isLinux) [
|
||||
"-Dsandbox-shell=${lib.getBin busybox-sandbox-shell}/bin/busybox"
|
||||
];
|
||||
|
||||
# We only include CMake so that Meson can locate toml11, which only ships CMake dependency metadata.
|
||||
dontUseCmakeConfigure = true;
|
||||
|
||||
nativeBuildInputs = [
|
||||
bison
|
||||
flex
|
||||
] ++ [
|
||||
(lib.getBin lowdown)
|
||||
mdbook
|
||||
mdbook-linkcheck
|
||||
autoconf-archive
|
||||
] ++ lib.optional (!buildWithMeson) autoreconfHook ++ [
|
||||
pkg-config
|
||||
|
||||
# Tests
|
||||
git
|
||||
mercurial
|
||||
jq
|
||||
lsof
|
||||
] ++ lib.optional stdenv.hostPlatform.isLinux util-linuxMinimal
|
||||
++ lib.optional (!officialRelease && buildUnreleasedNotes) build-release-notes
|
||||
++ lib.optional internalApiDocs doxygen
|
||||
++ lib.optionals buildWithMeson [
|
||||
meson
|
||||
ninja
|
||||
cmake
|
||||
];
|
||||
|
||||
buildInputs = [
|
||||
curl
|
||||
bzip2
|
||||
xz
|
||||
brotli
|
||||
editline
|
||||
openssl
|
||||
sqlite
|
||||
libarchive
|
||||
boost
|
||||
lowdown
|
||||
libsodium
|
||||
toml11
|
||||
]
|
||||
++ lib.optionals stdenv.hostPlatform.isLinux [ libseccomp busybox-sandbox-shell ]
|
||||
++ lib.optional stdenv.hostPlatform.isx86_64 libcpuid
|
||||
# There have been issues building these dependencies
|
||||
++ lib.optional (stdenv.hostPlatform == stdenv.buildPlatform) aws-sdk-cpp-nix
|
||||
++ lib.optionals (finalAttrs.dontBuild) maybePropagatedInputs
|
||||
;
|
||||
|
||||
checkInputs = [
|
||||
gtest
|
||||
rapidcheck
|
||||
];
|
||||
|
||||
propagatedBuildInputs = lib.optionals (!finalAttrs.dontBuild) maybePropagatedInputs;
|
||||
|
||||
disallowedReferences = [
|
||||
boost
|
||||
];
|
||||
|
||||
# Needed for Meson to find Boost.
|
||||
# https://github.com/NixOS/nixpkgs/issues/86131.
|
||||
env = lib.optionalAttrs (buildWithMeson || forDevShell) {
|
||||
BOOST_INCLUDEDIR = "${lib.getDev boost}/include";
|
||||
BOOST_LIBRARYDIR = "${lib.getLib boost}/lib";
|
||||
};
|
||||
|
||||
preConfigure = lib.optionalString (!finalAttrs.dontBuild && !stdenv.hostPlatform.isStatic) ''
|
||||
# Copy libboost_context so we don't get all of Boost in our closure.
|
||||
# https://github.com/NixOS/nixpkgs/issues/45462
|
||||
mkdir -p $out/lib
|
||||
cp -pd ${boost}/lib/{libboost_context*,libboost_thread*,libboost_system*} $out/lib
|
||||
rm -f $out/lib/*.a
|
||||
'' + lib.optionalString (!finalAttrs.dontBuild && stdenv.hostPlatform.isLinux) ''
|
||||
chmod u+w $out/lib/*.so.*
|
||||
patchelf --set-rpath $out/lib:${stdenv.cc.cc.lib}/lib $out/lib/libboost_thread.so.*
|
||||
'' + lib.optionalString (!finalAttrs.dontBuild && stdenv.hostPlatform.isDarwin) ''
|
||||
for LIB in $out/lib/*.dylib; do
|
||||
chmod u+w $LIB
|
||||
install_name_tool -id $LIB $LIB
|
||||
install_name_tool -delete_rpath ${boost}/lib/ $LIB || true
|
||||
done
|
||||
install_name_tool -change ${boost}/lib/libboost_system.dylib $out/lib/libboost_system.dylib $out/lib/libboost_thread.dylib
|
||||
'' + ''
|
||||
# Workaround https://github.com/NixOS/nixpkgs/issues/294890.
|
||||
if [[ -n "''${doCheck:-}" ]]; then
|
||||
appendToVar configureFlags "--enable-tests"
|
||||
else
|
||||
appendToVar configureFlags "--disable-tests"
|
||||
fi
|
||||
'';
|
||||
|
||||
configureFlags = lib.optionals stdenv.isLinux [
|
||||
"--with-boost=${boost}/lib"
|
||||
"--with-sandbox-shell=${busybox-sandbox-shell}/bin/busybox"
|
||||
] ++ lib.optionals (stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) [
|
||||
"LDFLAGS=-fuse-ld=gold"
|
||||
]
|
||||
++ lib.optional stdenv.hostPlatform.isStatic "--enable-embedded-sandbox-shell"
|
||||
++ lib.optionals (finalAttrs.doCheck || internalApiDocs) testConfigureFlags
|
||||
++ lib.optional (!canRunInstalled) "--disable-doc-gen"
|
||||
++ [ (lib.enableFeature internalApiDocs "internal-api-docs") ]
|
||||
++ lib.optional (!forDevShell) "--sysconfdir=/etc"
|
||||
++ [
|
||||
"TOML11_HEADERS=${lib.getDev toml11}/include"
|
||||
];
|
||||
|
||||
mesonBuildType = lib.optional (buildWithMeson || forDevShell) "debugoptimized";
|
||||
|
||||
installTargets = lib.optional internalApiDocs "internal-api-html";
|
||||
|
||||
enableParallelBuilding = true;
|
||||
|
||||
makeFlags = "profiledir=$(out)/etc/profile.d PRECOMPILE_HEADERS=1";
|
||||
|
||||
doCheck = true;
|
||||
|
||||
mesonCheckFlags = lib.optionals (buildWithMeson || forDevShell) [
|
||||
"--suite=check"
|
||||
];
|
||||
|
||||
installFlags = "sysconfdir=$(out)/etc";
|
||||
|
||||
postInstall = lib.optionalString (!finalAttrs.dontBuild) ''
|
||||
mkdir -p $doc/nix-support
|
||||
echo "doc manual $doc/share/doc/nix/manual" >> $doc/nix-support/hydra-build-products
|
||||
'' + lib.optionalString stdenv.hostPlatform.isStatic ''
|
||||
mkdir -p $out/nix-support
|
||||
echo "file binary-dist $out/bin/nix" >> $out/nix-support/hydra-build-products
|
||||
'' + lib.optionalString stdenv.isDarwin ''
|
||||
for lib in libnixutil.dylib libnixexpr.dylib; do
|
||||
install_name_tool \
|
||||
-change "${lib.getLib boost}/lib/libboost_context.dylib" \
|
||||
"$out/lib/libboost_context.dylib" \
|
||||
"$out/lib/$lib"
|
||||
done
|
||||
'' + lib.optionalString internalApiDocs ''
|
||||
mkdir -p $out/nix-support
|
||||
echo "doc internal-api-docs $out/share/doc/nix/internal-api/html" >> "$out/nix-support/hydra-build-products"
|
||||
'';
|
||||
|
||||
doInstallCheck = finalAttrs.doCheck;
|
||||
installCheckFlags = "sysconfdir=$(out)/etc";
|
||||
installCheckTarget = "installcheck"; # work around buggy detection in stdenv
|
||||
|
||||
mesonInstallCheckFlags = [
|
||||
"--suite=installcheck"
|
||||
];
|
||||
|
||||
preInstallCheck = lib.optionalString stdenv.hostPlatform.isDarwin ''
|
||||
export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
|
||||
'';
|
||||
|
||||
installCheckPhase = lib.optionalString buildWithMeson ''
|
||||
runHook preInstallCheck
|
||||
flagsArray=($mesonInstallCheckFlags "''${mesonInstallCheckFlagsArray[@]}")
|
||||
meson test --no-rebuild "''${flagsArray[@]}"
|
||||
runHook postInstallCheck
|
||||
'';
|
||||
|
||||
separateDebugInfo = !stdenv.hostPlatform.isStatic && !finalAttrs.dontBuild;
|
||||
|
||||
strictDeps = true;
|
||||
|
||||
# strictoverflow is disabled because we trap on signed overflow instead
|
||||
hardeningDisable = [ "strictoverflow" ]
|
||||
++ lib.optional stdenv.hostPlatform.isStatic "pie";
|
||||
|
||||
meta.platforms = lib.platforms.unix;
|
||||
|
||||
passthru.perl-bindings = pkgs.callPackage ./perl {
|
||||
inherit fileset stdenv;
|
||||
};
|
||||
})
|
||||
+2
-5
@@ -36,15 +36,12 @@ perl.pkgs.toPerlModule (stdenv.mkDerivation {
|
||||
xz
|
||||
perl
|
||||
boost
|
||||
perlPackages.DBI
|
||||
perlPackages.DBDSQLite
|
||||
]
|
||||
++ lib.optional (stdenv.isLinux || stdenv.isDarwin) libsodium
|
||||
++ lib.optional stdenv.isDarwin darwin.apple_sdk.frameworks.Security;
|
||||
|
||||
configureFlags = [
|
||||
"--with-dbi=${perlPackages.DBI}/${perl.libPrefix}"
|
||||
"--with-dbd-sqlite=${perlPackages.DBDSQLite}/${perl.libPrefix}"
|
||||
];
|
||||
|
||||
enableParallelBuilding = true;
|
||||
|
||||
postUnpack = "sourceRoot=$sourceRoot/perl";
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
((NEW_NIX_FIRST_BUILD_UID=301))
|
||||
|
||||
id_available(){
|
||||
dscl . list /Users UniqueID | grep -E '\b'$1'\b' >/dev/null
|
||||
}
|
||||
|
||||
change_nixbld_names_and_ids(){
|
||||
local name uid next_id
|
||||
((next_id=NEW_NIX_FIRST_BUILD_UID))
|
||||
echo "Attempting to migrate nixbld users."
|
||||
echo "Each user should change from nixbld# to _nixbld#"
|
||||
echo "and their IDs relocated to $next_id+"
|
||||
while read -r name uid; do
|
||||
echo " Checking $name (uid: $uid)"
|
||||
# iterate for a clean ID
|
||||
while id_available "$next_id"; do
|
||||
((next_id++))
|
||||
if ((next_id >= 400)); then
|
||||
echo "We've hit UID 400 without placing all of your users :("
|
||||
echo "You should use the commands in this script as a starting"
|
||||
echo "point to review your UID-space and manually move the"
|
||||
echo "remaining users (or delete them, if you don't need them)."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $name == _* ]]; then
|
||||
echo " It looks like $name has already been renamed--skipping."
|
||||
else
|
||||
# first 3 are cleanup, it's OK if they aren't here
|
||||
sudo dscl . delete /Users/$name dsAttrTypeNative:_writers_passwd &>/dev/null || true
|
||||
sudo dscl . change /Users/$name NFSHomeDirectory "/private/var/empty 1" "/var/empty" &>/dev/null || true
|
||||
# remove existing user from group
|
||||
sudo dseditgroup -o edit -t user -d $name nixbld || true
|
||||
sudo dscl . change /Users/$name UniqueID $uid $next_id
|
||||
sudo dscl . change /Users/$name RecordName $name _$name
|
||||
# add renamed user to group
|
||||
sudo dseditgroup -o edit -t user -a _$name nixbld
|
||||
echo " $name migrated to _$name (uid: $next_id)"
|
||||
fi
|
||||
done < <(dscl . list /Users UniqueID | grep nixbld | sort -n -k2)
|
||||
}
|
||||
|
||||
change_nixbld_names_and_ids
|
||||
@@ -1,33 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
# set -x
|
||||
|
||||
|
||||
# mapfile BUILDS_FOR_LATEST_EVAL < <(
|
||||
# curl -H 'Accept: application/json' https://hydra.nixos.org/jobset/nix/master/evals | \
|
||||
# jq -r '.evals[0].builds[] | @sh')
|
||||
BUILDS_FOR_LATEST_EVAL=$(
|
||||
curl -sS -H 'Accept: application/json' https://hydra.nixos.org/jobset/nix/master/evals | \
|
||||
jq -r '.evals[0].builds[]')
|
||||
|
||||
someBuildFailed=0
|
||||
|
||||
for buildId in $BUILDS_FOR_LATEST_EVAL; do
|
||||
buildInfo=$(curl --fail -sS -H 'Accept: application/json' "https://hydra.nixos.org/build/$buildId")
|
||||
|
||||
finished=$(echo "$buildInfo" | jq -r '.finished')
|
||||
|
||||
if [[ $finished = 0 ]]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
buildStatus=$(echo "$buildInfo" | jq -r '.buildstatus')
|
||||
|
||||
if [[ $buildStatus != 0 ]]; then
|
||||
someBuildFailed=1
|
||||
echo "Job “$(echo "$buildInfo" | jq -r '.job')” failed on hydra: $buildInfo"
|
||||
fi
|
||||
done
|
||||
|
||||
exit "$someBuildFailed"
|
||||
@@ -1,875 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eu
|
||||
set -o pipefail
|
||||
|
||||
# I'm a little agnostic on the choices, but supporting a wide
|
||||
# slate of uses for now, including:
|
||||
# - import-only: `. create-darwin-volume.sh no-main[ ...]`
|
||||
# - legacy: `./create-darwin-volume.sh` or `. create-darwin-volume.sh`
|
||||
# (both will run main())
|
||||
# - external alt-routine: `./create-darwin-volume.sh no-main func[ ...]`
|
||||
if [ "${1-}" = "no-main" ]; then
|
||||
shift
|
||||
readonly _CREATE_VOLUME_NO_MAIN=1
|
||||
else
|
||||
readonly _CREATE_VOLUME_NO_MAIN=0
|
||||
# declare some things we expect to inherit from install-multi-user
|
||||
# I don't love this (because it's a bit of a kludge).
|
||||
#
|
||||
# CAUTION: (Dec 19 2020)
|
||||
# This is a stopgap. It doesn't cover the full slate of
|
||||
# identifiers we inherit--just those necessary to:
|
||||
# - avoid breaking direct invocations of this script (here/now)
|
||||
# - avoid hard-to-reverse structural changes before the call to rm
|
||||
# single-user support is verified
|
||||
#
|
||||
# In the near-mid term, I (personally) think we should:
|
||||
# - decide to deprecate the direct call and add a notice
|
||||
# - fold all of this into install-darwin-multi-user.sh
|
||||
# - intentionally remove the old direct-invocation form (kill the
|
||||
# routine, replace this script w/ deprecation notice and a note
|
||||
# on the remove-after date)
|
||||
#
|
||||
readonly NIX_ROOT="${NIX_ROOT:-/nix}"
|
||||
|
||||
_sudo() {
|
||||
shift # throw away the 'explanation'
|
||||
/usr/bin/sudo "$@"
|
||||
}
|
||||
failure() {
|
||||
if [ "$*" = "" ]; then
|
||||
cat
|
||||
else
|
||||
echo "$@"
|
||||
fi
|
||||
exit 1
|
||||
}
|
||||
task() {
|
||||
echo "$@"
|
||||
}
|
||||
fi
|
||||
|
||||
# usually "disk1"
|
||||
root_disk_identifier() {
|
||||
# For performance (~10ms vs 280ms) I'm parsing 'diskX' from stat output
|
||||
# (~diskXsY)--but I'm retaining the more-semantic approach since
|
||||
# it documents intent better.
|
||||
# /usr/sbin/diskutil info -plist / | xmllint --xpath "/plist/dict/key[text()='ParentWholeDisk']/following-sibling::string[1]/text()" -
|
||||
#
|
||||
local special_device
|
||||
special_device="$(/usr/bin/stat -f "%Sd" /)"
|
||||
echo "${special_device%s[0-9]*}"
|
||||
}
|
||||
|
||||
# make it easy to play w/ 'Case-sensitive APFS'
|
||||
readonly NIX_VOLUME_FS="${NIX_VOLUME_FS:-APFS}"
|
||||
readonly NIX_VOLUME_LABEL="${NIX_VOLUME_LABEL:-Nix Store}"
|
||||
# Strongly assuming we'll make a volume on the device / is on
|
||||
# But you can override NIX_VOLUME_USE_DISK to create it on some other device
|
||||
readonly NIX_VOLUME_USE_DISK="${NIX_VOLUME_USE_DISK:-$(root_disk_identifier)}"
|
||||
NIX_VOLUME_USE_SPECIAL="${NIX_VOLUME_USE_SPECIAL:-}"
|
||||
NIX_VOLUME_USE_UUID="${NIX_VOLUME_USE_UUID:-}"
|
||||
readonly NIX_VOLUME_MOUNTD_DEST="${NIX_VOLUME_MOUNTD_DEST:-/Library/LaunchDaemons/org.nixos.darwin-store.plist}"
|
||||
|
||||
if /usr/bin/fdesetup isactive >/dev/null; then
|
||||
test_filevault_in_use() { return 0; }
|
||||
# no readonly; we may modify if user refuses from cure_volume
|
||||
NIX_VOLUME_DO_ENCRYPT="${NIX_VOLUME_DO_ENCRYPT:-1}"
|
||||
else
|
||||
test_filevault_in_use() { return 1; }
|
||||
NIX_VOLUME_DO_ENCRYPT="${NIX_VOLUME_DO_ENCRYPT:-0}"
|
||||
fi
|
||||
|
||||
should_encrypt_volume() {
|
||||
test_filevault_in_use && (( NIX_VOLUME_DO_ENCRYPT == 1 ))
|
||||
}
|
||||
|
||||
substep() {
|
||||
printf " %s\n" "" "- $1" "" "${@:2}"
|
||||
}
|
||||
|
||||
|
||||
volumes_labeled() {
|
||||
local label="$1"
|
||||
xsltproc --novalid --stringparam label "$label" - <(/usr/sbin/ioreg -ra -c "AppleAPFSVolume") <<'EOF'
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||
<xsl:output method="text"/>
|
||||
<xsl:template match="/">
|
||||
<xsl:apply-templates select="/plist/array/dict/key[text()='IORegistryEntryName']/following-sibling::*[1][text()=$label]/.."/>
|
||||
</xsl:template>
|
||||
<xsl:template match="dict">
|
||||
<xsl:apply-templates match="string" select="key[text()='BSD Name']/following-sibling::*[1]"/>
|
||||
<xsl:text>=</xsl:text>
|
||||
<xsl:apply-templates match="string" select="key[text()='UUID']/following-sibling::*[1]"/>
|
||||
<xsl:text>
</xsl:text>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
EOF
|
||||
# I cut label out of the extracted values, but here it is for reference:
|
||||
# <xsl:apply-templates match="string" select="key[text()='IORegistryEntryName']/following-sibling::*[1]"/>
|
||||
# <xsl:text>=</xsl:text>
|
||||
}
|
||||
|
||||
right_disk() {
|
||||
local volume_special="$1" # (i.e., disk1s7)
|
||||
[[ "$volume_special" == "$NIX_VOLUME_USE_DISK"s* ]]
|
||||
}
|
||||
|
||||
right_volume() {
|
||||
local volume_special="$1" # (i.e., disk1s7)
|
||||
# if set, it must match; otherwise ensure it's on the right disk
|
||||
if [ -z "$NIX_VOLUME_USE_SPECIAL" ]; then
|
||||
if right_disk "$volume_special"; then
|
||||
NIX_VOLUME_USE_SPECIAL="$volume_special" # latch on
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
[ "$volume_special" = "$NIX_VOLUME_USE_SPECIAL" ]
|
||||
fi
|
||||
}
|
||||
|
||||
right_uuid() {
|
||||
local volume_uuid="$1"
|
||||
# if set, it must match; otherwise allow
|
||||
if [ -z "$NIX_VOLUME_USE_UUID" ]; then
|
||||
NIX_VOLUME_USE_UUID="$volume_uuid" # latch on
|
||||
return 0
|
||||
else
|
||||
[ "$volume_uuid" = "$NIX_VOLUME_USE_UUID" ]
|
||||
fi
|
||||
}
|
||||
|
||||
cure_volumes() {
|
||||
local found volume special uuid
|
||||
# loop just in case they have more than one volume
|
||||
# (nothing stops you from doing this)
|
||||
for volume in $(volumes_labeled "$NIX_VOLUME_LABEL"); do
|
||||
# CAUTION: this could (maybe) be a more normal read
|
||||
# loop like:
|
||||
# while IFS== read -r special uuid; do
|
||||
# # ...
|
||||
# done <<<"$(volumes_labeled "$NIX_VOLUME_LABEL")"
|
||||
#
|
||||
# I did it with for to skirt a problem with the obvious
|
||||
# pattern replacing stdin and causing user prompts
|
||||
# inside (which also use read and access stdin) to skip
|
||||
#
|
||||
# If there's an existing encrypted volume we can't find
|
||||
# in keychain, the user never gets prompted to delete
|
||||
# the volume, and the install fails.
|
||||
#
|
||||
# If you change this, a human needs to test a very
|
||||
# specific scenario: you already have an encrypted
|
||||
# Nix Store volume, and have deleted its credential
|
||||
# from keychain. Ensure the script asks you if it can
|
||||
# delete the volume, and then prompts for your sudo
|
||||
# password to confirm.
|
||||
#
|
||||
# shellcheck disable=SC1097
|
||||
IFS== read -r special uuid <<< "$volume"
|
||||
# take the first one that's on the right disk
|
||||
if [ -z "${found:-}" ]; then
|
||||
if right_volume "$special" && right_uuid "$uuid"; then
|
||||
cure_volume "$special" "$uuid"
|
||||
found="${special} (${uuid})"
|
||||
else
|
||||
warning <<EOF
|
||||
Ignoring ${special} (${uuid}) because I am looking for:
|
||||
disk=${NIX_VOLUME_USE_DISK} special=${NIX_VOLUME_USE_SPECIAL:-${NIX_VOLUME_USE_DISK}sX} uuid=${NIX_VOLUME_USE_UUID:-any}
|
||||
EOF
|
||||
# TODO: give chance to delete if ! headless?
|
||||
fi
|
||||
else
|
||||
warning <<EOF
|
||||
Ignoring ${special} (${uuid}), already found target: $found
|
||||
EOF
|
||||
# TODO reminder? I feel like I want one
|
||||
# idiom that reminds some warnings, or warns
|
||||
# some reminders?
|
||||
# TODO: if ! headless, chance to delete?
|
||||
fi
|
||||
done
|
||||
if [ -z "${found:-}" ]; then
|
||||
readonly NIX_VOLUME_USE_SPECIAL NIX_VOLUME_USE_UUID
|
||||
fi
|
||||
}
|
||||
|
||||
volume_encrypted() {
|
||||
local volume_special="$1" # (i.e., disk1s7)
|
||||
# Trying to match the first line of output; known first lines:
|
||||
# No cryptographic users for <special>
|
||||
# Cryptographic user for <special> (1 found)
|
||||
# Cryptographic users for <special> (2 found)
|
||||
/usr/sbin/diskutil apfs listCryptoUsers -plist "$volume_special" | /usr/bin/grep -q APFSCryptoUserUUID
|
||||
}
|
||||
|
||||
test_fstab() {
|
||||
/usr/bin/grep -q "$NIX_ROOT apfs rw" /etc/fstab 2>/dev/null
|
||||
}
|
||||
|
||||
test_nix_root_is_symlink() {
|
||||
[ -L "$NIX_ROOT" ]
|
||||
}
|
||||
|
||||
test_synthetic_conf_either(){
|
||||
/usr/bin/grep -qE "^${NIX_ROOT:1}($|\t.{3,}$)" /etc/synthetic.conf 2>/dev/null
|
||||
}
|
||||
|
||||
test_synthetic_conf_mountable() {
|
||||
/usr/bin/grep -q "^${NIX_ROOT:1}$" /etc/synthetic.conf 2>/dev/null
|
||||
}
|
||||
|
||||
test_synthetic_conf_symlinked() {
|
||||
/usr/bin/grep -qE "^${NIX_ROOT:1}\t.{3,}$" /etc/synthetic.conf 2>/dev/null
|
||||
}
|
||||
|
||||
test_nix_volume_mountd_installed() {
|
||||
test -e "$NIX_VOLUME_MOUNTD_DEST"
|
||||
}
|
||||
|
||||
# current volume password
|
||||
test_keychain_by_uuid() {
|
||||
local volume_uuid="$1"
|
||||
# Note: doesn't need sudo just to check; doesn't output pw
|
||||
security find-generic-password -s "$volume_uuid" &>/dev/null
|
||||
}
|
||||
|
||||
get_volume_pass() {
|
||||
local volume_uuid="$1"
|
||||
_sudo \
|
||||
"to confirm keychain has a password that unlocks this volume" \
|
||||
security find-generic-password -s "$volume_uuid" -w
|
||||
}
|
||||
|
||||
verify_volume_pass() {
|
||||
local volume_special="$1" # (i.e., disk1s7)
|
||||
local volume_uuid="$2"
|
||||
_sudo "to confirm the password actually unlocks the volume" \
|
||||
/usr/sbin/diskutil apfs unlockVolume "$volume_special" -verify -stdinpassphrase -user "$volume_uuid"
|
||||
}
|
||||
|
||||
volume_pass_works() {
|
||||
local volume_special="$1" # (i.e., disk1s7)
|
||||
local volume_uuid="$2"
|
||||
get_volume_pass "$volume_uuid" | verify_volume_pass "$volume_special" "$volume_uuid"
|
||||
}
|
||||
|
||||
# Create the paths defined in synthetic.conf, saving us a reboot.
|
||||
create_synthetic_objects() {
|
||||
# Big Sur takes away the -B flag we were using and replaces it
|
||||
# with a -t flag that appears to do the same thing (but they
|
||||
# don't behave exactly the same way in terms of return values).
|
||||
# This feels a little dirty, but as far as I can tell the
|
||||
# simplest way to get the right one is to just throw away stderr
|
||||
# and call both... :]
|
||||
{
|
||||
/System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -t || true # Big Sur
|
||||
/System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -B || true # Catalina
|
||||
} >/dev/null 2>&1
|
||||
}
|
||||
|
||||
test_nix() {
|
||||
test -d "$NIX_ROOT"
|
||||
}
|
||||
|
||||
test_voldaemon() {
|
||||
test -f "$NIX_VOLUME_MOUNTD_DEST"
|
||||
}
|
||||
|
||||
generate_mount_command() {
|
||||
local cmd_type="$1" # encrypted|unencrypted
|
||||
local volume_uuid mountpoint cmd=()
|
||||
printf -v volume_uuid "%q" "$2"
|
||||
printf -v mountpoint "%q" "$NIX_ROOT"
|
||||
|
||||
case "$cmd_type" in
|
||||
encrypted)
|
||||
cmd=(/bin/sh -c "/usr/bin/security find-generic-password -s '$volume_uuid' -w | /usr/sbin/diskutil apfs unlockVolume '$volume_uuid' -mountpoint '$mountpoint' -stdinpassphrase");;
|
||||
unencrypted)
|
||||
cmd=(/usr/sbin/diskutil mount -mountPoint "$mountpoint" "$volume_uuid");;
|
||||
*)
|
||||
failure "Invalid first arg $cmd_type to generate_mount_command";;
|
||||
esac
|
||||
|
||||
printf " <string>%s</string>\n" "${cmd[@]}"
|
||||
}
|
||||
|
||||
generate_mount_daemon() {
|
||||
local cmd_type="$1" # encrypted|unencrypted
|
||||
local volume_uuid="$2"
|
||||
cat <<EOF
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
<key>Label</key>
|
||||
<string>org.nixos.darwin-store</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
$(generate_mount_command "$cmd_type" "$volume_uuid")
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
EOF
|
||||
}
|
||||
|
||||
_eat_bootout_err() {
|
||||
/usr/bin/grep -v "Boot-out failed: 36: Operation now in progress"
|
||||
}
|
||||
|
||||
# TODO: remove with --uninstall?
|
||||
uninstall_launch_daemon_directions() {
|
||||
local daemon_label="$1" # i.e., org.nixos.blah-blah
|
||||
local daemon_plist="$2" # abspath
|
||||
substep "Uninstall LaunchDaemon $daemon_label" \
|
||||
" sudo launchctl bootout system/$daemon_label" \
|
||||
" sudo rm $daemon_plist"
|
||||
}
|
||||
|
||||
uninstall_launch_daemon_prompt() {
|
||||
local daemon_label="$1" # i.e., org.nixos.blah-blah
|
||||
local daemon_plist="$2" # abspath
|
||||
local reason_for_daemon="$3"
|
||||
cat <<EOF
|
||||
|
||||
The installer adds a LaunchDaemon to $reason_for_daemon: $daemon_label
|
||||
EOF
|
||||
if ui_confirm "Can I remove it?"; then
|
||||
_sudo "to terminate the daemon" \
|
||||
launchctl bootout "system/$daemon_label" 2> >(_eat_bootout_err >&2) || true
|
||||
# this can "fail" with a message like:
|
||||
# Boot-out failed: 36: Operation now in progress
|
||||
_sudo "to remove the daemon definition" rm "$daemon_plist"
|
||||
fi
|
||||
}
|
||||
|
||||
nix_volume_mountd_uninstall_directions() {
|
||||
uninstall_launch_daemon_directions "org.nixos.darwin-store" \
|
||||
"$NIX_VOLUME_MOUNTD_DEST"
|
||||
}
|
||||
|
||||
nix_volume_mountd_uninstall_prompt() {
|
||||
uninstall_launch_daemon_prompt "org.nixos.darwin-store" \
|
||||
"$NIX_VOLUME_MOUNTD_DEST" \
|
||||
"mount your Nix volume"
|
||||
}
|
||||
|
||||
# TODO: move nix_daemon to install-darwin-multi-user if/when uninstall_launch_daemon_prompt moves up to install-multi-user
|
||||
nix_daemon_uninstall_prompt() {
|
||||
uninstall_launch_daemon_prompt "org.nixos.nix-daemon" \
|
||||
"$NIX_DAEMON_DEST" \
|
||||
"run the nix-daemon"
|
||||
}
|
||||
|
||||
# TODO: remove with --uninstall?
|
||||
nix_daemon_uninstall_directions() {
|
||||
uninstall_launch_daemon_directions "org.nixos.nix-daemon" \
|
||||
"$NIX_DAEMON_DEST"
|
||||
}
|
||||
|
||||
|
||||
# TODO: remove with --uninstall?
|
||||
synthetic_conf_uninstall_directions() {
|
||||
# :1 to strip leading slash
|
||||
substep "Remove ${NIX_ROOT:1} from /etc/synthetic.conf" \
|
||||
" If nix is the only entry: sudo rm /etc/synthetic.conf" \
|
||||
" Otherwise: sudo /usr/bin/sed -i '' -e '/^${NIX_ROOT:1}$/d' /etc/synthetic.conf"
|
||||
}
|
||||
|
||||
synthetic_conf_uninstall_prompt() {
|
||||
cat <<EOF
|
||||
|
||||
During install, I add '${NIX_ROOT:1}' to /etc/synthetic.conf, which instructs
|
||||
macOS to create an empty root directory for mounting the Nix volume.
|
||||
EOF
|
||||
# make the edit to a copy
|
||||
/usr/bin/grep -vE "^${NIX_ROOT:1}($|\t.{3,}$)" /etc/synthetic.conf > "$SCRATCH/synthetic.conf.edit"
|
||||
|
||||
if test_synthetic_conf_symlinked; then
|
||||
warning <<EOF
|
||||
|
||||
/etc/synthetic.conf already contains a line instructing your system
|
||||
to make '${NIX_ROOT}' as a symlink:
|
||||
$(/usr/bin/grep -nE "^${NIX_ROOT:1}\t.{3,}$" /etc/synthetic.conf)
|
||||
|
||||
This may mean your system has/had a non-standard Nix install.
|
||||
|
||||
The volume-creation process in this installer is *not* compatible
|
||||
with a symlinked store, so I'll have to remove this instruction to
|
||||
continue.
|
||||
|
||||
If you want/need to keep this instruction, answer 'n' to abort.
|
||||
|
||||
EOF
|
||||
fi
|
||||
|
||||
# ask to rm if this left the file empty aside from comments, else edit
|
||||
if /usr/bin/diff -q <(:) <(/usr/bin/grep -v "^#" "$SCRATCH/synthetic.conf.edit") &>/dev/null; then
|
||||
if confirm_rm "/etc/synthetic.conf"; then
|
||||
if test_nix_root_is_symlink; then
|
||||
failure >&2 <<EOF
|
||||
I removed /etc/synthetic.conf, but $NIX_ROOT is already a symlink
|
||||
(-> $(readlink "$NIX_ROOT")). The system should remove it when you reboot.
|
||||
Once you've rebooted, run the installer again.
|
||||
EOF
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
else
|
||||
if confirm_edit "$SCRATCH/synthetic.conf.edit" "/etc/synthetic.conf"; then
|
||||
if test_nix_root_is_symlink; then
|
||||
failure >&2 <<EOF
|
||||
I edited Nix out of /etc/synthetic.conf, but $NIX_ROOT is already a symlink
|
||||
(-> $(readlink "$NIX_ROOT")). The system should remove it when you reboot.
|
||||
Once you've rebooted, run the installer again.
|
||||
EOF
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
fi
|
||||
# fallback instructions
|
||||
echo "Manually remove nix from /etc/synthetic.conf"
|
||||
return 1
|
||||
}
|
||||
|
||||
add_nix_vol_fstab_line() {
|
||||
local uuid="$1"
|
||||
# shellcheck disable=SC1003,SC2026
|
||||
local escaped_mountpoint="${NIX_ROOT/ /'\\\'040}"
|
||||
shift
|
||||
|
||||
# wrap `ex` to work around problems w/ vim features breaking exit codes
|
||||
# - plugins (see github.com/NixOS/nix/issues/5468): -u NONE
|
||||
# - swap file: -n
|
||||
#
|
||||
# the first draft used `--noplugin`, but github.com/NixOS/nix/issues/6462
|
||||
# suggests we need the less-semantic `-u NONE`
|
||||
#
|
||||
# we'd prefer EDITOR="/usr/bin/ex -u NONE" but vifs doesn't word-split
|
||||
# the EDITOR env.
|
||||
#
|
||||
# TODO: at some point we should switch to `--clean`, but it wasn't added
|
||||
# until https://github.com/vim/vim/releases/tag/v8.0.1554 while the macOS
|
||||
# minver 10.12.6 seems to have released with vim 7.4
|
||||
cat > "$SCRATCH/ex_cleanroom_wrapper" <<EOF
|
||||
#!/bin/sh
|
||||
/usr/bin/ex -u NONE -n "\$@"
|
||||
EOF
|
||||
chmod 755 "$SCRATCH/ex_cleanroom_wrapper"
|
||||
|
||||
EDITOR="$SCRATCH/ex_cleanroom_wrapper" _sudo "to add nix to fstab" "$@" <<EOF
|
||||
:a
|
||||
UUID=$uuid $escaped_mountpoint apfs rw,noauto,nobrowse,suid,owners
|
||||
.
|
||||
:x
|
||||
EOF
|
||||
# TODO: preserving my notes on suid,owners above until resolved
|
||||
# There *may* be some issue regarding volume ownership, see nix#3156
|
||||
#
|
||||
# It seems like the cheapest fix is adding "suid,owners" to fstab, but:
|
||||
# - We don't have much info on this condition yet
|
||||
# - I'm not certain if these cause other problems?
|
||||
# - There's a "chown" component some people claim to need to fix this
|
||||
# that I don't understand yet
|
||||
# (Note however that I've had to add a chown step to handle
|
||||
# single->multi-user reinstalls, which may cover this)
|
||||
#
|
||||
# I'm not sure if it's safe to approach this way?
|
||||
#
|
||||
# I think I think the most-proper way to test for it is:
|
||||
# diskutil info -plist "$NIX_VOLUME_LABEL" | xmllint --xpath "(/plist/dict/key[text()='GlobalPermissionsEnabled'])/following-sibling::*[1][name()='true']" -; echo $?
|
||||
#
|
||||
# There's also `sudo /usr/sbin/vsdbutil -c /path` (which is much faster, but is also
|
||||
# deprecated and needs minor parsing).
|
||||
#
|
||||
# If no one finds a problem with doing so, I think the simplest approach
|
||||
# is to just eagerly set this. I found a few imperative approaches:
|
||||
# (diskutil enableOwnership, ~100ms), a cheap one (/usr/sbin/vsdbutil -a, ~40-50ms),
|
||||
# a very cheap one (append the internal format to /var/db/volinfo.database).
|
||||
#
|
||||
# But vsdbutil's deprecation notice suggests using fstab, so I want to
|
||||
# give that a whirl first.
|
||||
#
|
||||
# TODO: when this is workable, poke infinisil about reproducing the issue
|
||||
# and confirming this fix?
|
||||
}
|
||||
|
||||
delete_nix_vol_fstab_line() {
|
||||
# TODO: I'm scaffolding this to handle the new nix volumes
|
||||
# but it might be nice to generalize a smidge further to
|
||||
# go ahead and set up a pattern for curing "old" things
|
||||
# we no longer do?
|
||||
EDITOR="/usr/bin/patch" _sudo "to cut nix from fstab" "$@" < <(/usr/bin/diff /etc/fstab <(/usr/bin/grep -v "$NIX_ROOT apfs rw" /etc/fstab))
|
||||
# leaving some parts out of the grep; people may fiddle this a little?
|
||||
}
|
||||
|
||||
# TODO: hope to remove with --uninstall
|
||||
fstab_uninstall_directions() {
|
||||
substep "Remove ${NIX_ROOT} from /etc/fstab" \
|
||||
" If nix is the only entry: sudo rm /etc/fstab" \
|
||||
" Otherwise, run 'sudo /usr/sbin/vifs' to remove the nix line"
|
||||
}
|
||||
|
||||
fstab_uninstall_prompt() {
|
||||
cat <<EOF
|
||||
During install, I add '${NIX_ROOT}' to /etc/fstab so that macOS knows what
|
||||
mount options to use for the Nix volume.
|
||||
EOF
|
||||
cp /etc/fstab "$SCRATCH/fstab.edit"
|
||||
# technically doesn't need the _sudo path, but throwing away the
|
||||
# output is probably better than mostly-duplicating the code...
|
||||
delete_nix_vol_fstab_line patch "$SCRATCH/fstab.edit" &>/dev/null
|
||||
|
||||
# if the patch test edit, minus comment lines, is equal to empty (:)
|
||||
if /usr/bin/diff -q <(:) <(/usr/bin/grep -v "^#" "$SCRATCH/fstab.edit") &>/dev/null; then
|
||||
# this edit would leave it empty; propose deleting it
|
||||
if confirm_rm "/etc/fstab"; then
|
||||
return 0
|
||||
else
|
||||
echo "Remove nix from /etc/fstab (or remove the file)"
|
||||
fi
|
||||
else
|
||||
echo "I might be able to help you make this edit. Here's the diff:"
|
||||
if ! _diff "/etc/fstab" "$SCRATCH/fstab.edit" && ui_confirm "Does the change above look right?"; then
|
||||
delete_nix_vol_fstab_line /usr/sbin/vifs
|
||||
else
|
||||
echo "Remove nix from /etc/fstab (or remove the file)"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
remove_volume() {
|
||||
local volume_special="$1" # (i.e., disk1s7)
|
||||
_sudo "to unmount the Nix volume" \
|
||||
/usr/sbin/diskutil unmount force "$volume_special" || true # might not be mounted
|
||||
_sudo "to delete the Nix volume" \
|
||||
/usr/sbin/diskutil apfs deleteVolume "$volume_special"
|
||||
}
|
||||
|
||||
# aspiration: robust enough to both fix problems
|
||||
# *and* update older darwin volumes
|
||||
cure_volume() {
|
||||
local volume_special="$1" # (i.e., disk1s7)
|
||||
local volume_uuid="$2"
|
||||
header "Found existing Nix volume"
|
||||
row " special" "$volume_special"
|
||||
row " uuid" "$volume_uuid"
|
||||
|
||||
if volume_encrypted "$volume_special"; then
|
||||
row "encrypted" "yes"
|
||||
if volume_pass_works "$volume_special" "$volume_uuid"; then
|
||||
NIX_VOLUME_DO_ENCRYPT=0
|
||||
ok "Found a working decryption password in keychain :)"
|
||||
echo ""
|
||||
else
|
||||
# - this is a volume we made, and
|
||||
# - the user encrypted it on their own
|
||||
# - something deleted the credential
|
||||
# - this is an old or BYO volume and the pw
|
||||
# just isn't somewhere we can find it.
|
||||
#
|
||||
# We're going to explain why we're freaking out
|
||||
# and prompt them to either delete the volume
|
||||
# (requiring a sudo auth), or abort to fix
|
||||
warning <<EOF
|
||||
|
||||
This volume is encrypted, but I don't see a password to decrypt it.
|
||||
The quick fix is to let me delete this volume and make you a new one.
|
||||
If that's okay, enter your (sudo) password to continue. If not, you
|
||||
can ensure the decryption password is in your system keychain with a
|
||||
"Where" (service) field set to this volume's UUID:
|
||||
$volume_uuid
|
||||
EOF
|
||||
if password_confirm "delete this volume"; then
|
||||
remove_volume "$volume_special"
|
||||
else
|
||||
# TODO: this is a good design case for a warn-and
|
||||
# remind idiom...
|
||||
failure <<EOF
|
||||
Your Nix volume is encrypted, but I couldn't find its password. Either:
|
||||
- Delete or rename the volume out of the way
|
||||
- Ensure its decryption password is in the system keychain with a
|
||||
"Where" (service) field set to this volume's UUID:
|
||||
$volume_uuid
|
||||
EOF
|
||||
fi
|
||||
fi
|
||||
elif test_filevault_in_use; then
|
||||
row "encrypted" "no"
|
||||
warning <<EOF
|
||||
FileVault is on, but your $NIX_VOLUME_LABEL volume isn't encrypted.
|
||||
EOF
|
||||
# if we're interactive, give them a chance to
|
||||
# encrypt the volume. If not, /shrug
|
||||
if ! headless && (( NIX_VOLUME_DO_ENCRYPT == 1 )); then
|
||||
if ui_confirm "Should I encrypt it and add the decryption key to your keychain?"; then
|
||||
encrypt_volume "$volume_uuid" "$NIX_VOLUME_LABEL"
|
||||
NIX_VOLUME_DO_ENCRYPT=0
|
||||
else
|
||||
NIX_VOLUME_DO_ENCRYPT=0
|
||||
reminder "FileVault is on, but your $NIX_VOLUME_LABEL volume isn't encrypted."
|
||||
fi
|
||||
fi
|
||||
else
|
||||
row "encrypted" "no"
|
||||
fi
|
||||
}
|
||||
|
||||
remove_volume_artifacts() {
|
||||
if test_synthetic_conf_either; then
|
||||
# NIX_ROOT is in synthetic.conf
|
||||
if synthetic_conf_uninstall_prompt; then
|
||||
# TODO: moot until we tackle uninstall, but when we're
|
||||
# actually uninstalling, we should issue:
|
||||
# reminder "macOS will clean up the empty mount-point directory at $NIX_ROOT on reboot."
|
||||
:
|
||||
fi
|
||||
fi
|
||||
if test_fstab; then
|
||||
fstab_uninstall_prompt
|
||||
fi
|
||||
|
||||
if test_nix_volume_mountd_installed; then
|
||||
nix_volume_mountd_uninstall_prompt
|
||||
fi
|
||||
}
|
||||
|
||||
setup_synthetic_conf() {
|
||||
if test_nix_root_is_symlink; then
|
||||
if ! test_synthetic_conf_symlinked; then
|
||||
failure >&2 <<EOF
|
||||
error: $NIX_ROOT is a symlink (-> $(readlink "$NIX_ROOT")).
|
||||
Please remove it. If nix is in /etc/synthetic.conf, remove it and reboot.
|
||||
EOF
|
||||
fi
|
||||
fi
|
||||
if ! test_synthetic_conf_mountable; then
|
||||
task "Configuring /etc/synthetic.conf to make a mount-point at $NIX_ROOT" >&2
|
||||
# technically /etc/synthetic.d/nix is supported in Big Sur+
|
||||
# but handling both takes even more code...
|
||||
# See earlier note; `-u NONE` disables vim plugins/rc, `-n` skips swapfile
|
||||
_sudo "to add Nix to /etc/synthetic.conf" \
|
||||
/usr/bin/ex -u NONE -n /etc/synthetic.conf <<EOF
|
||||
:a
|
||||
${NIX_ROOT:1}
|
||||
.
|
||||
:x
|
||||
EOF
|
||||
if ! test_synthetic_conf_mountable; then
|
||||
failure "error: failed to configure synthetic.conf" >&2
|
||||
fi
|
||||
create_synthetic_objects
|
||||
if ! test_nix; then
|
||||
failure >&2 <<EOF
|
||||
error: failed to bootstrap $NIX_ROOT
|
||||
If you enabled FileVault after booting, this is likely a known issue
|
||||
with macOS that you'll have to reboot to fix. If you didn't enable FV,
|
||||
though, please open an issue describing how the system that you see
|
||||
this error on was set up.
|
||||
EOF
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
setup_fstab() {
|
||||
local volume_uuid="$1"
|
||||
# fstab used to be responsible for mounting the volume. Now the last
|
||||
# step adds a LaunchDaemon responsible for mounting. This is technically
|
||||
# redundant for mounting, but diskutil appears to pick up mount options
|
||||
# from fstab (and diskutil's support for specifying them directly is not
|
||||
# consistent across versions/subcommands).
|
||||
if ! test_fstab; then
|
||||
task "Configuring /etc/fstab to specify volume mount options" >&2
|
||||
add_nix_vol_fstab_line "$volume_uuid" /usr/sbin/vifs
|
||||
fi
|
||||
}
|
||||
|
||||
encrypt_volume() {
|
||||
local volume_uuid="$1"
|
||||
local volume_label="$2"
|
||||
local password
|
||||
|
||||
task "Encrypt the Nix volume" >&2
|
||||
|
||||
# Note: mount/unmount are late additions to support the right order
|
||||
# of operations for creating the volume and then baking its uuid into
|
||||
# other artifacts; not as well-trod wrt to potential errors, race
|
||||
# conditions, etc.
|
||||
|
||||
_sudo "to mount your Nix volume for encrypting" \
|
||||
/usr/sbin/diskutil mount "$volume_label"
|
||||
|
||||
password="$(/usr/bin/xxd -l 32 -p -c 256 /dev/random)"
|
||||
_sudo "to add your Nix volume's password to Keychain" \
|
||||
/usr/bin/security -i <<EOF
|
||||
add-generic-password -a "$volume_label" -s "$volume_uuid" -l "$volume_label encryption password" -D "Encrypted volume password" -j "Added automatically by the Nix installer for use by $NIX_VOLUME_MOUNTD_DEST" -w "$password" -T /System/Library/CoreServices/APFSUserAgent -T /System/Library/CoreServices/CSUserAgent -T /usr/bin/security "/Library/Keychains/System.keychain"
|
||||
EOF
|
||||
builtin printf "%s" "$password" | _sudo "to actually encrypt your Nix volume" \
|
||||
/usr/sbin/diskutil apfs encryptVolume "$volume_label" -user disk -stdinpassphrase
|
||||
|
||||
_sudo "to unmount the encrypted volume" \
|
||||
/usr/sbin/diskutil unmount force "$volume_label"
|
||||
}
|
||||
|
||||
create_volume() {
|
||||
# Notes:
|
||||
# 1) using `-nomount` instead of `-mountpoint "$NIX_ROOT"` to get
|
||||
# its UUID and set mount opts in fstab before first mount
|
||||
#
|
||||
# 2) system is in some sense less secure than user keychain... (it's
|
||||
# possible to read the password for decrypting the keychain) but
|
||||
# the user keychain appears to be available too late. As far as I
|
||||
# can tell, the file with this password (/var/db/SystemKey) is
|
||||
# inside the FileVault envelope. If that isn't true, it may make
|
||||
# sense to store the password inside the envelope?
|
||||
#
|
||||
# 3) At some point it would be ideal to have a small binary to serve
|
||||
# as the daemon itself, and for it to replace /usr/bin/security here.
|
||||
#
|
||||
# 4) *UserAgent exemptions should let the system seamlessly supply the
|
||||
# password if noauto is removed from fstab entry. This is intentional;
|
||||
# the user will hopefully look for help if the volume stops mounting,
|
||||
# rather than failing over into subtle race-condition problems.
|
||||
#
|
||||
# 5) If we ever get users griping about not having space to do
|
||||
# anything useful with Nix, it is possibly to specify
|
||||
# `-reserve 10g` or something, which will fail w/o that much
|
||||
#
|
||||
# 6) getting special w/ awk may be fragile, but doing it to:
|
||||
# - save time over running slow diskutil commands
|
||||
# - skirt risk we grab wrong volume if multiple match
|
||||
_sudo "to create a new APFS volume '$NIX_VOLUME_LABEL' on $NIX_VOLUME_USE_DISK" \
|
||||
/usr/sbin/diskutil apfs addVolume "$NIX_VOLUME_USE_DISK" "$NIX_VOLUME_FS" "$NIX_VOLUME_LABEL" -nomount | /usr/bin/awk '/Created new APFS Volume/ {print $5}'
|
||||
}
|
||||
|
||||
volume_uuid_from_special() {
|
||||
local volume_special="$1" # (i.e., disk1s7)
|
||||
# For reasons I won't pretend to fathom, this returns 253 when it works
|
||||
/System/Library/Filesystems/apfs.fs/Contents/Resources/apfs.util -k "$volume_special" || true
|
||||
}
|
||||
|
||||
# this sometimes clears immediately, and AFAIK clears
|
||||
# within about 1s. diskutil info on an unmounted path
|
||||
# fails in around 50-100ms and a match takes about
|
||||
# 250-300ms. I suspect it's usually ~250-750ms
|
||||
await_volume() {
|
||||
# caution: this could, in theory, get stuck
|
||||
until /usr/sbin/diskutil info "$NIX_ROOT" &>/dev/null; do
|
||||
:
|
||||
done
|
||||
}
|
||||
|
||||
setup_volume() {
|
||||
local use_special use_uuid profile_packages
|
||||
task "Creating a Nix volume" >&2
|
||||
|
||||
use_special="${NIX_VOLUME_USE_SPECIAL:-$(create_volume)}"
|
||||
|
||||
_sudo "to ensure the Nix volume is not mounted" \
|
||||
/usr/sbin/diskutil unmount force "$use_special" || true # might not be mounted
|
||||
|
||||
use_uuid=${NIX_VOLUME_USE_UUID:-$(volume_uuid_from_special "$use_special")}
|
||||
|
||||
setup_fstab "$use_uuid"
|
||||
|
||||
if should_encrypt_volume; then
|
||||
encrypt_volume "$use_uuid" "$NIX_VOLUME_LABEL"
|
||||
setup_volume_daemon "encrypted" "$use_uuid"
|
||||
# TODO: might be able to save ~60ms by caching or setting
|
||||
# this somewhere rather than re-checking here.
|
||||
elif volume_encrypted "$use_special"; then
|
||||
setup_volume_daemon "encrypted" "$use_uuid"
|
||||
else
|
||||
setup_volume_daemon "unencrypted" "$use_uuid"
|
||||
fi
|
||||
|
||||
await_volume
|
||||
|
||||
if [ "$(/usr/sbin/diskutil info -plist "$NIX_ROOT" | xmllint --xpath "(/plist/dict/key[text()='GlobalPermissionsEnabled'])/following-sibling::*[1]" -)" = "<false/>" ]; then
|
||||
_sudo "to set enableOwnership (enabling users to own files)" \
|
||||
/usr/sbin/diskutil enableOwnership "$NIX_ROOT"
|
||||
fi
|
||||
|
||||
# TODO: below is a vague kludge for now; I just don't know
|
||||
# what if any safe action there is to take here. Also, the
|
||||
# reminder isn't very helpful.
|
||||
# I'm less sure where this belongs, but it also wants mounted, pre-install
|
||||
if type -p nix-env; then
|
||||
profile_packages="$(nix-env --query --installed)"
|
||||
# TODO: can probably do below faster w/ read
|
||||
# intentionally unquoted string to eat whitespace in wc output
|
||||
# shellcheck disable=SC2046,SC2059
|
||||
if ! [ $(printf "$profile_packages" | /usr/bin/wc -l) = "0" ]; then
|
||||
reminder <<EOF
|
||||
Nix now supports only multi-user installs on Darwin/macOS, and your user's
|
||||
Nix profile has some packages in it. These packages may obscure those in the
|
||||
default profile, including the Nix this installer will add. You should
|
||||
review these packages:
|
||||
$profile_packages
|
||||
EOF
|
||||
fi
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
setup_volume_daemon() {
|
||||
local cmd_type="$1" # encrypted|unencrypted
|
||||
local volume_uuid="$2"
|
||||
if ! test_voldaemon; then
|
||||
task "Configuring LaunchDaemon to mount '$NIX_VOLUME_LABEL'" >&2
|
||||
# See earlier note; `-u NONE` disables vim plugins/rc, `-n` skips swapfile
|
||||
_sudo "to install the Nix volume mounter" /usr/bin/ex -u NONE -n "$NIX_VOLUME_MOUNTD_DEST" <<EOF
|
||||
:a
|
||||
$(generate_mount_daemon "$cmd_type" "$volume_uuid")
|
||||
.
|
||||
:x
|
||||
EOF
|
||||
|
||||
# TODO: should probably alert the user if this is disabled?
|
||||
_sudo "to launch the Nix volume mounter" \
|
||||
launchctl bootstrap system "$NIX_VOLUME_MOUNTD_DEST" || true
|
||||
# TODO: confirm whether kickstart is necessesary?
|
||||
# I feel a little superstitous, but it can guard
|
||||
# against multiple problems (doesn't start, old
|
||||
# version still running for some reason...)
|
||||
_sudo "to launch the Nix volume mounter" \
|
||||
launchctl kickstart -k system/org.nixos.darwin-store
|
||||
fi
|
||||
}
|
||||
|
||||
setup_darwin_volume() {
|
||||
setup_synthetic_conf
|
||||
setup_volume
|
||||
}
|
||||
|
||||
if [ "$_CREATE_VOLUME_NO_MAIN" = 1 ]; then
|
||||
if [ -n "$*" ]; then
|
||||
"$@" # expose functions in case we want multiple routines?
|
||||
fi
|
||||
else
|
||||
# no reason to pay for bash to process this
|
||||
main() {
|
||||
{
|
||||
echo ""
|
||||
echo " ------------------------------------------------------------------ "
|
||||
echo " | This installer will create a volume for the nix store and |"
|
||||
echo " | configure it to mount at $NIX_ROOT. Follow these steps to uninstall. |"
|
||||
echo " ------------------------------------------------------------------ "
|
||||
echo ""
|
||||
echo " 1. Remove the entry from fstab using 'sudo /usr/sbin/vifs'"
|
||||
echo " 2. Run 'sudo launchctl bootout system/org.nixos.darwin-store'"
|
||||
echo " 3. Remove $NIX_VOLUME_MOUNTD_DEST"
|
||||
echo " 4. Destroy the data volume using '/usr/sbin/diskutil apfs deleteVolume'"
|
||||
echo " 5. Remove the 'nix' line from /etc/synthetic.conf (or the file)"
|
||||
echo ""
|
||||
} >&2
|
||||
|
||||
setup_darwin_volume
|
||||
}
|
||||
|
||||
main "$@"
|
||||
fi
|
||||
@@ -1,226 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eu
|
||||
set -o pipefail
|
||||
|
||||
# System specific settings
|
||||
export NIX_FIRST_BUILD_UID="${NIX_FIRST_BUILD_UID:-301}"
|
||||
export NIX_BUILD_USER_NAME_TEMPLATE="_nixbld%d"
|
||||
|
||||
readonly NIX_DAEMON_DEST=/Library/LaunchDaemons/org.nixos.nix-daemon.plist
|
||||
# create by default; set 0 to DIY, use a symlink, etc.
|
||||
readonly NIX_VOLUME_CREATE=${NIX_VOLUME_CREATE:-1} # now default
|
||||
|
||||
# caution: may update times on / if not run as normal non-root user
|
||||
read_only_root() {
|
||||
# this touch command ~should~ always produce an error
|
||||
# as of this change I confirmed /usr/bin/touch emits:
|
||||
# "touch: /: Operation not permitted" Monterey
|
||||
# "touch: /: Read-only file system" Catalina+ and Big Sur
|
||||
# "touch: /: Permission denied" Mojave
|
||||
# (not matching prefix for compat w/ coreutils touch in case using
|
||||
# an explicit path causes problems; its prefix differs)
|
||||
case "$(/usr/bin/touch / 2>&1)" in
|
||||
*"Read-only file system") # Catalina, Big Sur
|
||||
return 0
|
||||
;;
|
||||
*"Operation not permitted") # Monterey
|
||||
return 0
|
||||
;;
|
||||
*)
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Avoiding the slow semantic way to get this information (~330ms vs ~8ms)
|
||||
# unless using touch causes problems. Just in case, that approach is:
|
||||
# diskutil info -plist / | <find the Writable or WritableVolume keys>, i.e.
|
||||
# diskutil info -plist / | xmllint --xpath "name(/plist/dict/key[text()='Writable']/following-sibling::*[1])" -
|
||||
}
|
||||
|
||||
if read_only_root && [ "$NIX_VOLUME_CREATE" = 1 ]; then
|
||||
should_create_volume() { return 0; }
|
||||
else
|
||||
should_create_volume() { return 1; }
|
||||
fi
|
||||
|
||||
# shellcheck source=./create-darwin-volume.sh
|
||||
. "$EXTRACTED_NIX_PATH/create-darwin-volume.sh" "no-main"
|
||||
|
||||
dsclattr() {
|
||||
/usr/bin/dscl . -read "$1" \
|
||||
| /usr/bin/awk "/$2/ { print \$2 }"
|
||||
}
|
||||
|
||||
test_nix_daemon_installed() {
|
||||
test -e "$NIX_DAEMON_DEST"
|
||||
}
|
||||
|
||||
poly_cure_artifacts() {
|
||||
if should_create_volume; then
|
||||
task "Fixing any leftover Nix volume state"
|
||||
cat <<EOF
|
||||
Before I try to install, I'll check for any existing Nix volume config
|
||||
and ask for your permission to remove it (so that the installer can
|
||||
start fresh). I'll also ask for permission to fix any issues I spot.
|
||||
EOF
|
||||
cure_volumes
|
||||
remove_volume_artifacts
|
||||
fi
|
||||
}
|
||||
|
||||
poly_service_installed_check() {
|
||||
if should_create_volume; then
|
||||
test_nix_daemon_installed || test_nix_volume_mountd_installed
|
||||
else
|
||||
test_nix_daemon_installed
|
||||
fi
|
||||
}
|
||||
|
||||
poly_service_uninstall_directions() {
|
||||
echo "$1. Remove macOS-specific components:"
|
||||
if should_create_volume && test_nix_volume_mountd_installed; then
|
||||
nix_volume_mountd_uninstall_directions
|
||||
fi
|
||||
if test_nix_daemon_installed; then
|
||||
nix_daemon_uninstall_directions
|
||||
fi
|
||||
}
|
||||
|
||||
poly_service_setup_note() {
|
||||
if should_create_volume; then
|
||||
echo " - create a Nix volume and a LaunchDaemon to mount it"
|
||||
fi
|
||||
echo " - create a LaunchDaemon (at $NIX_DAEMON_DEST) for nix-daemon"
|
||||
echo ""
|
||||
}
|
||||
|
||||
poly_extra_try_me_commands() {
|
||||
:
|
||||
}
|
||||
|
||||
poly_configure_nix_daemon_service() {
|
||||
task "Setting up the nix-daemon LaunchDaemon"
|
||||
_sudo "to set up the nix-daemon as a LaunchDaemon" \
|
||||
/usr/bin/install -m "u=rw,go=r" "/nix/var/nix/profiles/default$NIX_DAEMON_DEST" "$NIX_DAEMON_DEST"
|
||||
|
||||
_sudo "to load the LaunchDaemon plist for nix-daemon" \
|
||||
launchctl load /Library/LaunchDaemons/org.nixos.nix-daemon.plist
|
||||
|
||||
_sudo "to start the nix-daemon" \
|
||||
launchctl kickstart -k system/org.nixos.nix-daemon
|
||||
}
|
||||
|
||||
poly_group_exists() {
|
||||
/usr/bin/dscl . -read "/Groups/$1" > /dev/null 2>&1
|
||||
}
|
||||
|
||||
poly_group_id_get() {
|
||||
dsclattr "/Groups/$1" "PrimaryGroupID"
|
||||
}
|
||||
|
||||
poly_create_build_group() {
|
||||
_sudo "Create the Nix build group, $NIX_BUILD_GROUP_NAME" \
|
||||
/usr/sbin/dseditgroup -o create \
|
||||
-r "Nix build group for nix-daemon" \
|
||||
-i "$NIX_BUILD_GROUP_ID" \
|
||||
"$NIX_BUILD_GROUP_NAME" >&2
|
||||
}
|
||||
|
||||
poly_user_exists() {
|
||||
/usr/bin/dscl . -read "/Users/$1" > /dev/null 2>&1
|
||||
}
|
||||
|
||||
poly_user_id_get() {
|
||||
dsclattr "/Users/$1" "UniqueID"
|
||||
}
|
||||
|
||||
poly_user_hidden_get() {
|
||||
dsclattr "/Users/$1" "IsHidden"
|
||||
}
|
||||
|
||||
poly_user_hidden_set() {
|
||||
_sudo "in order to make $1 a hidden user" \
|
||||
/usr/bin/dscl . -create "/Users/$1" "IsHidden" "1"
|
||||
}
|
||||
|
||||
poly_user_home_get() {
|
||||
dsclattr "/Users/$1" "NFSHomeDirectory"
|
||||
}
|
||||
|
||||
poly_user_home_set() {
|
||||
# This can trigger a permission prompt now:
|
||||
# "Terminal" would like to administer your computer. Administration can include modifying passwords, networking, and system settings.
|
||||
_sudo "in order to give $1 a safe home directory" \
|
||||
/usr/bin/dscl . -create "/Users/$1" "NFSHomeDirectory" "$2"
|
||||
}
|
||||
|
||||
poly_user_note_get() {
|
||||
dsclattr "/Users/$1" "RealName"
|
||||
}
|
||||
|
||||
poly_user_note_set() {
|
||||
_sudo "in order to give $username a useful note" \
|
||||
/usr/bin/dscl . -create "/Users/$1" "RealName" "$2"
|
||||
}
|
||||
|
||||
poly_user_shell_get() {
|
||||
dsclattr "/Users/$1" "UserShell"
|
||||
}
|
||||
|
||||
poly_user_shell_set() {
|
||||
_sudo "in order to give $1 a safe shell" \
|
||||
/usr/bin/dscl . -create "/Users/$1" "UserShell" "$2"
|
||||
}
|
||||
|
||||
poly_user_in_group_check() {
|
||||
username=$1
|
||||
group=$2
|
||||
/usr/sbin/dseditgroup -o checkmember -m "$username" "$group" > /dev/null 2>&1
|
||||
}
|
||||
|
||||
poly_user_in_group_set() {
|
||||
username=$1
|
||||
group=$2
|
||||
|
||||
_sudo "Add $username to the $group group"\
|
||||
/usr/sbin/dseditgroup -o edit -t user \
|
||||
-a "$username" "$group"
|
||||
}
|
||||
|
||||
poly_user_primary_group_get() {
|
||||
dsclattr "/Users/$1" "PrimaryGroupID"
|
||||
}
|
||||
|
||||
poly_user_primary_group_set() {
|
||||
_sudo "to let the nix daemon use this user for builds (this might seem redundant, but there are two concepts of group membership)" \
|
||||
/usr/bin/dscl . -create "/Users/$1" "PrimaryGroupID" "$2"
|
||||
}
|
||||
|
||||
poly_create_build_user() {
|
||||
username=$1
|
||||
uid=$2
|
||||
builder_num=$3
|
||||
|
||||
_sudo "Creating the Nix build user (#$builder_num), $username" \
|
||||
/usr/bin/dscl . create "/Users/$username" \
|
||||
UniqueID "${uid}"
|
||||
}
|
||||
|
||||
poly_prepare_to_install() {
|
||||
if should_create_volume; then
|
||||
header "Preparing a Nix volume"
|
||||
# intentional indent below to match task indent
|
||||
cat <<EOF
|
||||
Nix traditionally stores its data in the root directory $NIX_ROOT, but
|
||||
macOS now (starting in 10.15 Catalina) has a read-only root directory.
|
||||
To support Nix, I will create a volume and configure macOS to mount it
|
||||
at $NIX_ROOT.
|
||||
EOF
|
||||
setup_darwin_volume
|
||||
fi
|
||||
|
||||
if [ "$(/usr/sbin/diskutil info -plist /nix | xmllint --xpath "(/plist/dict/key[text()='GlobalPermissionsEnabled'])/following-sibling::*[1]" -)" = "<false/>" ]; then
|
||||
failure "This script needs a /nix volume with global permissions! This may require running sudo /usr/sbin/diskutil enableOwnership /nix."
|
||||
fi
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user