Add Nix, a purely functional package manager

Nix is a purely functional package manager. This means that it treats
packages like values in purely functional programming languages such as
Haskell -- they are built by functions that don't have side-effects,
and they never change after they have been built.

FreeBSD support in Nix is not fully complete yet. This commit only
brings the Nix package manager to the ports. Hopefully, this port will
streamline the work of bootstrapping of Nix packages on FreeBSD.

Thanks to all the kind folks who contributed to the porting efforts.
It was a fun journey.

WWW: https://nixos.org/nix/

Differential Revision:	https://reviews.freebsd.org/D17766
This commit is contained in:
Mateusz Piotrowski 2020-09-25 12:54:38 +00:00
parent b52812065e
commit 25ca397083
Notes: svn2git 2021-03-31 03:12:20 +00:00
svn path=/head/; revision=550026
11 changed files with 466 additions and 1 deletions

2
GIDs
View File

@ -92,7 +92,7 @@ kdm:*:147:
ipv6mon:*:148:
avenger:*:149:
cbsd:*:150:
# free: 151
nixbld:*:151:
frrvty:*:152:frr
rbldns:*:153:
trircd:*:154:

View File

@ -735,6 +735,7 @@
SUBDIR += netevent
SUBDIR += nfcutils
SUBDIR += nitrogen
SUBDIR += nix
SUBDIR += no-login
SUBDIR += node_exporter
SUBDIR += nomad

114
sysutils/nix/Makefile Normal file
View File

@ -0,0 +1,114 @@
# Created by: Mateusz Piotrowski <0mp@FreeBSD.org>
# $FreeBSD$
PORTNAME= nix
DISTVERSION= 2.3.7
CATEGORIES= sysutils
MAINTAINER= 0mp@FreeBSD.org
COMMENT= Purely functional package manager
LICENSE= LGPL21
LICENSE_FILE= ${WRKSRC}/COPYING
BUILD_DEPENDS= ${LOCALBASE}/share/aclocal/ax_cxx_compile_stdcxx.m4:devel/autoconf-archive \
bash:shells/bash \
docbook-xsl-ns>=0:textproc/docbook-xsl-ns \
gnustat:sysutils/coreutils \
grealpath:sysutils/coreutils \
xmllint:textproc/libxml2 \
xsltproc:textproc/libxslt
LIB_DEPENDS= libaws-cpp-sdk-core.so:devel/aws-sdk-cpp \
libboost_context.so:devel/boost-libs \
libbrotlienc.so:archivers/brotli \
libcurl.so:ftp/curl \
libeditline.so:devel/editline \
libgc.so:devel/boehm-gc \
libsodium.so:security/libsodium
TEST_DEPENDS= dot:graphics/graphviz \
git:devel/git \
gxargs:misc/findutils \
hg:devel/mercurial
USES= autoreconf bison compiler:c++17-lang gmake localbase pkgconfig \
sqlite:3 ssl
USE_GITHUB= yes
GH_ACCOUNT= NixOS
USE_LDCONFIG= yes
HAS_CONFIGURE= yes
# Workaround for bashisms in the configure script.
CONFIGURE_SHELL= ${_BASH}
CONFIGURE_ARGS= --disable-seccomp-sandboxing \
--enable-gc
CONFIGURE_ENV= OPENSSL_CFLAGS="-I ${OPENSSLINC}" \
OPENSSL_LIBS="-L ${OPENSSLLIB}"
# Workaround for:
# /usr/bin/ld: error: undefined symbol: SHA512_Update
MAKE_ARGS= libutil_ALLOW_UNDEFINED=yes
# XXX: Tests require the port to be installed on the system. It is not enough
# to have the port staged.
TEST_ARGS= nix_tests="${_PASSING_TESTS}"
TEST_TARGET= installcheck
# grealpath and gnustat are needed for tests.
BINARY_ALIAS= realpath=grealpath stat=gnustat
SUB_FILES= pkg-message
GROUPS= nixbld
OPTIONS_DEFINE= DOCS
_BASH= ${LOCALBASE}/bin/bash
_STRIP_TARGETS= bin/nix bin/nix-build bin/nix-channel bin/nix-collect-garbage \
bin/nix-copy-closure bin/nix-daemon bin/nix-env \
bin/nix-instantiate bin/nix-prefetch-url bin/nix-store \
lib/libnixexpr.so lib/libnixmain.so lib/libnixstore.so \
lib/libnixutil.so
# Regenerate the list of all tests with:
# make patch && make -f $(make -V WRKSRC)/tests/local.mk -V nix_tests
_ALL_TESTS= init.sh hash.sh lang.sh add.sh simple.sh dependencies.sh gc.sh \
gc-concurrent.sh gc-auto.sh referrers.sh user-envs.sh \
logging.sh nix-build.sh misc.sh fixed.sh gc-runtime.sh \
check-refs.sh filter-source.sh remote-store.sh export.sh \
export-graph.sh timeout.sh secure-drv-outputs.sh nix-channel.sh \
multiple-outputs.sh import-derivation.sh fetchurl.sh \
optimise-store.sh binary-cache.sh nix-profile.sh repair.sh \
dump-db.sh case-hack.sh check-reqs.sh pass-as-file.sh \
tarball.sh restricted.sh placeholders.sh nix-shell.sh \
linux-sandbox.sh build-dry.sh build-remote.sh nar-access.sh \
structured-attrs.sh fetchGit.sh fetchMercurial.sh signing.sh \
run.sh brotli.sh pure-eval.sh check.sh plugins.sh search.sh \
nix-copy-ssh.sh post-hook.sh function-trace.sh
# Remove problematic tests from the list:
# - restricted.sh is hanging and never finishes.
_PASSING_TESTS= ${_ALL_TESTS:Nrestricted.sh}
post-install:
@${MKDIR} ${STAGEDIR}${DATADIR}
${INSTALL_SCRIPT} ${FILESDIR}/add-nixbld-users ${STAGEDIR}${DATADIR}
@${RM} ${STAGEDIR}${PREFIX}/libexec/nix/build-remote
@${RLN} ${STAGEDIR}${PREFIX}/bin/nix ${STAGEDIR}${PREFIX}/libexec/nix/build-remote
@cd ${STAGEDIR}${PREFIX} && ${STRIP_CMD} ${_STRIP_TARGETS}
pre-test:
${MKDIR} /tmp/nix-test
${REINPLACE_CMD} -e 's| xargs | gxargs |g' ${WRKSRC}/tests/push-to-store.sh
${REINPLACE_CMD} -e 's| touch | /usr/bin/touch |g' ${WRKSRC}/tests/timeout.nix
${REINPLACE_CMD} -e 's| touch | /usr/bin/touch |g' ${WRKSRC}/tests/check-reqs.nix
${REINPLACE_CMD} -e 's| touch | /usr/bin/touch |g' ${WRKSRC}/tests/nar-access.nix
${REINPLACE_CMD} -e 's| touch | /usr/bin/touch |g' ${WRKSRC}/tests/pass-as-file.sh
${REINPLACE_CMD} -e 's| date | ${LOCALBASE}/bin/gdate |g' ${WRKSRC}/tests/check.nix
${REINPLACE_CMD} -e 's| wc -l)| /usr/bin/grep -c .)|g' ${WRKSRC}/tests/gc-auto.sh
${REINPLACE_CMD} -e 's| tar c tarball)| tar -cf - tarball)|' ${WRKSRC}/tests/tarball.sh
${REINPLACE_CMD} -e 's|^grep |/usr/bin/grep |' ${WRKSRC}/tests/check.sh
post-test:
${RM} -r /tmp/nix-test
.include <bsd.port.mk>

3
sysutils/nix/distinfo Normal file
View File

@ -0,0 +1,3 @@
TIMESTAMP = 1600718771
SHA256 (NixOS-nix-2.3.7_GH0.tar.gz) = d5ea34196922c5f0d962649929be2a489b8cd29effcf1481c63aca154c65e739
SIZE (NixOS-nix-2.3.7_GH0.tar.gz) = 900906

View File

@ -0,0 +1,23 @@
#! /bin/sh -
# $FreeBSD$
set -eu
if [ -z "$1" ] || ! expr -- "$1" : "[0-9][0-9]*" >/dev/null; then
echo "Usage: $0 NUMBER" 2>/dev/null
exit 1
fi
if [ "$1" -lt 1 ]; then
echo "ERROR: NUMBER should be at least 1" 2>/dev/null
exit 1
fi
for n in $(seq 1 "$1"); do
user="nixbld${n}"
if pw usershow "$user" >/dev/null 2>&1; then
continue
fi
pw useradd "$user" -c "Nix build user $n" -d /var/empty -G nixbld \
-g nixbld -s /usr/sbin/nologin
done

View File

@ -0,0 +1,19 @@
--- src/libexpr/primops/fetchGit.cc.orig 2019-10-10 13:03:46 UTC
+++ src/libexpr/primops/fetchGit.cc
@@ -6,6 +6,7 @@
#include "hash.hh"
#include <sys/time.h>
+#include <sys/wait.h>
#include <regex>
@@ -173,7 +174,7 @@ GitInfo exportGit(ref<Store> store, const std::string
Path tmpDir = createTempDir();
AutoDelete delTmpDir(tmpDir, true);
- runProgram("tar", true, { "x", "-C", tmpDir }, tar);
+ runProgram("tar", true, { "x", "-C", tmpDir, "-f", "-"}, tar);
gitInfo.storePath = store->addToStore(name, tmpDir);

View File

@ -0,0 +1,29 @@
--- src/libstore/build.cc.orig 2019-11-28 21:39:47 UTC
+++ src/libstore/build.cc
@@ -44,12 +44,16 @@
#include <grp.h>
/* Includes required for chroot support. */
-#if __linux__
+#if __linux__ || __FreeBSD__
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
+#endif
+#if __linux__
#include <netinet/ip.h>
#include <sys/personality.h>
+#endif
+#if __linux__ || __FreeBSD__
#include <sys/mman.h>
#include <sched.h>
#include <sys/param.h>
@@ -1943,7 +1947,7 @@ void DerivationGoal::startBuilder()
/* If `build-users-group' is not empty, then we have to build as
one of the members of that group. */
if (settings.buildUsersGroup != "" && getuid() == 0) {
-#if defined(__linux__) || defined(__APPLE__)
+#if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__)
buildUser = std::make_unique<UserLock>();
/* Make sure that no other processes are executing under this

View File

@ -0,0 +1,104 @@
--- src/libstore/s3-binary-cache-store.cc.orig 2019-10-10 13:03:46 UTC
+++ src/libstore/s3-binary-cache-store.cc
@@ -44,7 +44,7 @@ R && checkAws(const FormatOrString & fs, Aws::Utils::O
if (!outcome.IsSuccess())
throw S3Error(
outcome.GetError().GetErrorType(),
- fs.s + ": " + outcome.GetError().GetMessage());
+ fs.s + ": " + outcome.GetError().GetMessage().c_str());
return outcome.GetResultWithOwnership();
}
@@ -54,8 +54,10 @@ class AwsLogger : public Aws::Utils::Logging::Formatte
void ProcessFormattedStatement(Aws::String && statement) override
{
- debug("AWS: %s", chomp(statement));
+ debug("AWS: %s", chomp((const std::string &)statement));
}
+
+ void Flush() override {}
};
static void initAWS()
@@ -139,8 +141,8 @@ S3Helper::DownloadResult S3Helper::getObject(
auto request =
Aws::S3::Model::GetObjectRequest()
- .WithBucket(bucketName)
- .WithKey(key);
+ .WithBucket(bucketName.c_str())
+ .WithKey(key.c_str());
request.SetResponseStreamFactory([&]() {
return Aws::New<std::stringstream>("STRINGSTREAM");
@@ -155,7 +157,7 @@ S3Helper::DownloadResult S3Helper::getObject(
auto result = checkAws(fmt("AWS error fetching '%s'", key),
client->GetObject(request));
- res.data = decompress(result.GetContentEncoding(),
+ res.data = decompress(result.GetContentEncoding().c_str(),
dynamic_cast<std::stringstream &>(result.GetBody()).str());
} catch (S3Error & e) {
@@ -238,8 +240,8 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheSt
auto res = s3Helper.client->HeadObject(
Aws::S3::Model::HeadObjectRequest()
- .WithBucket(bucketName)
- .WithKey(path));
+ .WithBucket(bucketName.c_str())
+ .WithKey(path.c_str()));
if (!res.IsSuccess()) {
auto & error = res.GetError();
@@ -302,7 +304,7 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheSt
std::shared_ptr<TransferHandle> transferHandle =
transferManager->UploadFile(
- stream, bucketName, path, mimeType,
+ stream, bucketName.c_str(), path.c_str(), mimeType.c_str(),
Aws::Map<Aws::String, Aws::String>(),
nullptr /*, contentEncoding */);
@@ -320,13 +322,13 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheSt
auto request =
Aws::S3::Model::PutObjectRequest()
- .WithBucket(bucketName)
- .WithKey(path);
+ .WithBucket(bucketName.c_str())
+ .WithKey(path.c_str());
- request.SetContentType(mimeType);
+ request.SetContentType(mimeType.c_str());
if (contentEncoding != "")
- request.SetContentEncoding(contentEncoding);
+ request.SetContentEncoding(contentEncoding.c_str());
auto stream = std::make_shared<istringstream_nocopy>(data);
@@ -393,9 +395,9 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheSt
auto res = checkAws(format("AWS error listing bucket '%s'") % bucketName,
s3Helper.client->ListObjects(
Aws::S3::Model::ListObjectsRequest()
- .WithBucket(bucketName)
+ .WithBucket(bucketName.c_str())
.WithDelimiter("/")
- .WithMarker(marker)));
+ .WithMarker(marker.c_str())));
auto & contents = res.GetContents();
@@ -404,8 +406,8 @@ struct S3BinaryCacheStoreImpl : public S3BinaryCacheSt
for (auto object : contents) {
auto & key = object.GetKey();
- if (key.size() != 40 || !hasSuffix(key, ".narinfo")) continue;
- paths.insert(storeDir + "/" + key.substr(0, key.size() - 8));
+ if (key.size() != 40 || !hasSuffix(key.c_str(), ".narinfo")) continue;
+ paths.insert(storeDir + "/" + key.substr(0, key.size() - 8).c_str());
}
marker = res.GetNextMarker();

View File

@ -0,0 +1,29 @@
[
{
type: install
message: <<EOD
Experimental support
--------------------
Nix support is very much experimental on FreeBSD. The sysutils/nix port is
mainly aimed at developers, testers, and curious users. Nix should not be
considered stable yet on FreeBSD.
Creating Nix build users
------------------------
Nix build users may be created by executing the "add-nixbld-users" script
(which is located in "%%DATADIR%%") and specifying
the desired number of build users as an argument.
For example:
%%DATADIR%%/add-nixbld-users 4
is going to create 4 nixbld users.
See https://nixos.org/nix/manual/#ssec-multi-user for more details about
build users.
EOD
}
]

14
sysutils/nix/pkg-descr Normal file
View File

@ -0,0 +1,14 @@
Nix is a purely functional package manager. This means that it treats packages
like values in purely functional programming languages such as Haskell -- they
are built by functions that don't have side-effects, and they never change
after they have been built. Nix stores packages in the Nix store, usually the
directory /nix/store, where each package has its own unique subdirectory such
as
/nix/store/b6gvzjyb2pg0kjfwrjmg1vfhh54ad73z-firefox-33.1/
where b6gvzjyb2pg0... is a unique identifier for the package that captures all
its dependencies (it's a cryptographic hash of the package's build dependency
graph). This enables many powerful features.
WWW: https://nixos.org/nix/

129
sysutils/nix/pkg-plist Normal file
View File

@ -0,0 +1,129 @@
bin/nix
bin/nix-build
bin/nix-channel
bin/nix-collect-garbage
bin/nix-copy-closure
bin/nix-daemon
bin/nix-env
bin/nix-hash
bin/nix-instantiate
bin/nix-prefetch-url
bin/nix-shell
bin/nix-store
etc/profile.d/nix-daemon.sh
etc/profile.d/nix.sh
include/nix/affinity.hh
include/nix/archive.hh
include/nix/args.hh
include/nix/attr-path.hh
include/nix/attr-set.hh
include/nix/binary-cache-store.hh
include/nix/builtins.hh
include/nix/common-args.hh
include/nix/common-eval-args.hh
include/nix/compression.hh
include/nix/config.h
include/nix/config.hh
include/nix/crypto.hh
include/nix/derivations.hh
include/nix/download.hh
include/nix/eval-inline.hh
include/nix/eval.hh
include/nix/finally.hh
include/nix/fs-accessor.hh
include/nix/function-trace.hh
include/nix/get-drvs.hh
include/nix/globals.hh
include/nix/hash.hh
include/nix/istringstream_nocopy.hh
include/nix/json-to-value.hh
include/nix/json.hh
include/nix/lazy.hh
include/nix/lexer-tab.hh
include/nix/local-store.hh
include/nix/logging.hh
include/nix/lru-cache.hh
include/nix/machines.hh
include/nix/monitor-fd.hh
include/nix/names.hh
include/nix/nar-accessor.hh
include/nix/nar-info-disk-cache.hh
include/nix/nar-info.hh
include/nix/nixexpr.hh
include/nix/parsed-derivations.hh
include/nix/parser-tab.hh
include/nix/pathlocks.hh
include/nix/pool.hh
include/nix/primops.hh
include/nix/profiles.hh
include/nix/ref.hh
include/nix/references.hh
include/nix/remote-fs-accessor.hh
include/nix/remote-store.hh
include/nix/s3-binary-cache-store.hh
include/nix/s3.hh
include/nix/schema.sql.gen.hh
include/nix/serialise.hh
include/nix/serve-protocol.hh
include/nix/shared.hh
include/nix/sqlite.hh
include/nix/ssh.hh
include/nix/store-api.hh
include/nix/symbol-table.hh
include/nix/sync.hh
include/nix/thread-pool.hh
include/nix/types.hh
include/nix/util.hh
include/nix/value-to-json.hh
include/nix/value-to-xml.hh
include/nix/value.hh
include/nix/worker-protocol.hh
include/nix/xml-writer.hh
lib/libnixexpr.so
lib/libnixmain.so
lib/libnixstore.so
lib/libnixutil.so
libdata/pkgconfig/nix-expr.pc
libdata/pkgconfig/nix-main.pc
libdata/pkgconfig/nix-store.pc
libexec/nix/build-remote
share/man/man1/nix-build.1.gz
share/man/man1/nix-channel.1.gz
share/man/man1/nix-collect-garbage.1.gz
share/man/man1/nix-copy-closure.1.gz
share/man/man1/nix-env.1.gz
share/man/man1/nix-hash.1.gz
share/man/man1/nix-instantiate.1.gz
share/man/man1/nix-prefetch-url.1.gz
share/man/man1/nix-shell.1.gz
share/man/man1/nix-store.1.gz
share/man/man5/nix.conf.5.gz
share/man/man8/nix-daemon.8.gz
%%PORTDOCS%%%%DOCSDIR%%/manual/figures/user-environments.png
%%PORTDOCS%%%%DOCSDIR%%/manual/images/callouts/1.gif
%%PORTDOCS%%%%DOCSDIR%%/manual/images/callouts/10.gif
%%PORTDOCS%%%%DOCSDIR%%/manual/images/callouts/11.gif
%%PORTDOCS%%%%DOCSDIR%%/manual/images/callouts/12.gif
%%PORTDOCS%%%%DOCSDIR%%/manual/images/callouts/13.gif
%%PORTDOCS%%%%DOCSDIR%%/manual/images/callouts/14.gif
%%PORTDOCS%%%%DOCSDIR%%/manual/images/callouts/15.gif
%%PORTDOCS%%%%DOCSDIR%%/manual/images/callouts/2.gif
%%PORTDOCS%%%%DOCSDIR%%/manual/images/callouts/3.gif
%%PORTDOCS%%%%DOCSDIR%%/manual/images/callouts/4.gif
%%PORTDOCS%%%%DOCSDIR%%/manual/images/callouts/5.gif
%%PORTDOCS%%%%DOCSDIR%%/manual/images/callouts/6.gif
%%PORTDOCS%%%%DOCSDIR%%/manual/images/callouts/7.gif
%%PORTDOCS%%%%DOCSDIR%%/manual/images/callouts/8.gif
%%PORTDOCS%%%%DOCSDIR%%/manual/images/callouts/9.gif
%%PORTDOCS%%%%DOCSDIR%%/manual/index.html
%%PORTDOCS%%%%DOCSDIR%%/manual/manual.html
%%DATADIR%%/add-nixbld-users
%%DATADIR%%/corepkgs/buildenv.nix
%%DATADIR%%/corepkgs/config.nix
%%DATADIR%%/corepkgs/derivation.nix
%%DATADIR%%/corepkgs/fetchurl.nix
%%DATADIR%%/corepkgs/imported-drv-to-derivation.nix
%%DATADIR%%/corepkgs/unpack-channel.nix
%%DATADIR%%/sandbox/sandbox-defaults.sb
%%DATADIR%%/sandbox/sandbox-minimal.sb
%%DATADIR%%/sandbox/sandbox-network.sb