From 67d231c0462dd53476342ed68032a930a9acaae5 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 7 Nov 2024 13:46:37 +0100 Subject: [PATCH] Revert "Merge pull request #11804 from obsidiansystems/remove-old-make" This reverts commit 619eeb658ab8ab6d7ec09d5f0c281f5ad1e10339, reversing changes made to 1af94bf4710f2937a511543e9d14815f3a67814c. --- .gitignore | 3 + Makefile | 129 +++ Makefile.config.in | 54 + config/install-sh | 527 ++++++++++ configure.ac | 456 +++++++++ doc/manual/local.mk | 236 +++++ flake.nix | 11 +- local.mk | 15 + m4/ax_cxx_compile_stdcxx.m4 | 951 ++++++++++++++++++ m4/ax_cxx_compile_stdcxx_17.m4 | 35 + maintainers/local.mk | 8 + misc/bash/local.mk | 1 + misc/fish/local.mk | 1 + misc/launchd/local.mk | 5 + misc/systemd/local.mk | 8 + misc/upstart/local.mk | 7 + misc/zsh/local.mk | 2 + mk/build-dir.mk | 10 + mk/clean.mk | 11 + mk/common-test.sh | 31 + mk/compilation-database.mk | 11 + mk/cxx-big-literal.mk | 5 + mk/debug-test.sh | 10 + mk/functions.mk | 14 + mk/install-dirs.mk | 11 + mk/install.mk | 62 ++ mk/lib.mk | 159 +++ mk/libraries.mk | 173 ++++ mk/patterns.mk | 41 + mk/platform.mk | 40 + mk/precompiled-headers.mk | 21 + mk/programs.mk | 98 ++ mk/run-test.sh | 38 + mk/templates.mk | 19 + mk/tests.mk | 30 + mk/tracing.mk | 18 + package.nix | 366 +++++++ packaging/components.nix | 8 +- packaging/dev-shell.nix | 7 +- packaging/hydra.nix | 15 +- scripts/local.mk | 13 + src/libcmd/local.mk | 15 + src/libcmd/nix-cmd.pc.in | 9 + src/libexpr-c/local.mk | 25 + src/libexpr-c/nix-expr-c.pc.in | 10 + src/libexpr-test-support/local.mk | 23 + src/libexpr-tests/local.mk | 45 + src/libexpr/local.mk | 50 + src/libexpr/nix-expr.pc.in | 10 + src/libexpr/package.nix | 4 - src/libfetchers-tests/local.mk | 37 + src/libfetchers/local.mk | 17 + src/libflake-tests/local.mk | 43 + src/libflake/flake/nix-flake.pc.in | 10 + src/libflake/local.mk | 22 + src/libmain/local.mk | 22 + src/libmain/nix-main.pc.in | 9 + src/libstore-c/local.mk | 21 + src/libstore-c/nix-store-c.pc.in | 9 + src/libstore-test-support/local.mk | 21 + src/libstore-tests/local.mk | 38 + src/libstore/local.mk | 103 ++ src/libstore/nix-store.pc.in | 10 + src/libutil-c/local.mk | 18 + src/libutil-c/nix-util-c.pc.in | 9 + src/libutil-test-support/local.mk | 19 + src/libutil-tests/local.mk | 37 + src/libutil/local.mk | 44 + src/libutil/nix-util.pc.in | 9 + src/nix/local.mk | 59 ++ src/perl/package.nix | 4 - tests/functional/build-hook-ca-fixed.nix | 2 +- tests/functional/build-hook.nix | 2 +- tests/functional/ca/config.nix | 2 - tests/functional/ca/content-addressed.nix | 2 +- tests/functional/ca/local.mk | 29 + tests/functional/ca/nix-run.sh | 3 + tests/functional/ca/nondeterministic.nix | 2 +- tests/functional/ca/racy.nix | 2 +- tests/functional/check-refs.nix | 2 +- tests/functional/check-reqs.nix | 2 +- tests/functional/check.nix | 2 +- tests/functional/chroot-store.sh | 3 + tests/functional/common/functions.sh | 9 + tests/functional/config.nix | 2 - tests/functional/dependencies.nix | 2 +- tests/functional/dyn-drv/config.nix | 2 - tests/functional/dyn-drv/local.mk | 15 + .../dyn-drv/old-daemon-error-hack.nix | 2 +- .../functional/dyn-drv/recursive-mod-json.nix | 2 +- .../functional/dyn-drv/text-hashed-output.nix | 2 +- tests/functional/export-graph.nix | 2 +- tests/functional/extra-sandbox-profile.nix | 2 +- tests/functional/failing.nix | 2 +- tests/functional/filter-source.nix | 2 +- tests/functional/fixed.nix | 2 +- tests/functional/flakes/bundle.sh | 3 + tests/functional/flakes/common.sh | 3 + tests/functional/flakes/config.sh | 1 + tests/functional/flakes/develop.sh | 3 + tests/functional/flakes/local.mk | 25 + tests/functional/flakes/run.sh | 2 + tests/functional/fod-failing.nix | 2 +- tests/functional/gc-concurrent.nix | 2 +- tests/functional/gc-runtime.nix | 2 +- tests/functional/git-hashing/local.mk | 7 + tests/functional/hermetic.nix | 2 +- tests/functional/ifd.nix | 2 +- tests/functional/import-from-derivation.nix | 2 +- tests/functional/impure-derivations.nix | 2 +- tests/functional/impure-env.nix | 2 +- tests/functional/linux-sandbox-cert-test.nix | 2 +- tests/functional/local-overlay-store/local.mk | 14 + tests/functional/local.mk | 146 +++ tests/functional/multiple-outputs.nix | 2 +- tests/functional/nar-access.nix | 2 +- tests/functional/nix-build-examples.nix | 2 +- tests/functional/parallel.nix | 2 +- tests/functional/path.nix | 2 +- tests/functional/plugins/local.mk | 11 + tests/functional/readfile-context.nix | 2 +- tests/functional/restricted.sh | 4 + tests/functional/search.nix | 2 +- tests/functional/secure-drv-outputs.nix | 2 +- tests/functional/shell-hello.nix | 2 +- tests/functional/shell.nix | 2 +- tests/functional/simple-failing.nix | 2 +- tests/functional/simple.nix | 2 +- tests/functional/structured-attrs-shell.nix | 2 +- tests/functional/structured-attrs.nix | 2 +- tests/functional/symlink-derivation.nix | 2 +- .../functional/test-libstoreconsumer/local.mk | 15 + tests/functional/timeout.nix | 2 +- tests/functional/user-envs.nix | 2 +- 134 files changed, 4722 insertions(+), 75 deletions(-) create mode 100644 Makefile create mode 100644 Makefile.config.in create mode 100755 config/install-sh create mode 100644 configure.ac create mode 100644 doc/manual/local.mk create mode 100644 local.mk create mode 100644 m4/ax_cxx_compile_stdcxx.m4 create mode 100644 m4/ax_cxx_compile_stdcxx_17.m4 create mode 100644 maintainers/local.mk create mode 100644 misc/bash/local.mk create mode 100644 misc/fish/local.mk create mode 100644 misc/launchd/local.mk create mode 100644 misc/systemd/local.mk create mode 100644 misc/upstart/local.mk create mode 100644 misc/zsh/local.mk create mode 100644 mk/build-dir.mk create mode 100644 mk/clean.mk create mode 100644 mk/common-test.sh create mode 100644 mk/compilation-database.mk create mode 100644 mk/cxx-big-literal.mk create mode 100755 mk/debug-test.sh create mode 100644 mk/functions.mk create mode 100644 mk/install-dirs.mk create mode 100644 mk/install.mk create mode 100644 mk/lib.mk create mode 100644 mk/libraries.mk create mode 100644 mk/patterns.mk create mode 100644 mk/platform.mk create mode 100644 mk/precompiled-headers.mk create mode 100644 mk/programs.mk create mode 100755 mk/run-test.sh create mode 100644 mk/templates.mk create mode 100644 mk/tests.mk create mode 100644 mk/tracing.mk create mode 100644 package.nix create mode 100644 scripts/local.mk create mode 100644 src/libcmd/local.mk create mode 100644 src/libcmd/nix-cmd.pc.in create mode 100644 src/libexpr-c/local.mk create mode 100644 src/libexpr-c/nix-expr-c.pc.in create mode 100644 src/libexpr-test-support/local.mk create mode 100644 src/libexpr-tests/local.mk create mode 100644 src/libexpr/local.mk create mode 100644 src/libexpr/nix-expr.pc.in create mode 100644 src/libfetchers-tests/local.mk create mode 100644 src/libfetchers/local.mk create mode 100644 src/libflake-tests/local.mk create mode 100644 src/libflake/flake/nix-flake.pc.in create mode 100644 src/libflake/local.mk create mode 100644 src/libmain/local.mk create mode 100644 src/libmain/nix-main.pc.in create mode 100644 src/libstore-c/local.mk create mode 100644 src/libstore-c/nix-store-c.pc.in create mode 100644 src/libstore-test-support/local.mk create mode 100644 src/libstore-tests/local.mk create mode 100644 src/libstore/local.mk create mode 100644 src/libstore/nix-store.pc.in create mode 100644 src/libutil-c/local.mk create mode 100644 src/libutil-c/nix-util-c.pc.in create mode 100644 src/libutil-test-support/local.mk create mode 100644 src/libutil-tests/local.mk create mode 100644 src/libutil/local.mk create mode 100644 src/libutil/nix-util.pc.in create mode 100644 src/nix/local.mk delete mode 100644 tests/functional/ca/config.nix create mode 100644 tests/functional/ca/local.mk delete mode 100644 tests/functional/config.nix delete mode 100644 tests/functional/dyn-drv/config.nix create mode 100644 tests/functional/dyn-drv/local.mk create mode 100644 tests/functional/flakes/local.mk create mode 100644 tests/functional/git-hashing/local.mk create mode 100644 tests/functional/local-overlay-store/local.mk create mode 100644 tests/functional/local.mk create mode 100644 tests/functional/plugins/local.mk create mode 100644 tests/functional/test-libstoreconsumer/local.mk diff --git a/.gitignore b/.gitignore index de1183977..11a80ab5b 100644 --- a/.gitignore +++ b/.gitignore @@ -102,6 +102,9 @@ perl/Makefile.config /tests/functional/restricted-innocent /tests/functional/shell /tests/functional/shell.drv +/tests/functional/config.nix +/tests/functional/ca/config.nix +/tests/functional/dyn-drv/config.nix /tests/functional/repl-result-out /tests/functional/debugger-test-out /tests/functional/test-libstoreconsumer/test-libstoreconsumer diff --git a/Makefile b/Makefile new file mode 100644 index 000000000..ee1a0de31 --- /dev/null +++ b/Makefile @@ -0,0 +1,129 @@ +# External build directory support + +include mk/build-dir.mk + +-include $(buildprefix)Makefile.config +clean-files += $(buildprefix)Makefile.config + +# List makefiles + +include mk/platform.mk + +ifeq ($(ENABLE_BUILD), yes) +makefiles = \ + mk/precompiled-headers.mk \ + local.mk \ + src/libutil/local.mk \ + src/libstore/local.mk \ + src/libfetchers/local.mk \ + src/libmain/local.mk \ + src/libexpr/local.mk \ + src/libflake/local.mk \ + src/libcmd/local.mk \ + src/nix/local.mk \ + src/libutil-c/local.mk \ + src/libstore-c/local.mk \ + src/libexpr-c/local.mk + +ifdef HOST_UNIX +makefiles += \ + scripts/local.mk \ + maintainers/local.mk \ + misc/bash/local.mk \ + misc/fish/local.mk \ + misc/zsh/local.mk \ + misc/systemd/local.mk \ + misc/launchd/local.mk \ + misc/upstart/local.mk +endif +endif + +ifeq ($(ENABLE_UNIT_TESTS), yes) +makefiles += \ + src/libutil-tests/local.mk \ + src/libutil-test-support/local.mk \ + src/libstore-tests/local.mk \ + src/libstore-test-support/local.mk \ + src/libfetchers-tests/local.mk \ + src/libexpr-tests/local.mk \ + src/libexpr-test-support/local.mk \ + src/libflake-tests/local.mk +endif + +ifeq ($(ENABLE_FUNCTIONAL_TESTS), yes) +ifdef HOST_UNIX +makefiles += \ + tests/functional/local.mk \ + tests/functional/flakes/local.mk \ + tests/functional/ca/local.mk \ + tests/functional/git-hashing/local.mk \ + tests/functional/dyn-drv/local.mk \ + tests/functional/local-overlay-store/local.mk \ + tests/functional/test-libstoreconsumer/local.mk \ + tests/functional/plugins/local.mk +endif +endif + +# Some makefiles require access to built programs and must be included late. +makefiles-late = + +ifeq ($(ENABLE_DOC_GEN), yes) +makefiles-late += doc/manual/local.mk +endif + +# Miscellaneous global Flags + +OPTIMIZE = 1 + +ifeq ($(OPTIMIZE), 1) + GLOBAL_CXXFLAGS += -O3 $(CXXLTO) + GLOBAL_LDFLAGS += $(CXXLTO) +else + GLOBAL_CXXFLAGS += -O0 -U_FORTIFY_SOURCE + unexport NIX_HARDENING_ENABLE +endif + +ifdef HOST_WINDOWS + # Windows DLLs are stricter about symbol visibility than Unix shared + # objects --- see https://gcc.gnu.org/wiki/Visibility for details. + # This is a temporary sledgehammer to export everything like on Unix, + # and not detail with this yet. + # + # TODO do not do this, and instead do fine-grained export annotations. + GLOBAL_LDFLAGS += -Wl,--export-all-symbols + GLOBAL_CXXFLAGS += -D_WIN32_WINNT=0x0602 +endif + +GLOBAL_CXXFLAGS += -g -Wall -Wdeprecated-copy -Wignored-qualifiers -Wimplicit-fallthrough -Werror=unused-result -Werror=suggest-override -include $(buildprefix)config.h -std=c++2a -I src + +# Include the main lib, causing rules to be defined + +include mk/lib.mk + +# Fallback stub rules for better UX when things are disabled +# +# These must be defined after `mk/lib.mk`. Otherwise the first rule +# incorrectly becomes the default target. + +ifneq ($(ENABLE_UNIT_TESTS), yes) +.PHONY: check +check: + @echo "Unit tests are disabled. Configure without '--disable-unit-tests', or avoid calling 'make check'." + @exit 1 +endif + +ifneq ($(ENABLE_FUNCTIONAL_TESTS), yes) +.PHONY: installcheck +installcheck: + @echo "Functional tests are disabled. Configure without '--disable-functional-tests', or avoid calling 'make installcheck'." + @exit 1 +endif + +# Documentation fallback stub rules. + +ifneq ($(ENABLE_DOC_GEN), yes) +.PHONY: manual-html manpages +manual-html manpages: + @echo "Generated docs are disabled. Configure without '--disable-doc-gen', or avoid calling 'make manpages' and 'make manual-html'." + @exit 1 +endif diff --git a/Makefile.config.in b/Makefile.config.in new file mode 100644 index 000000000..3100d2073 --- /dev/null +++ b/Makefile.config.in @@ -0,0 +1,54 @@ +AR = @AR@ +BDW_GC_LIBS = @BDW_GC_LIBS@ +BOOST_LDFLAGS = @BOOST_LDFLAGS@ +BUILD_SHARED_LIBS = @BUILD_SHARED_LIBS@ +CC = @CC@ +CFLAGS = @CFLAGS@ +CXX = @CXX@ +CXXFLAGS = @CXXFLAGS@ +CXXLTO = @CXXLTO@ +EDITLINE_LIBS = @EDITLINE_LIBS@ +ENABLE_BUILD = @ENABLE_BUILD@ +ENABLE_DOC_GEN = @ENABLE_DOC_GEN@ +ENABLE_FUNCTIONAL_TESTS = @ENABLE_FUNCTIONAL_TESTS@ +ENABLE_S3 = @ENABLE_S3@ +ENABLE_UNIT_TESTS = @ENABLE_UNIT_TESTS@ +GTEST_LIBS = @GTEST_LIBS@ +HAVE_LIBCPUID = @HAVE_LIBCPUID@ +HAVE_SECCOMP = @HAVE_SECCOMP@ +HOST_OS = @host_os@ +INSTALL_UNIT_TESTS = @INSTALL_UNIT_TESTS@ +LDFLAGS = @LDFLAGS@ +LIBARCHIVE_LIBS = @LIBARCHIVE_LIBS@ +LIBBROTLI_LIBS = @LIBBROTLI_LIBS@ +LIBCURL_LIBS = @LIBCURL_LIBS@ +LIBGIT2_LIBS = @LIBGIT2_LIBS@ +LIBSECCOMP_LIBS = @LIBSECCOMP_LIBS@ +LOWDOWN_LIBS = @LOWDOWN_LIBS@ +OPENSSL_LIBS = @OPENSSL_LIBS@ +PACKAGE_NAME = @PACKAGE_NAME@ +PACKAGE_VERSION = @PACKAGE_VERSION@ +SHELL = @bash@ +SODIUM_LIBS = @SODIUM_LIBS@ +SQLITE3_LIBS = @SQLITE3_LIBS@ +bash = @bash@ +bindir = @bindir@ +checkbindir = @checkbindir@ +checklibdir = @checklibdir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +embedded_sandbox_shell = @embedded_sandbox_shell@ +exec_prefix = @exec_prefix@ +includedir = @includedir@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localstatedir = @localstatedir@ +lsof = @lsof@ +mandir = @mandir@ +pkglibdir = $(libdir)/$(PACKAGE_NAME) +prefix = @prefix@ +sandbox_shell = @sandbox_shell@ +storedir = @storedir@ +sysconfdir = @sysconfdir@ +system = @system@ diff --git a/config/install-sh b/config/install-sh new file mode 100755 index 000000000..377bb8687 --- /dev/null +++ b/config/install-sh @@ -0,0 +1,527 @@ +#!/bin/sh +# install - install a program, script, or datafile + +scriptversion=2011-11-20.07; # UTC + +# This originates from X11R5 (mit/util/scripts/install.sh), which was +# later released in X11R6 (xc/config/util/install.sh) with the +# following copyright and license. +# +# Copyright (C) 1994 X Consortium +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN +# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- +# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +# Except as contained in this notice, the name of the X Consortium shall not +# be used in advertising or otherwise to promote the sale, use or other deal- +# ings in this Software without prior written authorization from the X Consor- +# tium. +# +# +# FSF changes to this file are in the public domain. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# 'make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. + +nl=' +' +IFS=" "" $nl" + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit=${DOITPROG-} +if test -z "$doit"; then + doit_exec=exec +else + doit_exec=$doit +fi + +# Put in absolute file names if you don't have them in your path; +# or use environment vars. + +chgrpprog=${CHGRPPROG-chgrp} +chmodprog=${CHMODPROG-chmod} +chownprog=${CHOWNPROG-chown} +cmpprog=${CMPPROG-cmp} +cpprog=${CPPROG-cp} +mkdirprog=${MKDIRPROG-mkdir} +mvprog=${MVPROG-mv} +rmprog=${RMPROG-rm} +stripprog=${STRIPPROG-strip} + +posix_glob='?' +initialize_posix_glob=' + test "$posix_glob" != "?" || { + if (set -f) 2>/dev/null; then + posix_glob= + else + posix_glob=: + fi + } +' + +posix_mkdir= + +# Desired mode of installed file. +mode=0755 + +chgrpcmd= +chmodcmd=$chmodprog +chowncmd= +mvcmd=$mvprog +rmcmd="$rmprog -f" +stripcmd= + +src= +dst= +dir_arg= +dst_arg= + +copy_on_change=false +no_target_directory= + +usage="\ +Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE + or: $0 [OPTION]... SRCFILES... DIRECTORY + or: $0 [OPTION]... -t DIRECTORY SRCFILES... + or: $0 [OPTION]... -d DIRECTORIES... + +In the 1st form, copy SRCFILE to DSTFILE. +In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. +In the 4th, create DIRECTORIES. + +Options: + --help display this help and exit. + --version display version info and exit. + + -c (ignored) + -C install only if different (preserve the last data modification time) + -d create directories instead of installing files. + -g GROUP $chgrpprog installed files to GROUP. + -m MODE $chmodprog installed files to MODE. + -o USER $chownprog installed files to USER. + -s $stripprog installed files. + -t DIRECTORY install into DIRECTORY. + -T report an error if DSTFILE is a directory. + +Environment variables override the default commands: + CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG + RMPROG STRIPPROG +" + +while test $# -ne 0; do + case $1 in + -c) ;; + + -C) copy_on_change=true;; + + -d) dir_arg=true;; + + -g) chgrpcmd="$chgrpprog $2" + shift;; + + --help) echo "$usage"; exit $?;; + + -m) mode=$2 + case $mode in + *' '* | *' '* | *' +'* | *'*'* | *'?'* | *'['*) + echo "$0: invalid mode: $mode" >&2 + exit 1;; + esac + shift;; + + -o) chowncmd="$chownprog $2" + shift;; + + -s) stripcmd=$stripprog;; + + -t) dst_arg=$2 + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + shift;; + + -T) no_target_directory=true;; + + --version) echo "$0 $scriptversion"; exit $?;; + + --) shift + break;; + + -*) echo "$0: invalid option: $1" >&2 + exit 1;; + + *) break;; + esac + shift +done + +if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then + # When -d is used, all remaining arguments are directories to create. + # When -t is used, the destination is already specified. + # Otherwise, the last argument is the destination. Remove it from $@. + for arg + do + if test -n "$dst_arg"; then + # $@ is not empty: it contains at least $arg. + set fnord "$@" "$dst_arg" + shift # fnord + fi + shift # arg + dst_arg=$arg + # Protect names problematic for 'test' and other utilities. + case $dst_arg in + -* | [=\(\)!]) dst_arg=./$dst_arg;; + esac + done +fi + +if test $# -eq 0; then + if test -z "$dir_arg"; then + echo "$0: no input file specified." >&2 + exit 1 + fi + # It's OK to call 'install-sh -d' without argument. + # This can happen when creating conditional directories. + exit 0 +fi + +if test -z "$dir_arg"; then + do_exit='(exit $ret); exit $ret' + trap "ret=129; $do_exit" 1 + trap "ret=130; $do_exit" 2 + trap "ret=141; $do_exit" 13 + trap "ret=143; $do_exit" 15 + + # Set umask so as not to create temps with too-generous modes. + # However, 'strip' requires both read and write access to temps. + case $mode in + # Optimize common cases. + *644) cp_umask=133;; + *755) cp_umask=22;; + + *[0-7]) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw='% 200' + fi + cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;; + *) + if test -z "$stripcmd"; then + u_plus_rw= + else + u_plus_rw=,u+rw + fi + cp_umask=$mode$u_plus_rw;; + esac +fi + +for src +do + # Protect names problematic for 'test' and other utilities. + case $src in + -* | [=\(\)!]) src=./$src;; + esac + + if test -n "$dir_arg"; then + dst=$src + dstdir=$dst + test -d "$dstdir" + dstdir_status=$? + else + + # Waiting for this to be detected by the "$cpprog $src $dsttmp" command + # might cause directories to be created, which would be especially bad + # if $src (and thus $dsttmp) contains '*'. + if test ! -f "$src" && test ! -d "$src"; then + echo "$0: $src does not exist." >&2 + exit 1 + fi + + if test -z "$dst_arg"; then + echo "$0: no destination specified." >&2 + exit 1 + fi + dst=$dst_arg + + # If destination is a directory, append the input filename; won't work + # if double slashes aren't ignored. + if test -d "$dst"; then + if test -n "$no_target_directory"; then + echo "$0: $dst_arg: Is a directory" >&2 + exit 1 + fi + dstdir=$dst + dst=$dstdir/`basename "$src"` + dstdir_status=0 + else + # Prefer dirname, but fall back on a substitute if dirname fails. + dstdir=` + (dirname "$dst") 2>/dev/null || + expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$dst" : 'X\(//\)[^/]' \| \ + X"$dst" : 'X\(//\)$' \| \ + X"$dst" : 'X\(/\)' \| . 2>/dev/null || + echo X"$dst" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q' + ` + + test -d "$dstdir" + dstdir_status=$? + fi + fi + + obsolete_mkdir_used=false + + if test $dstdir_status != 0; then + case $posix_mkdir in + '') + # Create intermediate dirs using mode 755 as modified by the umask. + # This is like FreeBSD 'install' as of 1997-10-28. + umask=`umask` + case $stripcmd.$umask in + # Optimize common cases. + *[2367][2367]) mkdir_umask=$umask;; + .*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;; + + *[0-7]) + mkdir_umask=`expr $umask + 22 \ + - $umask % 100 % 40 + $umask % 20 \ + - $umask % 10 % 4 + $umask % 2 + `;; + *) mkdir_umask=$umask,go-w;; + esac + + # With -d, create the new directory with the user-specified mode. + # Otherwise, rely on $mkdir_umask. + if test -n "$dir_arg"; then + mkdir_mode=-m$mode + else + mkdir_mode= + fi + + posix_mkdir=false + case $umask in + *[123567][0-7][0-7]) + # POSIX mkdir -p sets u+wx bits regardless of umask, which + # is incompatible with FreeBSD 'install' when (umask & 300) != 0. + ;; + *) + tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$ + trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0 + + if (umask $mkdir_umask && + exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1 + then + if test -z "$dir_arg" || { + # Check for POSIX incompatibilities with -m. + # HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or + # other-writable bit of parent directory when it shouldn't. + # FreeBSD 6.1 mkdir -m -p sets mode of existing directory. + ls_ld_tmpdir=`ls -ld "$tmpdir"` + case $ls_ld_tmpdir in + d????-?r-*) different_mode=700;; + d????-?--*) different_mode=755;; + *) false;; + esac && + $mkdirprog -m$different_mode -p -- "$tmpdir" && { + ls_ld_tmpdir_1=`ls -ld "$tmpdir"` + test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1" + } + } + then posix_mkdir=: + fi + rmdir "$tmpdir/d" "$tmpdir" + else + # Remove any dirs left behind by ancient mkdir implementations. + rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null + fi + trap '' 0;; + esac;; + esac + + if + $posix_mkdir && ( + umask $mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir" + ) + then : + else + + # The umask is ridiculous, or mkdir does not conform to POSIX, + # or it failed possibly due to a race condition. Create the + # directory the slow way, step by step, checking for races as we go. + + case $dstdir in + /*) prefix='/';; + [-=\(\)!]*) prefix='./';; + *) prefix='';; + esac + + eval "$initialize_posix_glob" + + oIFS=$IFS + IFS=/ + $posix_glob set -f + set fnord $dstdir + shift + $posix_glob set +f + IFS=$oIFS + + prefixes= + + for d + do + test X"$d" = X && continue + + prefix=$prefix$d + if test -d "$prefix"; then + prefixes= + else + if $posix_mkdir; then + (umask=$mkdir_umask && + $doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break + # Don't fail if two instances are running concurrently. + test -d "$prefix" || exit 1 + else + case $prefix in + *\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;; + *) qprefix=$prefix;; + esac + prefixes="$prefixes '$qprefix'" + fi + fi + prefix=$prefix/ + done + + if test -n "$prefixes"; then + # Don't fail if two instances are running concurrently. + (umask $mkdir_umask && + eval "\$doit_exec \$mkdirprog $prefixes") || + test -d "$dstdir" || exit 1 + obsolete_mkdir_used=true + fi + fi + fi + + if test -n "$dir_arg"; then + { test -z "$chowncmd" || $doit $chowncmd "$dst"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } && + { test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false || + test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1 + else + + # Make a couple of temp file names in the proper directory. + dsttmp=$dstdir/_inst.$$_ + rmtmp=$dstdir/_rm.$$_ + + # Trap to clean up those temp files at exit. + trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 + + # Copy the file name to the temp name. + (umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") && + + # and set any options; do chmod last to preserve setuid bits. + # + # If any of these fail, we abort the whole thing. If we want to + # ignore errors from any of these, just make sure not to ignore + # errors from the above "$doit $cpprog $src $dsttmp" command. + # + { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } && + { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } && + { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } && + { test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } && + + # If -C, don't bother to copy if it wouldn't change the file. + if $copy_on_change && + old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` && + new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` && + + eval "$initialize_posix_glob" && + $posix_glob set -f && + set X $old && old=:$2:$4:$5:$6 && + set X $new && new=:$2:$4:$5:$6 && + $posix_glob set +f && + + test "$old" = "$new" && + $cmpprog "$dst" "$dsttmp" >/dev/null 2>&1 + then + rm -f "$dsttmp" + else + # Rename the file to the real destination. + $doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null || + + # The rename failed, perhaps because mv can't rename something else + # to itself, or perhaps because mv is so ancient that it does not + # support -f. + { + # Now remove or move aside any old file at destination location. + # We try this two ways since rm can't unlink itself on some + # systems and the destination file might be busy for other + # reasons. In this case, the final cleanup might fail but the new + # file should still install successfully. + { + test ! -f "$dst" || + $doit $rmcmd -f "$dst" 2>/dev/null || + { $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null && + { $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; } + } || + { echo "$0: cannot unlink or rename $dst" >&2 + (exit 1); exit 1 + } + } && + + # Now rename the file to the real destination. + $doit $mvcmd "$dsttmp" "$dst" + } + fi || exit 1 + + trap '' 0 + fi +done + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "scriptversion=" +# time-stamp-format: "%:y-%02m-%02d.%02H" +# time-stamp-time-zone: "UTC" +# time-stamp-end: "; # UTC" +# End: diff --git a/configure.ac b/configure.ac new file mode 100644 index 000000000..4df5c80f0 --- /dev/null +++ b/configure.ac @@ -0,0 +1,456 @@ +AC_INIT([nix],[m4_esyscmd(bash -c "echo -n $(cat ./.version)$VERSION_SUFFIX")]) +AC_CONFIG_MACRO_DIRS([m4]) +AC_CONFIG_SRCDIR(README.md) +AC_CONFIG_AUX_DIR(config) + +AC_PROG_SED + +# Construct a Nix system name (like "i686-linux"): +# https://www.gnu.org/software/autoconf/manual/html_node/Canonicalizing.html#index-AC_005fCANONICAL_005fHOST-1 +# The inital value is produced by the `config/config.guess` script: +# upstream: https://git.savannah.gnu.org/cgit/config.git/tree/config.guess +# It has the following form, which is not documented anywhere: +# --[][-] +# If `./configure` is passed any of the `--host`, `--build`, `--target` options, the value comes from `config/config.sub` instead: +# upstream: https://git.savannah.gnu.org/cgit/config.git/tree/config.sub +AC_CANONICAL_HOST +AC_MSG_CHECKING([for the canonical Nix system name]) + +AC_ARG_WITH(system, AS_HELP_STRING([--with-system=SYSTEM],[Platform identifier (e.g., `i686-linux').]), + [system=$withval], + [case "$host_cpu" in + i*86) + machine_name="i686";; + amd64) + machine_name="x86_64";; + armv6|armv7) + machine_name="${host_cpu}l";; + *) + machine_name="$host_cpu";; + esac + + case "$host_os" in + linux-gnu*|linux-musl*) + # For backward compatibility, strip the `-gnu' part. + system="$machine_name-linux";; + *) + # Strip the version number from names such as `gnu0.3', + # `darwin10.2.0', etc. + system="$machine_name-`echo $host_os | "$SED" -e's/@<:@0-9.@:>@*$//g'`";; + esac]) + +AC_MSG_RESULT($system) +AC_SUBST(system) +AC_DEFINE_UNQUOTED(SYSTEM, ["$system"], [platform identifier ('cpu-os')]) + + +# State should be stored in /nix/var, unless the user overrides it explicitly. +test "$localstatedir" = '${prefix}/var' && localstatedir=/nix/var + +# Assign a default value to C{,XX}FLAGS as the default configure script sets them +# to -O2 otherwise, which we don't want to have hardcoded +CFLAGS=${CFLAGS-""} +CXXFLAGS=${CXXFLAGS-""} + +AC_PROG_CC +AC_PROG_CXX +AC_PROG_CPP + +AC_CHECK_TOOL([AR], [ar]) + +# Use 64-bit file system calls so that we can support files > 2 GiB. +AC_SYS_LARGEFILE + + +# OS-specific stuff. +case "$host_os" in + solaris*) + # Solaris requires -lsocket -lnsl for network functions + LDFLAGS="-lsocket -lnsl $LDFLAGS" + ;; + darwin*) + # Need to link to libsandbox. + LDFLAGS="-lsandbox $LDFLAGS" + ;; +esac + + +ENSURE_NO_GCC_BUG_80431 + + +# Check for pubsetbuf. +AC_MSG_CHECKING([for pubsetbuf]) +AC_LANG_PUSH(C++) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include +using namespace std; +static char buf[1024];]], + [[cerr.rdbuf()->pubsetbuf(buf, sizeof(buf));]])], + [AC_MSG_RESULT(yes) AC_DEFINE(HAVE_PUBSETBUF, 1, [Whether pubsetbuf is available.])], + AC_MSG_RESULT(no)) +AC_LANG_POP(C++) + + +AC_CHECK_FUNCS([statvfs pipe2 close_range]) + + +# Check for lutimes and utimensat, optionally used for changing the +# mtime of symlinks. +AC_CHECK_DECLS([AT_SYMLINK_NOFOLLOW], [], [], [[#include ]]) +AC_CHECK_FUNCS([lutimes utimensat]) + + +# Check whether the store optimiser can optimise symlinks. +AC_MSG_CHECKING([whether it is possible to create a link to a symlink]) +ln -s bla tmp_link +if ln tmp_link tmp_link2 2> /dev/null; then + AC_MSG_RESULT(yes) + AC_DEFINE(CAN_LINK_SYMLINK, 1, [Whether link() works on symlinks.]) +else + AC_MSG_RESULT(no) +fi +rm -f tmp_link tmp_link2 + + +# Check for . +AC_LANG_PUSH(C++) +AC_CHECK_HEADERS([locale]) +AC_LANG_POP(C++) + + +AC_DEFUN([NEED_PROG], +[ +AC_PATH_PROG($1, $2) +if test -z "$$1"; then + AC_MSG_ERROR([$2 is required]) +fi +]) + +NEED_PROG(bash, bash) +AC_PATH_PROG(flex, flex, false) +AC_PATH_PROG(bison, bison, false) +AC_PATH_PROG(dot, dot) +AC_PATH_PROG(lsof, lsof, lsof) + + +AC_SUBST(coreutils, [$(dirname $(type -p cat))]) + + +AC_ARG_WITH(store-dir, AS_HELP_STRING([--with-store-dir=PATH],[path of the Nix store (defaults to /nix/store)]), + storedir=$withval, storedir='/nix/store') +AC_SUBST(storedir) + + +# Running the functional tests without building Nix is useful for testing +# different pre-built versions of Nix against each other. +AC_ARG_ENABLE(build, AS_HELP_STRING([--disable-build],[Do not build nix]), + ENABLE_BUILD=$enableval, ENABLE_BUILD=yes) +AC_SUBST(ENABLE_BUILD) + +# Building without unit tests is useful for bootstrapping with a smaller footprint +# or running the tests in a separate derivation. Otherwise, we do compile and +# run them. + +AC_ARG_ENABLE(unit-tests, AS_HELP_STRING([--disable-unit-tests],[Do not build the tests]), + ENABLE_UNIT_TESTS=$enableval, ENABLE_UNIT_TESTS=$ENABLE_BUILD) +AC_SUBST(ENABLE_UNIT_TESTS) + +AS_IF( + [test "$ENABLE_BUILD" == "no" && test "$ENABLE_UNIT_TESTS" == "yes"], + [AC_MSG_ERROR([Cannot enable unit tests when building overall is disabled. Please do not pass '--enable-unit-tests' or do not pass '--disable-build'.])]) + +AC_ARG_ENABLE(functional-tests, AS_HELP_STRING([--disable-functional-tests],[Do not build the tests]), + ENABLE_FUNCTIONAL_TESTS=$enableval, ENABLE_FUNCTIONAL_TESTS=yes) +AC_SUBST(ENABLE_FUNCTIONAL_TESTS) + +# documentation generation switch +AC_ARG_ENABLE(doc-gen, AS_HELP_STRING([--disable-doc-gen],[disable documentation generation]), + ENABLE_DOC_GEN=$enableval, ENABLE_DOC_GEN=$ENABLE_BUILD) +AC_SUBST(ENABLE_DOC_GEN) + +AS_IF( + [test "$ENABLE_BUILD" == "no" && test "$ENABLE_DOC_GEN" == "yes"], + [AC_MSG_ERROR([Cannot enable generated docs when building overall is disabled. Please do not pass '--enable-doc-gen' or do not pass '--disable-build'.])]) + +AS_IF( + [test "$ENABLE_FUNCTIONAL_TESTS" == "yes" || test "$ENABLE_DOC_GEN" == "yes"], + [NEED_PROG(jq, jq)]) + +AS_IF( + [test "$ENABLE_DOC_GEN" == "yes"], + [NEED_PROG(man, man)]) + +AS_IF([test "$ENABLE_BUILD" == "yes"],[ + +# Look for boost, a required dependency. +# Note that AX_BOOST_BASE only exports *CPP* BOOST_CPPFLAGS, no CXX flags, +# and CPPFLAGS are not passed to the C++ compiler automatically. +# Thus we append the returned CPPFLAGS to the CXXFLAGS here. +AX_BOOST_BASE([1.66], [CXXFLAGS="$BOOST_CPPFLAGS $CXXFLAGS"], [AC_MSG_ERROR([Nix requires boost.])]) +# For unknown reasons, setting this directly in the ACTION-IF-FOUND above +# ends up with LDFLAGS being empty, so we set it afterwards. +LDFLAGS="$BOOST_LDFLAGS $LDFLAGS" + +# On some platforms, new-style atomics need a helper library +AC_MSG_CHECKING(whether -latomic is needed) +AC_LINK_IFELSE([AC_LANG_SOURCE([[ +#include +uint64_t v; +int main() { + return (int)__atomic_load_n(&v, __ATOMIC_ACQUIRE); +}]])], GCC_ATOMIC_BUILTINS_NEED_LIBATOMIC=no, GCC_ATOMIC_BUILTINS_NEED_LIBATOMIC=yes) +AC_MSG_RESULT($GCC_ATOMIC_BUILTINS_NEED_LIBATOMIC) +if test "x$GCC_ATOMIC_BUILTINS_NEED_LIBATOMIC" = xyes; then + LDFLAGS="-latomic $LDFLAGS" +fi + +AC_ARG_ENABLE(install-unit-tests, AS_HELP_STRING([--enable-install-unit-tests],[Install the unit tests for running later (default no)]), + INSTALL_UNIT_TESTS=$enableval, INSTALL_UNIT_TESTS=no) +AC_SUBST(INSTALL_UNIT_TESTS) + +AC_ARG_WITH(check-bin-dir, AS_HELP_STRING([--with-check-bin-dir=PATH],[path to install unit tests for running later (defaults to $libexecdir/nix)]), + checkbindir=$withval, checkbindir=$libexecdir/nix) +AC_SUBST(checkbindir) + +AC_ARG_WITH(check-lib-dir, AS_HELP_STRING([--with-check-lib-dir=PATH],[path to install unit tests for running later (defaults to $libdir)]), + checklibdir=$withval, checklibdir=$libdir) +AC_SUBST(checklibdir) + +# LTO is currently broken with clang for unknown reasons; ld segfaults in the llvm plugin +AC_ARG_ENABLE(lto, AS_HELP_STRING([--enable-lto],[Enable LTO (only supported with GCC) [default=no]]), + lto=$enableval, lto=no) +if test "$lto" = yes; then + if $CXX --version | grep -q GCC; then + AC_SUBST(CXXLTO, [-flto=jobserver]) + else + echo "error: LTO is only supported with GCC at the moment" >&2 + exit 1 + fi +else + AC_SUBST(CXXLTO, [""]) +fi + +PKG_PROG_PKG_CONFIG + +AC_ARG_ENABLE(shared, AS_HELP_STRING([--enable-shared],[Build shared libraries for Nix [default=yes]]), + shared=$enableval, shared=yes) +if test "$shared" = yes; then + AC_SUBST(BUILD_SHARED_LIBS, 1, [Whether to build shared libraries.]) +else + AC_SUBST(BUILD_SHARED_LIBS, 0, [Whether to build shared libraries.]) + PKG_CONFIG="$PKG_CONFIG --static" +fi + +# Look for OpenSSL, a required dependency. FIXME: this is only (maybe) +# used by S3BinaryCacheStore. +PKG_CHECK_MODULES([OPENSSL], [libcrypto >= 1.1.1], [CXXFLAGS="$OPENSSL_CFLAGS $CXXFLAGS"]) + + +# Look for libarchive. +PKG_CHECK_MODULES([LIBARCHIVE], [libarchive >= 3.1.2], [CXXFLAGS="$LIBARCHIVE_CFLAGS $CXXFLAGS"]) +# Workaround until https://github.com/libarchive/libarchive/issues/1446 is fixed +if test "$shared" != yes; then + LIBARCHIVE_LIBS+=' -lz' +fi + +# Look for SQLite, a required dependency. +PKG_CHECK_MODULES([SQLITE3], [sqlite3 >= 3.6.19], [CXXFLAGS="$SQLITE3_CFLAGS $CXXFLAGS"]) + +# Look for libcurl, a required dependency. +PKG_CHECK_MODULES([LIBCURL], [libcurl], [CXXFLAGS="$LIBCURL_CFLAGS $CXXFLAGS"]) + +# Look for editline or readline, a required dependency. +# The the libeditline.pc file was added only in libeditline >= 1.15.2, +# see https://github.com/troglobit/editline/commit/0a8f2ef4203c3a4a4726b9dd1336869cd0da8607, +# Older versions are no longer supported. +AC_ARG_WITH( + [readline-flavor], + AS_HELP_STRING([--with-readline-flavor],[Which library to use for nice line editting with the Nix language REPL" [default=editline]]), + [readline_flavor=$withval], + [readline_flavor=editline]) +AS_CASE(["$readline_flavor"], + [editline], [ + readline_flavor_pc=libeditline + ], + [readline], [ + readline_flavor_pc=readline + AC_DEFINE([USE_READLINE], [1], [Use readline instead of editline]) + ], + [AC_MSG_ERROR([bad value "$readline_flavor" for --with-readline-flavor, must be one of: editline, readline])]) +PKG_CHECK_MODULES([EDITLINE], [$readline_flavor_pc], [CXXFLAGS="$EDITLINE_CFLAGS $CXXFLAGS"]) + +# Look for libsodium. +PKG_CHECK_MODULES([SODIUM], [libsodium], [CXXFLAGS="$SODIUM_CFLAGS $CXXFLAGS"]) + +# Look for libbrotli{enc,dec}. +PKG_CHECK_MODULES([LIBBROTLI], [libbrotlienc libbrotlidec], [CXXFLAGS="$LIBBROTLI_CFLAGS $CXXFLAGS"]) + +# Look for libcpuid. +have_libcpuid= +if test "$machine_name" = "x86_64"; then + AC_ARG_ENABLE([cpuid], + AS_HELP_STRING([--disable-cpuid], [Do not determine microarchitecture levels with libcpuid (relevant to x86_64 only)])) + if test "x$enable_cpuid" != "xno"; then + PKG_CHECK_MODULES([LIBCPUID], [libcpuid], + [CXXFLAGS="$LIBCPUID_CFLAGS $CXXFLAGS" + have_libcpuid=1 + AC_DEFINE([HAVE_LIBCPUID], [1], [Use libcpuid])] + ) + fi +fi +AC_SUBST(HAVE_LIBCPUID, [$have_libcpuid]) + + +# Look for libseccomp, required for Linux sandboxing. +case "$host_os" in + linux*) + AC_ARG_ENABLE([seccomp-sandboxing], + AS_HELP_STRING([--disable-seccomp-sandboxing],[Don't build support for seccomp sandboxing (only recommended if your arch doesn't support libseccomp yet!) + ])) + if test "x$enable_seccomp_sandboxing" != "xno"; then + PKG_CHECK_MODULES([LIBSECCOMP], [libseccomp], + [CXXFLAGS="$LIBSECCOMP_CFLAGS $CXXFLAGS" CFLAGS="$LIBSECCOMP_CFLAGS $CFLAGS"]) + have_seccomp=1 + AC_DEFINE([HAVE_SECCOMP], [1], [Whether seccomp is available and should be used for sandboxing.]) + AC_COMPILE_IFELSE([ + AC_LANG_SOURCE([[ + #include + #ifndef __SNR_fchmodat2 + # error "Missing support for fchmodat2" + #endif + ]]) + ], [], [ + echo "libseccomp is missing __SNR_fchmodat2. Please provide libseccomp 2.5.5 or later" + exit 1 + ]) + else + have_seccomp= + fi + ;; + *) + have_seccomp= + ;; +esac +AC_SUBST(HAVE_SECCOMP, [$have_seccomp]) + +# Optional dependencies for better normalizing file system data +AC_CHECK_HEADERS([sys/xattr.h]) +AS_IF([test "$ac_cv_header_sys_xattr_h" = "yes"],[ + AC_CHECK_FUNCS([llistxattr lremovexattr]) + AS_IF([test "$ac_cv_func_llistxattr" = "yes" && test "$ac_cv_func_lremovexattr" = "yes"],[ + AC_DEFINE([HAVE_ACL_SUPPORT], [1], [Define if we can manipulate file system Access Control Lists]) + ]) +]) + +# Look for aws-cpp-sdk-s3. +AC_LANG_PUSH(C++) +AC_CHECK_HEADERS([aws/s3/S3Client.h], + [AC_DEFINE([ENABLE_S3], [1], [Whether to enable S3 support via aws-sdk-cpp.]) enable_s3=1], + [AC_DEFINE([ENABLE_S3], [0], [Whether to enable S3 support via aws-sdk-cpp.]) enable_s3=]) +AC_SUBST(ENABLE_S3, [$enable_s3]) +AC_LANG_POP(C++) + + +# Whether to use the Boehm garbage collector. +AC_ARG_ENABLE(gc, AS_HELP_STRING([--enable-gc],[enable garbage collection in the Nix expression evaluator (requires Boehm GC) [default=yes]]), + gc=$enableval, gc=yes) +if test "$gc" = yes; then + PKG_CHECK_MODULES([BDW_GC], [bdw-gc]) + CXXFLAGS="$BDW_GC_CFLAGS $CXXFLAGS" + AC_DEFINE(HAVE_BOEHMGC, 1, [Whether to use the Boehm garbage collector.]) + + # See `fixupBoehmStackPointer`, for the integration between Boehm GC + # and Boost coroutines. + old_CFLAGS="$CFLAGS" + # Temporary set `-pthread` just for the next check + CFLAGS="$CFLAGS -pthread" + AC_CHECK_FUNCS([pthread_attr_get_np pthread_getattr_np]) + CFLAGS="$old_CFLAGS" +fi + +AS_IF([test "$ENABLE_UNIT_TESTS" == "yes"],[ + +# Look for gtest. +PKG_CHECK_MODULES([GTEST], [gtest_main gmock_main]) + +# Look for rapidcheck. +PKG_CHECK_MODULES([RAPIDCHECK], [rapidcheck rapidcheck_gtest]) + +]) + +# Look for nlohmann/json. +PKG_CHECK_MODULES([NLOHMANN_JSON], [nlohmann_json >= 3.9]) + + +# Look for lowdown library. +AC_ARG_ENABLE([markdown], AS_HELP_STRING([--enable-markdown], [Enable Markdown rendering in the Nix binary (requires lowdown) [default=auto]]), + enable_markdown=$enableval, enable_markdown=auto) +AS_CASE(["$enable_markdown"], + [yes | auto], [ + PKG_CHECK_MODULES([LOWDOWN], [lowdown >= 0.9.0], [ + CXXFLAGS="$LOWDOWN_CFLAGS $CXXFLAGS" + have_lowdown=1 + AC_DEFINE(HAVE_LOWDOWN, 1, [Whether lowdown is available and should be used for Markdown rendering.]) + ], [ + AS_IF([test "x$enable_markdown" == "xyes"], [AC_MSG_ERROR([--enable-markdown was specified, but lowdown was not found.])]) + ]) + ], + [no], [have_lowdown=], + [AC_MSG_ERROR([bad value "$enable_markdown" for --enable-markdown, must be one of: yes, no, auto])]) + + +# Look for libgit2. +PKG_CHECK_MODULES([LIBGIT2], [libgit2]) + + +# Look for toml11, a required dependency. +AC_LANG_PUSH(C++) +AC_CHECK_HEADER([toml.hpp], [], [AC_MSG_ERROR([toml11 is not found.])]) +AC_LANG_POP(C++) + +# Setuid installations. +AC_CHECK_FUNCS([setresuid setreuid lchown]) + + +# Nice to have, but not essential. +AC_CHECK_FUNCS([strsignal posix_fallocate sysconf]) + + +AC_ARG_WITH(sandbox-shell, AS_HELP_STRING([--with-sandbox-shell=PATH],[path of a statically-linked shell to use as /bin/sh in sandboxes]), + sandbox_shell=$withval) +AC_SUBST(sandbox_shell) +if test ${cross_compiling:-no} = no && ! test -z ${sandbox_shell+x}; then + AC_MSG_CHECKING([whether sandbox-shell has the standalone feature]) + # busybox shell sometimes allows executing other busybox applets, + # even if they are not in the path, breaking our sandbox + if PATH= $sandbox_shell -c "busybox" 2>&1 | grep -qv "not found"; then + AC_MSG_RESULT(enabled) + AC_MSG_ERROR([Please disable busybox FEATURE_SH_STANDALONE]) + else + AC_MSG_RESULT(disabled) + fi +fi + +AC_ARG_ENABLE(embedded-sandbox-shell, AS_HELP_STRING([--enable-embedded-sandbox-shell],[include the sandbox shell in the Nix binary [default=no]]), + embedded_sandbox_shell=$enableval, embedded_sandbox_shell=no) +AC_SUBST(embedded_sandbox_shell) +if test "$embedded_sandbox_shell" = yes; then + AC_DEFINE(HAVE_EMBEDDED_SANDBOX_SHELL, 1, [Include the sandbox shell in the Nix binary.]) +fi + +]) + + +# Expand all variables in config.status. +test "$prefix" = NONE && prefix=$ac_default_prefix +test "$exec_prefix" = NONE && exec_prefix='${prefix}' +for name in $ac_subst_vars; do + declare $name="$(eval echo "${!name}")" + declare $name="$(eval echo "${!name}")" + declare $name="$(eval echo "${!name}")" +done + +rm -f Makefile.config + +AC_CONFIG_HEADERS([config.h]) +AC_CONFIG_FILES([]) +AC_OUTPUT diff --git a/doc/manual/local.mk b/doc/manual/local.mk new file mode 100644 index 000000000..36cccc506 --- /dev/null +++ b/doc/manual/local.mk @@ -0,0 +1,236 @@ +# The version of Nix used to generate the doc. Can also be +# `$(nix_INSTALL_PATH)` or just `nix` (to grap ambient from the `PATH`), +# if one prefers. +doc_nix = $(nix_PATH) + +MANUAL_SRCS := \ + $(call rwildcard, $(d)/source, *.md) \ + $(call rwildcard, $(d)/source, */*.md) + +man-pages := $(foreach n, \ + 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-daemon.8 \ + nix-profiles.5 \ +, $(d)/$(n)) + +# man pages for subcommands +# convert from `$(d)/source/command-ref/nix-{1}/{2}.md` to `$(d)/nix-{1}-{2}.1` +# FIXME: unify with how nix3-cli man pages are generated +man-pages += $(foreach subcommand, \ + $(filter-out %opt-common.md %env-common.md, $(wildcard $(d)/source/command-ref/nix-*/*.md)), \ + $(d)/$(subst /,-,$(subst $(d)/source/command-ref/,,$(subst .md,.1,$(subcommand))))) + +clean-files += $(d)/*.1 $(d)/*.5 $(d)/*.8 + +# Provide a dummy environment for nix, so that it will not access files outside the macOS sandbox. +# Set cores to 0 because otherwise `nix config show` resolves the cores based on the current machine +dummy-env = env -i \ + HOME=/dummy \ + NIX_CONF_DIR=/dummy \ + NIX_SSL_CERT_FILE=/dummy/no-ca-bundle.crt \ + NIX_STATE_DIR=/dummy \ + NIX_CONFIG='cores = 0' + +nix-eval = $(dummy-env) $(doc_nix) eval --experimental-features nix-command -I nix=doc/manual --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)/source/command-ref/nix-env/%.md + @printf "Title: %s\n\n" "$(subst nix-env-,nix-env --,$$(basename "$@" .1))" > $^.tmp + $(render-subcommand) + +$(d)/nix-store-%.1: $(d)/source/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 + + +$(d)/%.1: $(d)/source/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 + +$(d)/%.8: $(d)/source/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 + +$(d)/nix.conf.5: $(d)/source/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 + +$(d)/nix-profiles.5: $(d)/source/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 + +$(d)/source/SUMMARY.md: $(d)/source/SUMMARY.md.in $(d)/source/SUMMARY-rl-next.md $(d)/source/store/types $(d)/source/command-ref/new-cli $(d)/source/development/experimental-feature-descriptions.md + @cp $< $@ + @$(call process-includes,$@,$@) + +$(d)/source/store/types: $(d)/nix.json $(d)/utils.nix $(d)/generate-store-info.nix $(d)/generate-store-types.nix $(d)/source/store/types/index.md.in $(doc_nix) + @# FIXME: build out of tree! + @rm -rf $@.tmp + $(trace-gen) $(nix-eval) --write-to $@.tmp --expr 'import doc/manual/generate-store-types.nix (builtins.fromJSON (builtins.readFile $<)).stores' + @# do not destroy existing contents + @mv $@.tmp/* $@/ + +$(d)/source/command-ref/new-cli: $(d)/nix.json $(d)/utils.nix $(d)/generate-manpage.nix $(d)/generate-settings.nix $(d)/generate-store-info.nix $(doc_nix) + @rm -rf $@ $@.tmp + $(trace-gen) $(nix-eval) --write-to $@.tmp --expr 'import doc/manual/generate-manpage.nix true (builtins.readFile $<)' + @mv $@.tmp $@ + +$(d)/source/command-ref/conf-file.md: $(d)/conf-file.json $(d)/utils.nix $(d)/generate-settings.nix $(d)/source/command-ref/conf-file-prefix.md $(d)/source/command-ref/experimental-features-shortlist.md $(doc_nix) + @cat doc/manual/source/command-ref/conf-file-prefix.md > $@.tmp + $(trace-gen) $(nix-eval) --expr 'import doc/manual/generate-settings.nix { prefix = "conf"; } (builtins.fromJSON (builtins.readFile $<))' >> $@.tmp; + @mv $@.tmp $@ + +$(d)/nix.json: $(doc_nix) + $(trace-gen) $(dummy-env) $(doc_nix) __dump-cli > $@.tmp + @mv $@.tmp $@ + +$(d)/conf-file.json: $(doc_nix) + $(trace-gen) $(dummy-env) $(doc_nix) config show --json --experimental-features nix-command > $@.tmp + @mv $@.tmp $@ + +$(d)/source/development/experimental-feature-descriptions.md: $(d)/xp-features.json $(d)/utils.nix $(d)/generate-xp-features.nix $(doc_nix) + @rm -rf $@ $@.tmp + $(trace-gen) $(nix-eval) --write-to $@.tmp --expr 'import doc/manual/generate-xp-features.nix (builtins.fromJSON (builtins.readFile $<))' + @mv $@.tmp $@ + +$(d)/source/command-ref/experimental-features-shortlist.md: $(d)/xp-features.json $(d)/utils.nix $(d)/generate-xp-features-shortlist.nix $(doc_nix) + @rm -rf $@ $@.tmp + $(trace-gen) $(nix-eval) --write-to $@.tmp --expr 'import doc/manual/generate-xp-features-shortlist.nix (builtins.fromJSON (builtins.readFile $<))' + @mv $@.tmp $@ + +$(d)/xp-features.json: $(doc_nix) + $(trace-gen) $(dummy-env) $(doc_nix) __dump-xp-features > $@.tmp + @mv $@.tmp $@ + +$(d)/source/language/builtins.md: $(d)/language.json $(d)/generate-builtins.nix $(d)/source/language/builtins-prefix.md $(doc_nix) + @cat doc/manual/source/language/builtins-prefix.md > $@.tmp + $(trace-gen) $(nix-eval) --expr 'import doc/manual/generate-builtins.nix (builtins.fromJSON (builtins.readFile $<))' >> $@.tmp; + @cat doc/manual/source/language/builtins-suffix.md >> $@.tmp + @mv $@.tmp $@ + +$(d)/language.json: $(doc_nix) + $(trace-gen) $(dummy-env) $(doc_nix) __dump-language > $@.tmp + @mv $@.tmp $@ + +# Generate "Upcoming release" notes (or clear it and remove from menu) +$(d)/source/release-notes/rl-next.md: $(d)/rl-next $(d)/rl-next/* + @if type -p changelog-d > /dev/null; then \ + echo " GEN " $@; \ + changelog-d doc/manual/rl-next > $@; \ + else \ + echo " NULL " $@; \ + true > $@; \ + fi + +$(d)/source/SUMMARY-rl-next.md: $(d)/source/release-notes/rl-next.md + $(trace-gen) true + @if [ -s $< ]; then \ + echo ' - [Upcoming release](release-notes/rl-next.md)' > $@; \ + else \ + true > $@; \ + fi + +# Generate the HTML manual. +.PHONY: manual-html +manual-html: $(docdir)/manual/index.html + +# Open the built HTML manual in the default browser. +manual-html-open: $(docdir)/manual/index.html + @echo " OPEN " $<; \ + xdg-open $< \ + || open $< \ + || { \ + echo "Could not open the manual in a browser. Please open '$<'" >&2; \ + false; \ + } +install: $(docdir)/manual/index.html + +# Generate 'nix' manpages. +.PHONY: manpages +manpages: $(mandir)/man1/nix3-manpages +install: $(mandir)/man1/nix3-manpages +man: doc/manual/generated/man1/nix3-manpages +all: doc/manual/generated/man1/nix3-manpages + +# FIXME: unify with how the other man pages are generated. +# this one works differently and does not use any of the amenities provided by `/mk/lib.mk`. +$(mandir)/man1/nix3-manpages: doc/manual/generated/man1/nix3-manpages + @mkdir -p $(DESTDIR)$$(dirname $@) + $(trace-install) install -m 0644 $$(dirname $<)/* $(DESTDIR)$$(dirname $@) + +doc/manual/generated/man1/nix3-manpages: $(d)/source/command-ref/new-cli + @mkdir -p $(DESTDIR)$$(dirname $@) + $(trace-gen) for i in doc/manual/source/command-ref/new-cli/*.md; do \ + name=$$(basename $$i .md); \ + tmpFile=$$(mktemp); \ + if [[ $$name = SUMMARY ]]; then continue; fi; \ + printf "Title: %s\n\n" "$$name" > $$tmpFile; \ + cat $$i >> $$tmpFile; \ + lowdown -sT man --nroff-nolinks -M section=1 $$tmpFile -o $(DESTDIR)$$(dirname $@)/$$name.1; \ + rm $$tmpFile; \ + done + @touch $@ + +# the `! -name 'documentation.md'` filter excludes the one place where +# `@docroot@` is to be preserved for documenting the mechanism +# FIXME: maybe contributing guides should live right next to the code +# instead of in the manual +$(docdir)/manual/index.html: $(MANUAL_SRCS) $(d)/book.toml $(d)/anchors.jq $(d)/custom.css $(d)/source/SUMMARY.md $(d)/source/store/types $(d)/source/command-ref/new-cli $(d)/source/development/experimental-feature-descriptions.md $(d)/source/command-ref/conf-file.md $(d)/source/language/builtins.md $(d)/source/release-notes/rl-next.md $(d)/source/figures $(d)/source/favicon.png $(d)/source/favicon.svg + $(trace-gen) \ + tmp="$$(mktemp -d)"; \ + cp -r doc/manual "$$tmp"; \ + find "$$tmp" -name '*.md' | while read -r file; do \ + $(call process-includes,$$file,$$file); \ + done; \ + find "$$tmp" -name '*.md' ! -name 'documentation.md' | while read -r file; do \ + docroot="$$(realpath --relative-to="$$(dirname "$$file")" $$tmp/manual/source)"; \ + sed -i "s,@docroot@,$$docroot,g" "$$file"; \ + done; \ + set -euo pipefail; \ + ( \ + cd "$$tmp/manual"; \ + RUST_LOG=warn \ + MDBOOK_SUBSTITUTE_SEARCH=$(d)/source \ + mdbook build -d $(DESTDIR)$(docdir)/manual.tmp 2>&1 \ + | { grep -Fv "because fragment resolution isn't implemented" || :; } \ + ); \ + rm -rf "$$tmp/manual" + @rm -rf $(DESTDIR)$(docdir)/manual + @mv $(DESTDIR)$(docdir)/manual.tmp/html $(DESTDIR)$(docdir)/manual + @rm -rf $(DESTDIR)$(docdir)/manual.tmp diff --git a/flake.nix b/flake.nix index 4d339f6e7..3ef027dd1 100644 --- a/flake.nix +++ b/flake.nix @@ -137,7 +137,7 @@ pkgs = final; }); - nix = final.nixComponents.nix-cli; + nix = final.nixComponents.nix; # See https://github.com/NixOS/nixpkgs/pull/214409 # Remove when fixed in this flake's nixpkgs @@ -189,6 +189,7 @@ # system, we should reenable this. #perlBindings = self.hydraJobs.perlBindings.${system}; } + /* # Add "passthru" tests // flatMapAttrs ({ "" = nixpkgsFor.${system}.native; @@ -210,6 +211,7 @@ "${nixpkgsPrefix}nix-functional-tests" = nixpkgs.nixComponents.nix-functional-tests; } ) + */ // devFlake.checks.${system} or {} ); @@ -218,8 +220,7 @@ # for which we don't apply the full build matrix such as cross or static. inherit (nixpkgsFor.${system}.native) changelog-d; - # TODO probably should be `nix-cli` - default = self.packages.${system}.nix-everything; + default = self.packages.${system}.nix-ng; nix-manual = nixpkgsFor.${system}.native.nixComponents.nix-manual; nix-internal-api-docs = nixpkgsFor.${system}.native.nixComponents.nix-internal-api-docs; nix-external-api-docs = nixpkgsFor.${system}.native.nixComponents.nix-external-api-docs; @@ -227,6 +228,7 @@ # We need to flatten recursive attribute sets of derivations to pass `flake check`. // flatMapAttrs { # Components we'll iterate over in the upcoming lambda + "nix" = { }; "nix-util" = { }; "nix-util-c" = { }; "nix-util-test-support" = { }; @@ -255,11 +257,10 @@ "nix-cli" = { }; - "nix-everything" = { }; - "nix-functional-tests" = { supportsCross = false; }; "nix-perl-bindings" = { supportsCross = false; }; + "nix-ng" = { }; } (pkgName: { supportsCross ? true }: { # These attributes go right into `packages.`. diff --git a/local.mk b/local.mk new file mode 100644 index 000000000..b27c7031e --- /dev/null +++ b/local.mk @@ -0,0 +1,15 @@ +GLOBAL_CXXFLAGS += -Wno-deprecated-declarations -Werror=switch +# Allow switch-enum to be overridden for files that do not support it, usually because of dependency headers. +ERROR_SWITCH_ENUM = -Werror=switch-enum + +$(foreach i, config.h $(wildcard src/lib*/*.hh) $(filter-out %_internal.h, $(wildcard src/lib*c/*.h)), \ + $(eval $(call install-file-in, $(i), $(includedir)/nix, 0644))) + +ifdef HOST_UNIX + $(foreach i, $(wildcard src/lib*/unix/*.hh), \ + $(eval $(call install-file-in, $(i), $(includedir)/nix, 0644))) +endif + +$(GCH): src/libutil/util.hh config.h + +GCH_CXXFLAGS = $(INCLUDE_libutil) diff --git a/m4/ax_cxx_compile_stdcxx.m4 b/m4/ax_cxx_compile_stdcxx.m4 new file mode 100644 index 000000000..43087b2e6 --- /dev/null +++ b/m4/ax_cxx_compile_stdcxx.m4 @@ -0,0 +1,951 @@ +# =========================================================================== +# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html +# =========================================================================== +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the specified +# version of the C++ standard. If necessary, add switches to CXX and +# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard) +# or '14' (for the C++14 standard). +# +# The second argument, if specified, indicates whether you insist on an +# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. +# -std=c++11). If neither is specified, you get whatever works, with +# preference for an extended mode. +# +# The third argument, if specified 'mandatory' or if left unspecified, +# indicates that baseline support for the specified C++ standard is +# required and that the macro should error out if no mode with that +# support is found. If specified 'optional', then configuration proceeds +# regardless, after defining HAVE_CXX${VERSION} if and only if a +# supporting mode is found. +# +# LICENSE +# +# Copyright (c) 2008 Benjamin Kosnik +# Copyright (c) 2012 Zack Weinberg +# Copyright (c) 2013 Roy Stogner +# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov +# Copyright (c) 2015 Paul Norman +# Copyright (c) 2015 Moritz Klammler +# Copyright (c) 2016, 2018 Krzesimir Nowak +# Copyright (c) 2019 Enji Cooper +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 11 + +dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro +dnl (serial version number 13). + +AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl + m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"], + [$1], [14], [ax_cxx_compile_alternatives="14 1y"], + [$1], [17], [ax_cxx_compile_alternatives="17 1z"], + [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$2], [], [], + [$2], [ext], [], + [$2], [noext], [], + [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl + m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true], + [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true], + [$3], [optional], [ax_cxx_compile_cxx$1_required=false], + [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])]) + AC_LANG_PUSH([C++])dnl + ac_success=no + + m4_if([$2], [noext], [], [dnl + if test x$ac_success = xno; then + for alternative in ${ax_cxx_compile_alternatives}; do + switch="-std=gnu++${alternative}" + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + fi]) + + m4_if([$2], [ext], [], [dnl + if test x$ac_success = xno; then + dnl HP's aCC needs +std=c++11 according to: + dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf + dnl Cray's crayCC needs "-h std=c++11" + for alternative in ${ax_cxx_compile_alternatives}; do + for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch, + $cachevar, + [ac_save_CXX="$CXX" + CXX="$CXX $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXX="$ac_save_CXX"]) + if eval test x\$$cachevar = xyes; then + CXX="$CXX $switch" + if test -n "$CXXCPP" ; then + CXXCPP="$CXXCPP $switch" + fi + ac_success=yes + break + fi + done + if test x$ac_success = xyes; then + break + fi + done + fi]) + AC_LANG_POP([C++]) + if test x$ax_cxx_compile_cxx$1_required = xtrue; then + if test x$ac_success = xno; then + AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.]) + fi + fi + if test x$ac_success = xno; then + HAVE_CXX$1=0 + AC_MSG_NOTICE([No compiler with C++$1 support was found]) + else + HAVE_CXX$1=1 + AC_DEFINE(HAVE_CXX$1,1, + [define if the compiler supports basic C++$1 syntax]) + fi + AC_SUBST(HAVE_CXX$1) +]) + + +dnl Test body for checking C++11 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 +) + + +dnl Test body for checking C++14 support + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 +) + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17], + _AX_CXX_COMPILE_STDCXX_testbody_new_in_11 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_14 + _AX_CXX_COMPILE_STDCXX_testbody_new_in_17 +) + +dnl Tests for new features in C++11 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[ + +// If the compiler admits that it is not ready for C++11, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201103L + +#error "This is not a C++11 compiler" + +#else + +namespace cxx11 +{ + + namespace test_static_assert + { + + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + } + + namespace test_final_override + { + + struct Base + { + virtual ~Base() {} + virtual void f() {} + }; + + struct Derived : public Base + { + virtual ~Derived() override {} + virtual void f() override {} + }; + + } + + namespace test_double_right_angle_brackets + { + + template < typename T > + struct check {}; + + typedef check single_type; + typedef check> double_type; + typedef check>> triple_type; + typedef check>>> quadruple_type; + + } + + namespace test_decltype + { + + int + f() + { + int a = 1; + decltype(a) b = 2; + return a + b; + } + + } + + namespace test_type_deduction + { + + template < typename T1, typename T2 > + struct is_same + { + static const bool value = false; + }; + + template < typename T > + struct is_same + { + static const bool value = true; + }; + + template < typename T1, typename T2 > + auto + add(T1 a1, T2 a2) -> decltype(a1 + a2) + { + return a1 + a2; + } + + int + test(const int c, volatile int v) + { + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == false, ""); + auto ac = c; + auto av = v; + auto sumi = ac + av + 'x'; + auto sumf = ac + av + 1.0; + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == true, ""); + static_assert(is_same::value == false, ""); + static_assert(is_same::value == true, ""); + return (sumf > 0.0) ? sumi : add(c, v); + } + + } + + namespace test_noexcept + { + + int f() { return 0; } + int g() noexcept { return 0; } + + static_assert(noexcept(f()) == false, ""); + static_assert(noexcept(g()) == true, ""); + + } + + namespace test_constexpr + { + + template < typename CharT > + unsigned long constexpr + strlen_c_r(const CharT *const s, const unsigned long acc) noexcept + { + return *s ? strlen_c_r(s + 1, acc + 1) : acc; + } + + template < typename CharT > + unsigned long constexpr + strlen_c(const CharT *const s) noexcept + { + return strlen_c_r(s, 0UL); + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("1") == 1UL, ""); + static_assert(strlen_c("example") == 7UL, ""); + static_assert(strlen_c("another\0example") == 7UL, ""); + + } + + namespace test_rvalue_references + { + + template < int N > + struct answer + { + static constexpr int value = N; + }; + + answer<1> f(int&) { return answer<1>(); } + answer<2> f(const int&) { return answer<2>(); } + answer<3> f(int&&) { return answer<3>(); } + + void + test() + { + int i = 0; + const int c = 0; + static_assert(decltype(f(i))::value == 1, ""); + static_assert(decltype(f(c))::value == 2, ""); + static_assert(decltype(f(0))::value == 3, ""); + } + + } + + namespace test_uniform_initialization + { + + struct test + { + static const int zero {}; + static const int one {1}; + }; + + static_assert(test::zero == 0, ""); + static_assert(test::one == 1, ""); + + } + + namespace test_lambdas + { + + void + test1() + { + auto lambda1 = [](){}; + auto lambda2 = lambda1; + lambda1(); + lambda2(); + } + + int + test2() + { + auto a = [](int i, int j){ return i + j; }(1, 2); + auto b = []() -> int { return '0'; }(); + auto c = [=](){ return a + b; }(); + auto d = [&](){ return c; }(); + auto e = [a, &b](int x) mutable { + const auto identity = [](int y){ return y; }; + for (auto i = 0; i < a; ++i) + a += b--; + return x + identity(a + b); + }(0); + return a + b + c + d + e; + } + + int + test3() + { + const auto nullary = [](){ return 0; }; + const auto unary = [](int x){ return x; }; + using nullary_t = decltype(nullary); + using unary_t = decltype(unary); + const auto higher1st = [](nullary_t f){ return f(); }; + const auto higher2nd = [unary](nullary_t f1){ + return [unary, f1](unary_t f2){ return f2(unary(f1())); }; + }; + return higher1st(nullary) + higher2nd(nullary)(unary); + } + + } + + namespace test_variadic_templates + { + + template + struct sum; + + template + struct sum + { + static constexpr auto value = N0 + sum::value; + }; + + template <> + struct sum<> + { + static constexpr auto value = 0; + }; + + static_assert(sum<>::value == 0, ""); + static_assert(sum<1>::value == 1, ""); + static_assert(sum<23>::value == 23, ""); + static_assert(sum<1, 2>::value == 3, ""); + static_assert(sum<5, 5, 11>::value == 21, ""); + static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, ""); + + } + + // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae + // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function + // because of this. + namespace test_template_alias_sfinae + { + + struct foo {}; + + template + using member = typename T::member_type; + + template + void func(...) {} + + template + void func(member*) {} + + void test(); + + void test() { func(0); } + + } + +} // namespace cxx11 + +#endif // __cplusplus >= 201103L + +]]) + + +dnl Tests for new features in C++14 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[ + +// If the compiler admits that it is not ready for C++14, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201402L + +#error "This is not a C++14 compiler" + +#else + +namespace cxx14 +{ + + namespace test_polymorphic_lambdas + { + + int + test() + { + const auto lambda = [](auto&&... args){ + const auto istiny = [](auto x){ + return (sizeof(x) == 1UL) ? 1 : 0; + }; + const int aretiny[] = { istiny(args)... }; + return aretiny[0]; + }; + return lambda(1, 1L, 1.0f, '1'); + } + + } + + namespace test_binary_literals + { + + constexpr auto ivii = 0b0000000000101010; + static_assert(ivii == 42, "wrong value"); + + } + + namespace test_generalized_constexpr + { + + template < typename CharT > + constexpr unsigned long + strlen_c(const CharT *const s) noexcept + { + auto length = 0UL; + for (auto p = s; *p; ++p) + ++length; + return length; + } + + static_assert(strlen_c("") == 0UL, ""); + static_assert(strlen_c("x") == 1UL, ""); + static_assert(strlen_c("test") == 4UL, ""); + static_assert(strlen_c("another\0test") == 7UL, ""); + + } + + namespace test_lambda_init_capture + { + + int + test() + { + auto x = 0; + const auto lambda1 = [a = x](int b){ return a + b; }; + const auto lambda2 = [a = lambda1(x)](){ return a; }; + return lambda2(); + } + + } + + namespace test_digit_separators + { + + constexpr auto ten_million = 100'000'000; + static_assert(ten_million == 100000000, ""); + + } + + namespace test_return_type_deduction + { + + auto f(int& x) { return x; } + decltype(auto) g(int& x) { return x; } + + template < typename T1, typename T2 > + struct is_same + { + static constexpr auto value = false; + }; + + template < typename T > + struct is_same + { + static constexpr auto value = true; + }; + + int + test() + { + auto x = 0; + static_assert(is_same::value, ""); + static_assert(is_same::value, ""); + return x; + } + + } + +} // namespace cxx14 + +#endif // __cplusplus >= 201402L + +]]) + + +dnl Tests for new features in C++17 + +m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[ + +// If the compiler admits that it is not ready for C++17, why torture it? +// Hopefully, this will speed up the test. + +#ifndef __cplusplus + +#error "This is not a C++ compiler" + +#elif __cplusplus < 201703L + +#error "This is not a C++17 compiler" + +#else + +#include +#include +#include + +namespace cxx17 +{ + + namespace test_constexpr_lambdas + { + + constexpr int foo = [](){return 42;}(); + + } + + namespace test::nested_namespace::definitions + { + + } + + namespace test_fold_expression + { + + template + int multiply(Args... args) + { + return (args * ... * 1); + } + + template + bool all(Args... args) + { + return (args && ...); + } + + } + + namespace test_extended_static_assert + { + + static_assert (true); + + } + + namespace test_auto_brace_init_list + { + + auto foo = {5}; + auto bar {5}; + + static_assert(std::is_same, decltype(foo)>::value); + static_assert(std::is_same::value); + } + + namespace test_typename_in_template_template_parameter + { + + template typename X> struct D; + + } + + namespace test_fallthrough_nodiscard_maybe_unused_attributes + { + + int f1() + { + return 42; + } + + [[nodiscard]] int f2() + { + [[maybe_unused]] auto unused = f1(); + + switch (f1()) + { + case 17: + f1(); + [[fallthrough]]; + case 42: + f1(); + } + return f1(); + } + + } + + namespace test_extended_aggregate_initialization + { + + struct base1 + { + int b1, b2 = 42; + }; + + struct base2 + { + base2() { + b3 = 42; + } + int b3; + }; + + struct derived : base1, base2 + { + int d; + }; + + derived d1 {{1, 2}, {}, 4}; // full initialization + derived d2 {{}, {}, 4}; // value-initialized bases + + } + + namespace test_general_range_based_for_loop + { + + struct iter + { + int i; + + int& operator* () + { + return i; + } + + const int& operator* () const + { + return i; + } + + iter& operator++() + { + ++i; + return *this; + } + }; + + struct sentinel + { + int i; + }; + + bool operator== (const iter& i, const sentinel& s) + { + return i.i == s.i; + } + + bool operator!= (const iter& i, const sentinel& s) + { + return !(i == s); + } + + struct range + { + iter begin() const + { + return {0}; + } + + sentinel end() const + { + return {5}; + } + }; + + void f() + { + range r {}; + + for (auto i : r) + { + [[maybe_unused]] auto v = i; + } + } + + } + + namespace test_lambda_capture_asterisk_this_by_value + { + + struct t + { + int i; + int foo() + { + return [*this]() + { + return i; + }(); + } + }; + + } + + namespace test_enum_class_construction + { + + enum class byte : unsigned char + {}; + + byte foo {42}; + + } + + namespace test_constexpr_if + { + + template + int f () + { + if constexpr(cond) + { + return 13; + } + else + { + return 42; + } + } + + } + + namespace test_selection_statement_with_initializer + { + + int f() + { + return 13; + } + + int f2() + { + if (auto i = f(); i > 0) + { + return 3; + } + + switch (auto i = f(); i + 4) + { + case 17: + return 2; + + default: + return 1; + } + } + + } + + namespace test_template_argument_deduction_for_class_templates + { + + template + struct pair + { + pair (T1 p1, T2 p2) + : m1 {p1}, + m2 {p2} + {} + + T1 m1; + T2 m2; + }; + + void f() + { + [[maybe_unused]] auto p = pair{13, 42u}; + } + + } + + namespace test_non_type_auto_template_parameters + { + + template + struct B + {}; + + B<5> b1; + B<'a'> b2; + + } + + namespace test_structured_bindings + { + + int arr[2] = { 1, 2 }; + std::pair pr = { 1, 2 }; + + auto f1() -> int(&)[2] + { + return arr; + } + + auto f2() -> std::pair& + { + return pr; + } + + struct S + { + int x1 : 2; + volatile double y1; + }; + + S f3() + { + return {}; + } + + auto [ x1, y1 ] = f1(); + auto& [ xr1, yr1 ] = f1(); + auto [ x2, y2 ] = f2(); + auto& [ xr2, yr2 ] = f2(); + const auto [ x3, y3 ] = f3(); + + } + + namespace test_exception_spec_type_system + { + + struct Good {}; + struct Bad {}; + + void g1() noexcept; + void g2(); + + template + Bad + f(T*, T*); + + template + Good + f(T1*, T2*); + + static_assert (std::is_same_v); + + } + + namespace test_inline_variables + { + + template void f(T) + {} + + template inline T g(T) + { + return T{}; + } + + template<> inline void f<>(int) + {} + + template<> int g<>(int) + { + return 5; + } + + } + +} // namespace cxx17 + +#endif // __cplusplus < 201703L + +]]) diff --git a/m4/ax_cxx_compile_stdcxx_17.m4 b/m4/ax_cxx_compile_stdcxx_17.m4 new file mode 100644 index 000000000..a68341717 --- /dev/null +++ b/m4/ax_cxx_compile_stdcxx_17.m4 @@ -0,0 +1,35 @@ +# ============================================================================= +# https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_17.html +# ============================================================================= +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX_17([ext|noext], [mandatory|optional]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the C++17 +# standard; if necessary, add switches to CXX and CXXCPP to enable +# support. +# +# This macro is a convenience alias for calling the AX_CXX_COMPILE_STDCXX +# macro with the version set to C++17. The two optional arguments are +# forwarded literally as the second and third argument respectively. +# Please see the documentation for the AX_CXX_COMPILE_STDCXX macro for +# more information. If you want to use this macro, you also need to +# download the ax_cxx_compile_stdcxx.m4 file. +# +# LICENSE +# +# Copyright (c) 2015 Moritz Klammler +# Copyright (c) 2016 Krzesimir Nowak +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 2 + +AX_REQUIRE_DEFINED([AX_CXX_COMPILE_STDCXX]) +AC_DEFUN([AX_CXX_COMPILE_STDCXX_17], [AX_CXX_COMPILE_STDCXX([17], [$1], [$2])]) diff --git a/maintainers/local.mk b/maintainers/local.mk new file mode 100644 index 000000000..e81517eda --- /dev/null +++ b/maintainers/local.mk @@ -0,0 +1,8 @@ + +.PHONY: format +print-top-help += echo ' format: Format source code' + +# This uses the cached .pre-commit-hooks.yaml file +fmt_script := $(d)/format.sh +format: + @$(fmt_script) diff --git a/misc/bash/local.mk b/misc/bash/local.mk new file mode 100644 index 000000000..66235af05 --- /dev/null +++ b/misc/bash/local.mk @@ -0,0 +1 @@ +$(eval $(call install-file-as, $(d)/completion.sh, $(datarootdir)/bash-completion/completions/nix, 0644)) diff --git a/misc/fish/local.mk b/misc/fish/local.mk new file mode 100644 index 000000000..ece899fc3 --- /dev/null +++ b/misc/fish/local.mk @@ -0,0 +1 @@ +$(eval $(call install-file-as, $(d)/completion.fish, $(datarootdir)/fish/vendor_completions.d/nix.fish, 0644)) diff --git a/misc/launchd/local.mk b/misc/launchd/local.mk new file mode 100644 index 000000000..a39188fe6 --- /dev/null +++ b/misc/launchd/local.mk @@ -0,0 +1,5 @@ +ifdef HOST_DARWIN + + $(eval $(call install-data-in, $(d)/org.nixos.nix-daemon.plist, $(prefix)/Library/LaunchDaemons)) + +endif diff --git a/misc/systemd/local.mk b/misc/systemd/local.mk new file mode 100644 index 000000000..76121a0f9 --- /dev/null +++ b/misc/systemd/local.mk @@ -0,0 +1,8 @@ +ifdef HOST_LINUX + + $(foreach n, nix-daemon.socket nix-daemon.service, $(eval $(call install-file-in, $(d)/$(n), $(prefix)/lib/systemd/system, 0644))) + $(foreach n, nix-daemon.conf, $(eval $(call install-file-in, $(d)/$(n), $(prefix)/lib/tmpfiles.d, 0644))) + + clean-files += $(d)/nix-daemon.socket $(d)/nix-daemon.service $(d)/nix-daemon.conf + +endif diff --git a/misc/upstart/local.mk b/misc/upstart/local.mk new file mode 100644 index 000000000..2fbfb29b9 --- /dev/null +++ b/misc/upstart/local.mk @@ -0,0 +1,7 @@ +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 diff --git a/misc/zsh/local.mk b/misc/zsh/local.mk new file mode 100644 index 000000000..0b4e294fb --- /dev/null +++ b/misc/zsh/local.mk @@ -0,0 +1,2 @@ +$(eval $(call install-file-as, $(d)/completion.zsh, $(datarootdir)/zsh/site-functions/_nix, 0644)) +$(eval $(call install-file-as, $(d)/run-help-nix, $(datarootdir)/zsh/site-functions/run-help-nix, 0644)) diff --git a/mk/build-dir.mk b/mk/build-dir.mk new file mode 100644 index 000000000..02f4cae60 --- /dev/null +++ b/mk/build-dir.mk @@ -0,0 +1,10 @@ +# Initialise support for build directories. +builddir ?= + +ifdef builddir + buildprefix = $(builddir)/ + buildprefixrel = $(builddir) +else + buildprefix = + buildprefixrel = . +endif diff --git a/mk/clean.mk b/mk/clean.mk new file mode 100644 index 000000000..ce9afb3b0 --- /dev/null +++ b/mk/clean.mk @@ -0,0 +1,11 @@ +clean-files := + +clean: + $(suppress) rm -fv -- $(clean-files) + +dryclean: + @for i in $(clean-files); do if [ -e $$i ]; then echo $$i; fi; done | sort + +print-top-help += \ + echo " clean: Delete generated files"; \ + echo " dryclean: Show what files would be deleted by 'make clean'"; diff --git a/mk/common-test.sh b/mk/common-test.sh new file mode 100644 index 000000000..dd899e869 --- /dev/null +++ b/mk/common-test.sh @@ -0,0 +1,31 @@ +# shellcheck shell=bash + +# Remove overall test dir (at most one of the two should match) and +# remove file extension. + +test_name=$(echo -n "${test?must be defined by caller (test runner)}" | sed \ + -e "s|^src/[^/]*-test/data/||" \ + -e "s|^tests/functional/||" \ + -e "s|\.sh$||" \ + ) + +# Layer violation, but I am not inclined to care too much, as this code +# is about to be deleted. +src_dir=$(realpath tests/functional) + +# shellcheck disable=SC2016 +TESTS_ENVIRONMENT=( + "TEST_NAME=$test_name" + 'NIX_REMOTE=' + 'PS4=+(${BASH_SOURCE[0]-$0}:$LINENO) ' + "_NIX_TEST_SOURCE_DIR=${src_dir}" + "_NIX_TEST_BUILD_DIR=${src_dir}" +) + +unset src_dir + +read -r -a bash <<< "${BASH:-/usr/bin/env bash}" + +run () { + cd "$(dirname "$1")" && env "${TESTS_ENVIRONMENT[@]}" "${bash[@]}" -x -e -u -o pipefail "$(basename "$1")" +} diff --git a/mk/compilation-database.mk b/mk/compilation-database.mk new file mode 100644 index 000000000..f69dc0de0 --- /dev/null +++ b/mk/compilation-database.mk @@ -0,0 +1,11 @@ +compile-commands-json-files := + +define write-compile-commands + _srcs := $$(sort $$(foreach src, $$($(1)_SOURCES), $$(src))) + + $(1)_COMPILE_COMMANDS_JSON := $$(addprefix $(buildprefix), $$(addsuffix .compile_commands.json, $$(basename $$(_srcs)))) + + compile-commands-json-files += $$($(1)_COMPILE_COMMANDS_JSON) + + clean-files += $$($(1)_COMPILE_COMMANDS_JSON) +endef diff --git a/mk/cxx-big-literal.mk b/mk/cxx-big-literal.mk new file mode 100644 index 000000000..d64a171c8 --- /dev/null +++ b/mk/cxx-big-literal.mk @@ -0,0 +1,5 @@ +%.gen.hh: % + @echo 'R"__NIX_STR(' >> $@.tmp + $(trace-gen) cat $< >> $@.tmp + @echo ')__NIX_STR"' >> $@.tmp + @mv $@.tmp $@ diff --git a/mk/debug-test.sh b/mk/debug-test.sh new file mode 100755 index 000000000..0dd4406c3 --- /dev/null +++ b/mk/debug-test.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash + +set -eu -o pipefail + +test=$1 + +dir="$(dirname "${BASH_SOURCE[0]}")" +source "$dir/common-test.sh" + +run "$test" diff --git a/mk/functions.mk b/mk/functions.mk new file mode 100644 index 000000000..c48775db8 --- /dev/null +++ b/mk/functions.mk @@ -0,0 +1,14 @@ +# Utility function for recursively finding files, e.g. +# ‘$(call rwildcard, path/to/dir, *.c *.h)’. +rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d)) + +# Given a file name, produce the corresponding dependency file +# (e.g. ‘foo/bar.o’ becomes ‘foo/.bar.o.dep’). +filename-to-dep = $(dir $1).$(notdir $1).dep + +# Return the full path to a program by looking it up in $PATH, or the +# empty string if not found. +find-program = $(shell for i in $$(IFS=: ; echo $$PATH); do p=$$i/$(strip $1); if [ -e $$p ]; then echo $$p; break; fi; done) + +# Ensure that the given string ends in a single slash. +add-trailing-slash = $(patsubst %/,%,$(1))/ diff --git a/mk/install-dirs.mk b/mk/install-dirs.mk new file mode 100644 index 000000000..732b0d6fc --- /dev/null +++ b/mk/install-dirs.mk @@ -0,0 +1,11 @@ +# Default installation paths. +prefix ?= /usr/local +libdir ?= $(prefix)/lib +bindir ?= $(prefix)/bin +libexecdir ?= $(prefix)/libexec +datadir ?= $(prefix)/share +localstatedir ?= $(prefix)/var +sysconfdir ?= $(prefix)/etc +mandir ?= $(prefix)/share/man + +DESTDIR ?= diff --git a/mk/install.mk b/mk/install.mk new file mode 100644 index 000000000..dad0fd853 --- /dev/null +++ b/mk/install.mk @@ -0,0 +1,62 @@ +# Add a rule for creating $(1) as a directory. This template may be +# called multiple times for the same directory. +define create-dir + _i := $$(call add-trailing-slash, $(DESTDIR)$$(strip $(1))) + ifndef $$(_i)_SEEN + $$(_i)_SEEN = 1 + $$(_i): + $$(trace-mkdir) install -d "$$@" + endif +endef + + +# Add a rule for installing file $(1) as file $(2) with mode $(3). +# The directory containing $(2) will be created automatically. +define install-file-as + + _i := $(DESTDIR)$$(strip $(2)) + + install: $$(_i) + + $$(_i): $(1) | $$(dir $$(_i)) + $$(trace-install) install -m $(3) $(1) "$$@" + + $$(eval $$(call create-dir, $$(dir $(2)))) + +endef + + +# Add a rule for installing file $(1) in directory $(2) with mode +# $(3). The directory will be created automatically. +define install-file-in + $$(eval $$(call install-file-as,$(1),$(2)/$$(notdir $(1)),$(3))) +endef + + +define install-program-in + $$(eval $$(call install-file-in,$(1),$(2),0755)) +endef + + +define install-data-in + $$(eval $$(call install-file-in,$(1),$(2),0644)) +endef + + +# Install a symlink from $(2) to $(1). Note that $(1) need not exist. +define install-symlink + + _i := $(DESTDIR)$$(strip $(2)) + + install: $$(_i) + + $$(_i): | $$(dir $$(_i)) + $$(trace-install) ln -sfn $(1) "$$@" + + $$(eval $$(call create-dir, $$(dir $(2)))) + +endef + + +print-top-help += \ + echo " install: Install into \$$(prefix) (currently set to '$(prefix)')"; diff --git a/mk/lib.mk b/mk/lib.mk new file mode 100644 index 000000000..1e7af6ad5 --- /dev/null +++ b/mk/lib.mk @@ -0,0 +1,159 @@ +default: all + + +# Get rid of default suffixes. FIXME: is this a good idea? +.SUFFIXES: + + +# Initialise some variables. +bin-scripts := +noinst-scripts := +man-pages := +install-tests := +install-tests-groups := + +include mk/platform.mk + +# Hack to define a literal space. +space := +space += + + +# Hack to define a literal newline. +define newline + + +endef + + +# Pass -fPIC if we're building dynamic libraries. +BUILD_SHARED_LIBS ?= 1 + +ifeq ($(BUILD_SHARED_LIBS), 1) + ifdef HOST_CYGWIN + GLOBAL_CFLAGS += -U__STRICT_ANSI__ -D_GNU_SOURCE + GLOBAL_CXXFLAGS += -U__STRICT_ANSI__ -D_GNU_SOURCE + else + GLOBAL_CFLAGS += -fPIC + GLOBAL_CXXFLAGS += -fPIC + endif + ifndef HOST_DARWIN + ifndef HOST_SOLARIS + ifndef HOST_FREEBSD + GLOBAL_LDFLAGS += -Wl,--no-copy-dt-needed-entries + endif + endif + endif + SET_RPATH_TO_LIBS ?= 1 +endif + +# Pass -g if we want debug info. +BUILD_DEBUG ?= 1 + +ifeq ($(BUILD_DEBUG), 1) + GLOBAL_CFLAGS += -g + GLOBAL_CXXFLAGS += -g +endif + + +include mk/build-dir.mk +include mk/install-dirs.mk +include mk/functions.mk +include mk/tracing.mk +include mk/clean.mk +include mk/install.mk +include mk/libraries.mk +include mk/programs.mk +include mk/patterns.mk +include mk/templates.mk +include mk/cxx-big-literal.mk +include mk/tests.mk +include mk/compilation-database.mk + + +# Include all sub-Makefiles. +define include-sub-makefile + d := $$(patsubst %/,%,$$(dir $(1))) + include $(1) +endef + +$(foreach mf, $(makefiles), $(eval $(call include-sub-makefile,$(mf)))) + + +# Instantiate stuff. +$(foreach lib, $(libraries), $(eval $(call build-library,$(lib)))) +$(foreach prog, $(programs), $(eval $(call build-program,$(prog)))) +$(foreach script, $(bin-scripts), $(eval $(call install-program-in,$(script),$(bindir)))) +$(foreach script, $(bin-scripts), $(eval programs-list += $(script))) +$(foreach script, $(noinst-scripts), $(eval programs-list += $(script))) +$(foreach template, $(template-files), $(eval $(call instantiate-template,$(template)))) +$(foreach test, $(install-tests), \ + $(eval $(call run-test,$(test))) \ + $(eval installcheck: $(test).test)) +$(foreach test-group, $(install-tests-groups), \ + $(eval $(call run-test-group,$(test-group))) \ + $(eval installcheck: $(test-group).test-group) \ + $(foreach test, $($(test-group)-tests), \ + $(eval $(call run-test,$(test))) \ + $(eval $(test-group).test-group: $(test).test))) + +# Compilation database. +$(foreach lib, $(libraries), $(eval $(call write-compile-commands,$(lib)))) +$(foreach prog, $(programs), $(eval $(call write-compile-commands,$(prog)))) + +compile_commands.json: $(compile-commands-json-files) + @jq --slurp '.' $^ >$@ + +# Include makefiles requiring built programs. +$(foreach mf, $(makefiles-late), $(eval $(call include-sub-makefile,$(mf)))) + + +$(foreach file, $(man-pages), $(eval $(call install-data-in, $(file), $(mandir)/man$(patsubst .%,%,$(suffix $(file)))))) + + +.PHONY: default all man help + +all: $(programs-list) $(libs-list) $(man-pages) + +man: $(man-pages) + + +help: + @echo "The following targets are available:" + @echo "" + @echo " default: Build default targets" +ifdef man-pages + @echo " man: Generate manual pages" +endif + @$(print-top-help) +ifdef programs-list + @echo "" + @echo "The following programs can be built:" + @echo "" + @for i in $(programs-list); do echo " $$i"; done +endif +ifdef libs-list + @echo "" + @echo "The following libraries can be built:" + @echo "" + @for i in $(libs-list); do echo " $$i"; done +endif +ifdef install-tests-groups + @echo "" + @echo "The following groups of functional tests can be run:" + @echo "" + @for i in $(install-tests-groups); do echo " $$i.test-group"; done + @echo "" + @echo "(installcheck includes tests in test groups too.)" +endif + @echo "" + @echo "The following variables control the build:" + @echo "" + @echo " BUILD_SHARED_LIBS ($(BUILD_SHARED_LIBS)): Whether to build shared libraries" + @echo " BUILD_DEBUG ($(BUILD_DEBUG)): Whether to include debug symbols" + @echo " CC ($(CC)): C compiler to be used" + @echo " CFLAGS: Flags for the C compiler" + @echo " CXX ($(CXX)): C++ compiler to be used" + @echo " CXXFLAGS: Flags for the C++ compiler" + @echo " CPPFLAGS: C preprocessor flags, used for both CC and CXX" + @$(print-var-help) diff --git a/mk/libraries.mk b/mk/libraries.mk new file mode 100644 index 000000000..a7848ba35 --- /dev/null +++ b/mk/libraries.mk @@ -0,0 +1,173 @@ +libs-list := + +ifdef HOST_DARWIN + SO_EXT = dylib +else + ifdef HOST_WINDOWS + SO_EXT = dll + else + SO_EXT = so + endif +endif + +ifdef HOST_UNIX + THREAD_LDFLAGS = -pthread +else + THREAD_LDFLAGS = +endif + +# Build a library with symbolic name $(1). The library is defined by +# various variables prefixed by ‘$(1)_’: +# +# - $(1)_NAME: the name of the library (e.g. ‘libfoo’); defaults to +# $(1). +# +# - $(1)_DIR: the directory where the (non-installed) library will be +# placed. +# +# - $(1)_SOURCES: the source files of the library. +# +# - $(1)_CFLAGS: additional C compiler flags. +# +# - $(1)_CXXFLAGS: additional C++ compiler flags. +# +# - $(1)_ORDER_AFTER: a set of targets on which the object files of +# this libraries will have an order-only dependency. +# +# - $(1)_LIBS: the symbolic names of other libraries on which this +# library depends. +# +# - $(1)_ALLOW_UNDEFINED: if set, the library is allowed to have +# undefined symbols. Has no effect for static libraries. +# +# - $(1)_LDFLAGS: additional linker flags. +# +# - $(1)_LDFLAGS_PROPAGATED: additional linker flags, also propagated +# to the linking of programs/libraries that use this library. +# +# - $(1)_FORCE_INSTALL: if defined, the library will be installed even +# if it's not needed (i.e. dynamically linked) by a program. +# +# - $(1)_INSTALL_DIR: the directory where the library will be +# installed. Defaults to $(libdir). +# +# - $(1)_EXCLUDE_FROM_LIBRARY_LIST: if defined, the library will not +# be automatically marked as a dependency of the top-level all +# target andwill not be listed in the make help output. This is +# useful for libraries built solely for testing, for example. +# +# - BUILD_SHARED_LIBS: if equal to ‘1’, a dynamic library will be +# built, otherwise a static library. +define build-library + $(1)_NAME ?= $(1) + _d := $(buildprefix)$$(strip $$($(1)_DIR)) + _srcs := $$(sort $$(foreach src, $$($(1)_SOURCES), $$(src))) + $(1)_OBJS := $$(addprefix $(buildprefix), $$(addsuffix .o, $$(basename $$(_srcs)))) + _libs := $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_PATH)) + + ifdef HOST_WINDOWS + $(1)_INSTALL_DIR ?= $$(bindir) + else + $(1)_INSTALL_DIR ?= $$(libdir) + endif + + $(1)_LDFLAGS_USE := + $(1)_LDFLAGS_USE_INSTALLED := + $(1)_LIB_CLOSURE := $(1) + + $$(eval $$(call create-dir, $$(_d))) + + ifeq ($(BUILD_SHARED_LIBS), 1) + + ifdef $(1)_ALLOW_UNDEFINED + ifdef HOST_DARWIN + $(1)_LDFLAGS += -undefined suppress -flat_namespace + endif + else + ifndef HOST_DARWIN + ifndef HOST_WINDOWS + ifndef HOST_OPENBSD + $(1)_LDFLAGS += -Wl,-z,defs + endif + endif + endif + endif + + ifndef HOST_DARWIN + $(1)_LDFLAGS += -Wl,-soname=$$($(1)_NAME).$(SO_EXT) + endif + + $(1)_PATH := $$(_d)/$$($(1)_NAME).$(SO_EXT) + + $$($(1)_PATH): $$($(1)_OBJS) $$(_libs) | $$(_d)/ + +$$(trace-ld) $(CXX) -o $$(abspath $$@) -shared $$(LDFLAGS) $$(GLOBAL_LDFLAGS) $$($(1)_OBJS) $$($(1)_LDFLAGS) $$($(1)_LDFLAGS_PROPAGATED) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE)) $$($(1)_LDFLAGS_UNINSTALLED) + + ifndef HOST_DARWIN + $(1)_LDFLAGS_USE += -Wl,-rpath,$$(abspath $$(_d)) + endif + $(1)_LDFLAGS_USE += -L$$(_d) -l$$(patsubst lib%,%,$$(strip $$($(1)_NAME))) + + $(1)_INSTALL_PATH := $(DESTDIR)$$($(1)_INSTALL_DIR)/$$($(1)_NAME).$(SO_EXT) + + _libs_final := $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_INSTALL_PATH)) + + $$(eval $$(call create-dir, $$($(1)_INSTALL_DIR))) + + $$($(1)_INSTALL_PATH): $$($(1)_OBJS) $$(_libs_final) | $(DESTDIR)$$($(1)_INSTALL_DIR)/ + +$$(trace-ld) $(CXX) -o $$@ -shared $$(LDFLAGS) $$(GLOBAL_LDFLAGS) $$($(1)_OBJS) $$($(1)_LDFLAGS) $$($(1)_LDFLAGS_PROPAGATED) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE_INSTALLED)) + + $(1)_LDFLAGS_USE_INSTALLED += -L$$(DESTDIR)$$($(1)_INSTALL_DIR) -l$$(patsubst lib%,%,$$(strip $$($(1)_NAME))) + ifndef HOST_DARWIN + ifeq ($(SET_RPATH_TO_LIBS), 1) + $(1)_LDFLAGS_USE_INSTALLED += -Wl,-rpath,$$($(1)_INSTALL_DIR) + else + $(1)_LDFLAGS_USE_INSTALLED += -Wl,-rpath-link,$$($(1)_INSTALL_DIR) + endif + endif + + ifdef $(1)_FORCE_INSTALL + install: $$($(1)_INSTALL_PATH) + endif + + else + + $(1)_PATH := $$(_d)/$$($(1)_NAME).a + + $$($(1)_PATH): $$($(1)_OBJS) | $$(_d)/ + $$(trace-ld) $(LD) $$(ifndef $(HOST_DARWIN),-U) -r -o $$(_d)/$$($(1)_NAME).o $$^ + $$(trace-ar) $(AR) crs $$@ $$(_d)/$$($(1)_NAME).o + + $(1)_LDFLAGS_USE += $$($(1)_PATH) $$($(1)_LDFLAGS) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE)) + + $(1)_INSTALL_PATH := $$(libdir)/$$($(1)_NAME).a + + $(1)_LIB_CLOSURE += $$($(1)_LIBS) + + endif + + $(1)_LDFLAGS_USE += $$($(1)_LDFLAGS_PROPAGATED) + $(1)_LDFLAGS_USE_INSTALLED += $$($(1)_LDFLAGS_PROPAGATED) + + # Propagate CFLAGS and CXXFLAGS to the individual object files. + $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj)_CFLAGS=$$($(1)_CFLAGS))) + $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj)_CXXFLAGS=$$($(1)_CXXFLAGS))) + + # Make each object file depend on the common dependencies. + $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj): $$($(1)_COMMON_DEPS) $$(GLOBAL_COMMON_DEPS))) + + # Make each object file have order-only dependencies on the common + # order-only dependencies. This includes the order-only dependencies + # of libraries we're depending on. + $(1)_ORDER_AFTER_CLOSED = $$($(1)_ORDER_AFTER) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_ORDER_AFTER_CLOSED)) + + $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj): | $$($(1)_ORDER_AFTER_CLOSED) $$(GLOBAL_ORDER_AFTER))) + + # Include .dep files, if they exist. + $(1)_DEPS := $$(foreach fn, $$($(1)_OBJS), $$(call filename-to-dep, $$(fn))) + -include $$($(1)_DEPS) + + ifndef $(1)_EXCLUDE_FROM_LIBRARY_LIST + libs-list += $$($(1)_PATH) + endif + clean-files += $$(_d)/*.a $$(_d)/*.$(SO_EXT) $$(_d)/*.o $$(_d)/.*.dep $$($(1)_DEPS) $$($(1)_OBJS) +endef diff --git a/mk/patterns.mk b/mk/patterns.mk new file mode 100644 index 000000000..4caa2039e --- /dev/null +++ b/mk/patterns.mk @@ -0,0 +1,41 @@ + +# These are the complete command lines we use to compile C and C++ files. +# - $< is the source file. +# - $1 is the object file to create. +CC_CMD=$(CC) -o $1 -c $< $(CPPFLAGS) $(GLOBAL_CFLAGS) $(CFLAGS) $($1_CFLAGS) -MMD -MF $(call filename-to-dep,$1) -MP +CXX_CMD=$(CXX) -o $1 -c $< $(CPPFLAGS) $(GLOBAL_CXXFLAGS_PCH) $(GLOBAL_CXXFLAGS) $(CXXFLAGS) $($1_CXXFLAGS) $(ERROR_SWITCH_ENUM) -MMD -MF $(call filename-to-dep,$1) -MP + +# We use COMPILE_COMMANDS_JSON_CMD to turn a compilation command (like CC_CMD +# or CXX_CMD above) into a comple_commands.json file. We rely on bash native +# word splitting to define the positional arguments. +# - $< is the source file being compiled. +COMPILE_COMMANDS_JSON_CMD=jq --null-input '{ directory: $$ENV.PWD, file: "$<", arguments: $$ARGS.positional }' --args -- + + +$(buildprefix)%.o: %.cc + @mkdir -p "$(dir $@)" + $(trace-cxx) $(call CXX_CMD,$@) + +$(buildprefix)%.o: %.cpp + @mkdir -p "$(dir $@)" + $(trace-cxx) $(call CXX_CMD,$@) + +$(buildprefix)%.o: %.c + @mkdir -p "$(dir $@)" + $(trace-cc) $(call CC_CMD,$@) + +# In the following we need to replace the .compile_commands.json extension in $@ with .o +# to make the object file. This is needed because CC_CMD and CXX_CMD do further expansions +# based on the object file name (i.e. *_CXXFLAGS and filename-to-dep). + +$(buildprefix)%.compile_commands.json: %.cc + @mkdir -p "$(dir $@)" + $(trace-jq) $(COMPILE_COMMANDS_JSON_CMD) $(call CXX_CMD,$(@:.compile_commands.json=.o)) > $@ + +$(buildprefix)%.compile_commands.json: %.cpp + @mkdir -p "$(dir $@)" + $(trace-jq) $(COMPILE_COMMANDS_JSON_CMD) $(call CXX_CMD,$(@:.compile_commands.json=.o)) > $@ + +$(buildprefix)%.compile_commands.json: %.c + @mkdir -p "$(dir $@)" + $(trace-jq) $(COMPILE_COMMANDS_JSON_CMD) $(call CC_CMD,$(@:.compile_commands.json=.o)) > $@ diff --git a/mk/platform.mk b/mk/platform.mk new file mode 100644 index 000000000..3c4fff780 --- /dev/null +++ b/mk/platform.mk @@ -0,0 +1,40 @@ +ifdef HOST_OS + HOST_KERNEL = $(firstword $(subst -, ,$(HOST_OS))) + ifeq ($(patsubst mingw%,,$(HOST_KERNEL)),) + HOST_MINGW = 1 + HOST_WINDOWS = 1 + endif + ifeq ($(HOST_KERNEL), cygwin) + HOST_CYGWIN = 1 + HOST_WINDOWS = 1 + HOST_UNIX = 1 + endif + ifeq ($(patsubst darwin%,,$(HOST_KERNEL)),) + HOST_DARWIN = 1 + HOST_UNIX = 1 + endif + ifeq ($(patsubst freebsd%,,$(HOST_KERNEL)),) + HOST_FREEBSD = 1 + HOST_UNIX = 1 + endif + ifeq ($(patsubst netbsd%,,$(HOST_KERNEL)),) + HOST_NETBSD = 1 + HOST_UNIX = 1 + endif + ifeq ($(patsubst openbsd%,,$(HOST_KERNEL)),) + HOST_OPENBSD = 1 + HOST_UNIX = 1 + endif + ifeq ($(HOST_KERNEL), linux) + HOST_LINUX = 1 + HOST_UNIX = 1 + endif + ifeq ($(patsubst solaris%,,$(HOST_KERNEL)),) + HOST_SOLARIS = 1 + HOST_UNIX = 1 + endif + ifeq ($(HOST_KERNEL), gnu) + HOST_HURD = 1 + HOST_UNIX = 1 + endif +endif diff --git a/mk/precompiled-headers.mk b/mk/precompiled-headers.mk new file mode 100644 index 000000000..f2803eb79 --- /dev/null +++ b/mk/precompiled-headers.mk @@ -0,0 +1,21 @@ +PRECOMPILE_HEADERS ?= 0 + +print-var-help += \ + echo " PRECOMPILE_HEADERS ($(PRECOMPILE_HEADERS)): Whether to use precompiled headers to speed up the build"; + +GCH = $(buildprefix)precompiled-headers.h.gch + +$(GCH): precompiled-headers.h + @rm -f $@ + @mkdir -p "$(dir $@)" + $(trace-gen) $(CXX) -c -x c++-header -o $@ $< $(GLOBAL_CXXFLAGS) $(GCH_CXXFLAGS) + +clean-files += $(GCH) + +ifeq ($(PRECOMPILE_HEADERS), 1) + + GLOBAL_CXXFLAGS_PCH += -include $(buildprefix)precompiled-headers.h -Winvalid-pch + + GLOBAL_ORDER_AFTER += $(GCH) + +endif diff --git a/mk/programs.mk b/mk/programs.mk new file mode 100644 index 000000000..623caaf55 --- /dev/null +++ b/mk/programs.mk @@ -0,0 +1,98 @@ +programs-list := + +ifdef HOST_WINDOWS + EXE_EXT = .exe +else + EXE_EXT = +endif + +# Build a program with symbolic name $(1). The program is defined by +# various variables prefixed by ‘$(1)_’: +# +# - $(1)_NAME: the name of the program (e.g. ‘foo’); defaults to +# $(1). +# +# - $(1)_DIR: the directory where the (non-installed) program will be +# placed. +# +# - $(1)_SOURCES: the source files of the program. +# +# - $(1)_CFLAGS: additional C compiler flags. +# +# - $(1)_CXXFLAGS: additional C++ compiler flags. +# +# - $(1)_ORDER_AFTER: a set of targets on which the object files of +# this program will have an order-only dependency. +# +# - $(1)_LIBS: the symbolic names of libraries on which this program +# depends. +# +# - $(1)_LDFLAGS: additional linker flags. +# +# - $(1)_INSTALL_DIR: the directory where the program will be +# installed; defaults to $(bindir). +define build-program + $(1)_NAME ?= $(1) + _d := $(buildprefix)$$($(1)_DIR) + _srcs := $$(sort $$(foreach src, $$($(1)_SOURCES), $$(src))) + $(1)_OBJS := $$(addprefix $(buildprefix), $$(addsuffix .o, $$(basename $$(_srcs)))) + _libs := $$(foreach lib, $$($(1)_LIBS), $$(foreach lib2, $$($$(lib)_LIB_CLOSURE), $$($$(lib2)_PATH))) + $(1)_PATH := $$(_d)/$$($(1)_NAME)$(EXE_EXT) + + $$(eval $$(call create-dir, $$(_d))) + + $$($(1)_PATH): $$($(1)_OBJS) $$(_libs) | $$(_d)/ + +$$(trace-ld) $(CXX) -o $$@ $$(LDFLAGS) $$(GLOBAL_LDFLAGS) $$($(1)_OBJS) $$($(1)_LDFLAGS) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE)) + + $(1)_INSTALL_DIR ?= $$(bindir) + + ifdef $(1)_INSTALL_DIR + + $(1)_INSTALL_PATH := $$($(1)_INSTALL_DIR)/$$($(1)_NAME)$(EXE_EXT) + + $$(eval $$(call create-dir, $$($(1)_INSTALL_DIR))) + + install: $(DESTDIR)$$($(1)_INSTALL_PATH) + + ifeq ($(BUILD_SHARED_LIBS), 1) + + _libs_final := $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_INSTALL_PATH)) + + $(DESTDIR)$$($(1)_INSTALL_PATH): $$($(1)_OBJS) $$(_libs_final) | $(DESTDIR)$$($(1)_INSTALL_DIR)/ + +$$(trace-ld) $(CXX) -o $$@ $$(LDFLAGS) $$(GLOBAL_LDFLAGS) $$($(1)_OBJS) $$($(1)_LDFLAGS) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_LDFLAGS_USE_INSTALLED)) + + else + + $(DESTDIR)$$($(1)_INSTALL_PATH): $$($(1)_PATH) | $(DESTDIR)$$($(1)_INSTALL_DIR)/ + +$$(trace-install) install -t $(DESTDIR)$$($(1)_INSTALL_DIR) $$< + + endif + endif + + # Propagate CFLAGS and CXXFLAGS to the individual object files. + $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj)_CFLAGS=$$($(1)_CFLAGS))) + $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj)_CXXFLAGS=$$($(1)_CXXFLAGS))) + + # Make each object file depend on the common dependencies. + $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj): $$($(1)_COMMON_DEPS) $$(GLOBAL_COMMON_DEPS))) + + # Make each object file have order-only dependencies on the common + # order-only dependencies. This includes the order-only dependencies + # of libraries we're depending on. + $(1)_ORDER_AFTER_CLOSED = $$($(1)_ORDER_AFTER) $$(foreach lib, $$($(1)_LIBS), $$($$(lib)_ORDER_AFTER_CLOSED)) + + $$(foreach obj, $$($(1)_OBJS), $$(eval $$(obj): | $$($(1)_ORDER_AFTER_CLOSED) $$(GLOBAL_ORDER_AFTER))) + + # Include .dep files, if they exist. + $(1)_DEPS := $$(foreach fn, $$($(1)_OBJS), $$(call filename-to-dep, $$(fn))) + -include $$($(1)_DEPS) + + programs-list += $$($(1)_PATH) + clean-files += $$($(1)_PATH) $$(_d)/*.o $$(_d)/.*.dep $$($(1)_DEPS) $$($(1)_OBJS) + + # Phony target to run this program (typically as a dependency of 'check'). + .PHONY: $(1)_RUN + $(1)_RUN: $$($(1)_PATH) + $(trace-test) $$($(1)_ENV) $$($(1)_PATH) + +endef diff --git a/mk/run-test.sh b/mk/run-test.sh new file mode 100755 index 000000000..7f9f1d5f8 --- /dev/null +++ b/mk/run-test.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +set -eu -o pipefail + +red="" +green="" +yellow="" +normal="" + +test=$1 + +dir="$(dirname "${BASH_SOURCE[0]}")" +source "$dir/common-test.sh" + +post_run_msg="ran test $test..." +if [ -t 1 ]; then + red="" + green="" + yellow="" + normal="" +fi + +run_test () { + log="$(run "$test" 2>&1)" && status=0 || status=$? +} + +run_test + +if [[ "$status" = 0 ]]; then + echo "$post_run_msg [${green}PASS$normal]" +elif [[ "$status" = 77 ]]; then + echo "$post_run_msg [${yellow}SKIP$normal]" +else + echo "$post_run_msg [${red}FAIL$normal]" + # shellcheck disable=SC2001 + echo "$log" | sed 's/^/ /' + exit "$status" +fi diff --git a/mk/templates.mk b/mk/templates.mk new file mode 100644 index 000000000..d5dae61c7 --- /dev/null +++ b/mk/templates.mk @@ -0,0 +1,19 @@ +template-files := + +# Create the file $(1) from $(1).in by running config.status (which +# substitutes all ‘@var@’ variables set by the configure script). +define instantiate-template + + clean-files += $(1) + +endef + +ifneq ($(MAKECMDGOALS), clean) + +$(buildprefix)%.h: %.h.in $(buildprefix)config.status + $(trace-gen) rm -f $@ && cd $(buildprefixrel) && ./config.status --quiet --header=$(@:$(buildprefix)%=%) + +$(buildprefix)%: %.in $(buildprefix)config.status + $(trace-gen) rm -f $@ && cd $(buildprefixrel) && ./config.status --quiet --file=$(@:$(buildprefix)%=%) + +endif diff --git a/mk/tests.mk b/mk/tests.mk new file mode 100644 index 000000000..0a10f6d3b --- /dev/null +++ b/mk/tests.mk @@ -0,0 +1,30 @@ +# Run program $1 as part of ‘make installcheck’. + +test-deps = + +define run-bash + + .PHONY: $1 + $1: $2 + @env BASH=$(bash) $(bash) $3 < /dev/null + +endef + +define run-test + + $(eval $(call run-bash,$1.test,$1 $(test-deps),mk/run-test.sh $1)) + $(eval $(call run-bash,$1.test-debug,$1 $(test-deps),mk/debug-test.sh $1)) + +endef + +define run-test-group + + .PHONY: $1.test-group + +endef + +.PHONY: check installcheck + +print-top-help += \ + echo " check: Run unit tests"; \ + echo " installcheck: Run functional tests"; diff --git a/mk/tracing.mk b/mk/tracing.mk new file mode 100644 index 000000000..09db1e617 --- /dev/null +++ b/mk/tracing.mk @@ -0,0 +1,18 @@ +V ?= 0 + +ifeq ($(V), 0) + + trace-gen = @echo " GEN " $@; + trace-cc = @echo " CC " $@; + trace-cxx = @echo " CXX " $@; + trace-ld = @echo " LD " $@; + trace-ar = @echo " AR " $@; + trace-install = @echo " INST " $@; + trace-mkdir = @echo " MKDIR " $@; + trace-test = @echo " TEST " $@; + trace-sh = @echo " SH " $@; + trace-jq = @echo " JQ " $@; + + suppress = @ + +endif diff --git a/package.nix b/package.nix new file mode 100644 index 000000000..8cbe325e9 --- /dev/null +++ b/package.nix @@ -0,0 +1,366 @@ +{ lib +, stdenv +, releaseTools +, autoconf-archive +, autoreconfHook +, aws-sdk-cpp +, boehmgc +, nlohmann_json +, bison +, boost +, brotli +, bzip2 +, curl +, editline +, readline +, flex +, git +, gtest +, jq +, libarchive +, libcpuid +, libgit2 +, libseccomp +, libsodium +, man +, darwin +, lowdown +, mdbook +, mdbook-linkcheck +, mercurial +, openssh +, openssl +, pkg-config +, rapidcheck +, sqlite +, toml11 +, unixtools +, xz + +, busybox-sandbox-shell ? null + +# Configuration Options +#: +# This probably seems like too many degrees of freedom, but it +# faithfully reflects how the underlying configure + make build system +# work. The top-level flake.nix will choose useful combinations of these +# options to CI. + +, pname ? "nix" + +, version +, versionSuffix + +# Whether to build Nix. Useful to skip for tasks like testing existing pre-built versions of Nix +, doBuild ? true + +# Run the unit tests as part of the build. See `installUnitTests` for an +# alternative to this. +, doCheck ? __forDefaults.canRunInstalled + +# Run the functional tests as part of the build. +, doInstallCheck ? test-client != null || __forDefaults.canRunInstalled + +# Check test coverage of Nix. Probably want to use with at least +# one of `doCHeck` or `doInstallCheck` enabled. +, withCoverageChecks ? false + +# Whether to build the regular manual +, enableManual ? __forDefaults.canRunInstalled + +# Whether to use garbage collection for the Nix language evaluator. +# +# If it is disabled, we just leak memory, but this is not as bad as it +# sounds so long as evaluation just takes places within short-lived +# processes. (When the process exits, the memory is reclaimed; it is +# only leaked *within* the process.) +# +# Temporarily disabled on Windows because the `GC_throw_bad_alloc` +# symbol is missing during linking. +# +# Disabled on OpenBSD because of missing `_data_start` symbol while linking +, enableGC ? !stdenv.hostPlatform.isWindows && !stdenv.hostPlatform.isOpenBSD + +# Whether to enable Markdown rendering in the Nix binary. +, enableMarkdown ? !stdenv.hostPlatform.isWindows + +# Which interactive line editor library to use for Nix's repl. +# +# Currently supported choices are: +# +# - editline (default) +# - readline +, readlineFlavor ? if stdenv.hostPlatform.isWindows then "readline" else "editline" + +# Whether to install unit tests. This is useful when cross compiling +# since we cannot run them natively during the build, but can do so +# later. +, installUnitTests ? doBuild && !__forDefaults.canExecuteHost + +# For running the functional tests against a pre-built Nix. Probably +# want to use in conjunction with `doBuild = false;`. +, test-daemon ? null +, test-client ? null + +# Avoid setting things that would interfere with a functioning devShell +, forDevShell ? false + +# Not a real argument, just the only way to approximate let-binding some +# stuff for argument defaults. +, __forDefaults ? { + canExecuteHost = stdenv.buildPlatform.canExecute stdenv.hostPlatform; + canRunInstalled = doBuild && __forDefaults.canExecuteHost; + } +}: + +let + inherit (lib) fileset; + + # selected attributes with defaults, will be used to define some + # things which should instead be gotten via `finalAttrs` in order to + # work with overriding. + attrs = { + inherit doBuild doCheck doInstallCheck; + }; + + mkDerivation = + if withCoverageChecks + then + # TODO support `finalAttrs` args function in + # `releaseTools.coverageAnalysis`. + argsFun: + releaseTools.coverageAnalysis (let args = argsFun args; in args) + else stdenv.mkDerivation; +in + +mkDerivation (finalAttrs: let + + inherit (finalAttrs) + doCheck + doInstallCheck + ; + + doBuild = !finalAttrs.dontBuild; + + # Either running the unit tests during the build, or installing them + # to be run later, requiresthe unit tests to be built. + buildUnitTests = doCheck || installUnitTests; + +in { + inherit pname version; + + src = + let + baseFiles = fileset.fileFilter (f: f.name != ".gitignore") ./.; + in + fileset.toSource { + root = ./.; + fileset = fileset.intersection baseFiles (fileset.unions ([ + # For configure + ./.version + ./configure.ac + ./m4 + # TODO: do we really need README.md? It doesn't seem used in the build. + ./README.md + # This could be put behind a conditional + ./maintainers/local.mk + # For make, regardless of what we are building + ./local.mk + ./Makefile + ./Makefile.config.in + ./mk + (fileset.fileFilter (f: lib.strings.hasPrefix "nix-profile" f.name) ./scripts) + ] ++ lib.optionals doBuild [ + ./doc + ./misc + ./precompiled-headers.h + (fileset.difference ./src ./src/perl) + ./COPYING + ./scripts/local.mk + ] ++ lib.optionals enableManual [ + ./doc/manual + ] ++ lib.optionals doInstallCheck [ + ./tests/functional + ])); + }; + + VERSION_SUFFIX = versionSuffix; + + outputs = [ "out" ] + ++ lib.optional doBuild "dev" + # If we are doing just build or just docs, the one thing will use + # "out". We only need additional outputs if we are doing both. + ++ lib.optional (doBuild && enableManual) "doc" + ++ lib.optional installUnitTests "check" + ++ lib.optional doCheck "testresults" + ; + + nativeBuildInputs = [ + autoconf-archive + autoreconfHook + pkg-config + ] ++ lib.optionals doBuild [ + bison + flex + ] ++ lib.optionals enableManual [ + (lib.getBin lowdown) + mdbook + mdbook-linkcheck + ] ++ lib.optionals doInstallCheck [ + git + mercurial + openssh + ] ++ lib.optionals (doInstallCheck || enableManual) [ + jq # Also for custom mdBook preprocessor. + ] ++ lib.optionals enableManual [ + man + ] ++ lib.optional stdenv.hostPlatform.isStatic unixtools.hexdump + ; + + buildInputs = lib.optionals doBuild ( + [ + brotli + bzip2 + curl + libarchive + libgit2 + libsodium + openssl + sqlite + toml11 + xz + ({ inherit readline editline; }.${readlineFlavor}) + ] ++ lib.optionals enableMarkdown [ + lowdown + ] ++ lib.optionals buildUnitTests [ + gtest + rapidcheck + ] ++ lib.optional stdenv.isLinux libseccomp + ++ lib.optional stdenv.hostPlatform.isDarwin darwin.apple_sdk.libs.sandbox + ++ lib.optional stdenv.hostPlatform.isx86_64 libcpuid + # There have been issues building these dependencies + ++ lib.optional (stdenv.hostPlatform == stdenv.buildPlatform && (stdenv.isLinux || stdenv.isDarwin)) + aws-sdk-cpp + ); + + propagatedBuildInputs = lib.optionals doBuild ([ + boost + nlohmann_json + ] ++ lib.optional enableGC boehmgc + ); + + dontBuild = !attrs.doBuild; + doCheck = attrs.doCheck; + + configureFlags = [ + (lib.enableFeature doBuild "build") + (lib.enableFeature buildUnitTests "unit-tests") + (lib.enableFeature doInstallCheck "functional-tests") + (lib.enableFeature enableManual "doc-gen") + (lib.enableFeature enableGC "gc") + (lib.enableFeature enableMarkdown "markdown") + (lib.enableFeature installUnitTests "install-unit-tests") + (lib.withFeatureAs true "readline-flavor" readlineFlavor) + ] ++ lib.optionals (!forDevShell) [ + "--sysconfdir=/etc" + ] ++ lib.optionals installUnitTests [ + "--with-check-bin-dir=${builtins.placeholder "check"}/bin" + "--with-check-lib-dir=${builtins.placeholder "check"}/lib" + ] ++ lib.optionals (doBuild) [ + "--with-boost=${boost}/lib" + ] ++ lib.optionals (doBuild && stdenv.isLinux) [ + "--with-sandbox-shell=${busybox-sandbox-shell}/bin/busybox" + ] ++ lib.optional (doBuild && stdenv.isLinux && !(stdenv.hostPlatform.isStatic && stdenv.system == "aarch64-linux")) + "LDFLAGS=-fuse-ld=gold" + ++ lib.optional (doBuild && stdenv.hostPlatform.isStatic) "--enable-embedded-sandbox-shell" + ; + + enableParallelBuilding = true; + + makeFlags = "profiledir=$(out)/etc/profile.d PRECOMPILE_HEADERS=1"; + + preCheck = '' + mkdir $testresults + ''; + + installTargets = lib.optional doBuild "install"; + + installFlags = "sysconfdir=$(out)/etc"; + + # In this case we are probably just running tests, and so there isn't + # anything to install, we just make an empty directory to signify tests + # succeeded. + installPhase = if finalAttrs.installTargets != [] then null else '' + mkdir -p $out + ''; + + postInstall = lib.optionalString doBuild ( + 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 enableManual '' + mkdir -p ''${!outputDoc}/nix-support + echo "doc manual ''${!outputDoc}/share/doc/nix/manual" >> ''${!outputDoc}/nix-support/hydra-build-products + ''; + + # So the check output gets links for DLLs in the out output. + preFixup = lib.optionalString (stdenv.hostPlatform.isWindows && builtins.elem "check" finalAttrs.outputs) '' + ln -s "$check/lib/"*.dll "$check/bin" + ln -s "$out/bin/"*.dll "$check/bin" + ''; + + doInstallCheck = attrs.doInstallCheck; + + installCheckFlags = "sysconfdir=$(out)/etc"; + # Work around buggy detection in stdenv. + installCheckTarget = "installcheck"; + + # Work around weird bug where it doesn't think there is a Makefile. + installCheckPhase = if (!doBuild && doInstallCheck) then '' + runHook preInstallCheck + mkdir -p src/nix-channel + make installcheck -j$NIX_BUILD_CORES -l$NIX_BUILD_CORES + '' else null; + + # Needed for tests if we are not doing a build, but testing existing + # built Nix. + preInstallCheck = + lib.optionalString (! doBuild) '' + mkdir -p src/nix-channel + ''; + + separateDebugInfo = !stdenv.hostPlatform.isStatic; + + # TODO Always true after https://github.com/NixOS/nixpkgs/issues/318564 + strictDeps = !withCoverageChecks; + + hardeningDisable = lib.optional stdenv.hostPlatform.isStatic "pie"; + + meta = { + platforms = lib.platforms.unix ++ lib.platforms.windows; + mainProgram = "nix"; + broken = !(lib.all (a: a) [ + # We cannot run or install unit tests if we don't build them or + # Nix proper (which they depend on). + (installUnitTests -> doBuild) + (doCheck -> doBuild) + # The build process for the manual currently requires extracting + # data from the Nix executable we are trying to document. + (enableManual -> doBuild) + ]); + }; + +} // lib.optionalAttrs withCoverageChecks { + lcovFilter = [ "*/boost/*" "*-tab.*" ]; + + hardeningDisable = ["fortify"]; + + NIX_CFLAGS_COMPILE = "-DCOVERAGE=1"; + + dontInstall = false; +} // lib.optionalAttrs (test-daemon != null) { + NIX_DAEMON_PACKAGE = test-daemon; +} // lib.optionalAttrs (test-client != null) { + NIX_CLIENT_PACKAGE = test-client; +}) diff --git a/packaging/components.nix b/packaging/components.nix index c29e04ae9..5cc0be784 100644 --- a/packaging/components.nix +++ b/packaging/components.nix @@ -25,6 +25,11 @@ in version = baseVersion + versionSuffix; inherit versionSuffix; + nix = callPackage ../package.nix { + version = fineVersion; + versionSuffix = fineVersionSuffix; + }; + nix-util = callPackage ../src/libutil/package.nix { }; nix-util-c = callPackage ../src/libutil-c/package.nix { }; nix-util-test-support = callPackage ../src/libutil-test-support/package.nix { }; @@ -61,5 +66,6 @@ in nix-perl-bindings = callPackage ../src/perl/package.nix { }; - nix-everything = callPackage ../packaging/everything.nix { }; + # Will replace `nix` once the old build system is gone. + nix-ng = callPackage ../packaging/everything.nix { }; } diff --git a/packaging/dev-shell.nix b/packaging/dev-shell.nix index 8ac17f61a..4b2a87632 100644 --- a/packaging/dev-shell.nix +++ b/packaging/dev-shell.nix @@ -2,7 +2,7 @@ { pkgs }: -pkgs.nixComponents.nix-util.overrideAttrs (attrs: +(pkgs.nix.override { forDevShell = true; }).overrideAttrs (attrs: let stdenv = pkgs.nixDependencies.stdenv; @@ -88,12 +88,9 @@ in { buildInputs = attrs.buildInputs or [] ++ pkgs.nixComponents.nix-util.buildInputs ++ pkgs.nixComponents.nix-store.buildInputs - ++ pkgs.nixComponents.nix-store-tests.externalBuildInputs ++ pkgs.nixComponents.nix-fetchers.buildInputs ++ pkgs.nixComponents.nix-expr.buildInputs - ++ pkgs.nixComponents.nix-expr.externalPropagatedBuildInputs - ++ pkgs.nixComponents.nix-cmd.buildInputs - ++ lib.optionals havePerl pkgs.nixComponents.nix-perl-bindings.externalBuildInputs + ++ pkgs.nixComponents.nix-store-tests.externalBuildInputs ++ lib.optional havePerl pkgs.perl ; }) diff --git a/packaging/hydra.nix b/packaging/hydra.nix index 3e5d4bbb2..6da502079 100644 --- a/packaging/hydra.nix +++ b/packaging/hydra.nix @@ -32,7 +32,7 @@ let # convention to transpose it, and to transpose it efficiently, we need to # enumerate them manually, so that we don't evaluate unnecessary package sets. forAllPackages = lib.genAttrs [ - "nix-everything" + "nix" "nix-util" "nix-util-c" "nix-util-test-support" @@ -54,6 +54,7 @@ let "nix-cmd" "nix-cli" "nix-functional-tests" + "nix-ng" ]; in { @@ -138,11 +139,11 @@ in # docker image with Nix inside dockerImage = lib.genAttrs linux64BitSystems (system: self.packages.${system}.dockerImage); - # # Line coverage analysis. - # coverage = nixpkgsFor.x86_64-linux.native.nix.override { - # pname = "nix-coverage"; - # withCoverageChecks = true; - # }; + # Line coverage analysis. + coverage = nixpkgsFor.x86_64-linux.native.nix.override { + pname = "nix-coverage"; + withCoverageChecks = true; + }; # Nix's manual manual = nixpkgsFor.x86_64-linux.native.nixComponents.nix-manual; @@ -179,7 +180,7 @@ in import (nixpkgs + "/lib/tests/test-with-nix.nix") { lib = nixpkgsFor.${system}.native.lib; - nix = self.packages.${system}.nix-cli; + nix = self.packages.${system}.nix; pkgs = nixpkgsFor.${system}.native; } ); diff --git a/scripts/local.mk b/scripts/local.mk new file mode 100644 index 000000000..46255e432 --- /dev/null +++ b/scripts/local.mk @@ -0,0 +1,13 @@ +nix_noinst_scripts := \ + $(d)/nix-profile.sh + +noinst-scripts += $(nix_noinst_scripts) + +profiledir = $(sysconfdir)/profile.d + +$(eval $(call install-file-as, $(d)/nix-profile.sh, $(profiledir)/nix.sh, 0644)) +$(eval $(call install-file-as, $(d)/nix-profile.fish, $(profiledir)/nix.fish, 0644)) +$(eval $(call install-file-as, $(d)/nix-profile-daemon.sh, $(profiledir)/nix-daemon.sh, 0644)) +$(eval $(call install-file-as, $(d)/nix-profile-daemon.fish, $(profiledir)/nix-daemon.fish, 0644)) + +clean-files += $(nix_noinst_scripts) diff --git a/src/libcmd/local.mk b/src/libcmd/local.mk new file mode 100644 index 000000000..a270333f4 --- /dev/null +++ b/src/libcmd/local.mk @@ -0,0 +1,15 @@ +libraries += libcmd + +libcmd_NAME = libnixcmd + +libcmd_DIR := $(d) + +libcmd_SOURCES := $(wildcard $(d)/*.cc) + +libcmd_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libfetchers) $(INCLUDE_libexpr) $(INCLUDE_libflake) $(INCLUDE_libmain) + +libcmd_LDFLAGS = $(EDITLINE_LIBS) $(LOWDOWN_LIBS) $(THREAD_LDFLAGS) + +libcmd_LIBS = libutil libstore libfetchers libflake libexpr libmain + +$(eval $(call install-file-in, $(buildprefix)$(d)/nix-cmd.pc, $(libdir)/pkgconfig, 0644)) diff --git a/src/libcmd/nix-cmd.pc.in b/src/libcmd/nix-cmd.pc.in new file mode 100644 index 000000000..39575f222 --- /dev/null +++ b/src/libcmd/nix-cmd.pc.in @@ -0,0 +1,9 @@ +prefix=@prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Nix +Description: Nix Package Manager +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lnixcmd +Cflags: -I${includedir}/nix -std=c++2a diff --git a/src/libexpr-c/local.mk b/src/libexpr-c/local.mk new file mode 100644 index 000000000..227a4095b --- /dev/null +++ b/src/libexpr-c/local.mk @@ -0,0 +1,25 @@ +libraries += libexprc + +libexprc_NAME = libnixexprc + +libexprc_DIR := $(d) + +libexprc_SOURCES := \ + $(wildcard $(d)/*.cc) \ + +# Not just for this library itself, but also for downstream libraries using this library + +INCLUDE_libexprc := -I $(d) +libexprc_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libutilc) \ + $(INCLUDE_libfetchers) \ + $(INCLUDE_libstore) $(INCLUDE_libstorec) \ + $(INCLUDE_libexpr) $(INCLUDE_libexprc) + +libexprc_LIBS = libutil libutilc libstore libstorec libfetchers libexpr + +libexprc_LDFLAGS += $(THREAD_LDFLAGS) + +$(eval $(call install-file-in, $(d)/nix-expr-c.pc, $(libdir)/pkgconfig, 0644)) + +libexprc_FORCE_INSTALL := 1 + diff --git a/src/libexpr-c/nix-expr-c.pc.in b/src/libexpr-c/nix-expr-c.pc.in new file mode 100644 index 000000000..06897064d --- /dev/null +++ b/src/libexpr-c/nix-expr-c.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Nix +Description: Nix Language Evaluator - C API +Version: @PACKAGE_VERSION@ +Requires: nix-store-c +Libs: -L${libdir} -lnixexprc +Cflags: -I${includedir}/nix diff --git a/src/libexpr-test-support/local.mk b/src/libexpr-test-support/local.mk new file mode 100644 index 000000000..0501de33c --- /dev/null +++ b/src/libexpr-test-support/local.mk @@ -0,0 +1,23 @@ +libraries += libexpr-test-support + +libexpr-test-support_NAME = libnixexpr-test-support + +libexpr-test-support_DIR := $(d) + +ifeq ($(INSTALL_UNIT_TESTS), yes) + libexpr-test-support_INSTALL_DIR := $(checklibdir) +else + libexpr-test-support_INSTALL_DIR := +endif + +libexpr-test-support_SOURCES := \ + $(wildcard $(d)/tests/*.cc) \ + $(wildcard $(d)/tests/value/*.cc) + +libexpr-test-support_CXXFLAGS += $(libexpr-tests_EXTRA_INCLUDES) + +libexpr-test-support_LIBS = \ + libstore-test-support libutil-test-support \ + libexpr libstore libutil + +libexpr-test-support_LDFLAGS := $(THREAD_LDFLAGS) -lrapidcheck diff --git a/src/libexpr-tests/local.mk b/src/libexpr-tests/local.mk new file mode 100644 index 000000000..79583a9ee --- /dev/null +++ b/src/libexpr-tests/local.mk @@ -0,0 +1,45 @@ +check: libexpr-tests_RUN + +programs += libexpr-tests + +libexpr-tests_NAME := libnixexpr-tests + +libexpr-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libexpr-tests.xml + +libexpr-tests_DIR := $(d) + +ifeq ($(INSTALL_UNIT_TESTS), yes) + libexpr-tests_INSTALL_DIR := $(checkbindir) +else + libexpr-tests_INSTALL_DIR := +endif + +libexpr-tests_SOURCES := \ + $(wildcard $(d)/*.cc) \ + $(wildcard $(d)/value/*.cc) \ + $(wildcard $(d)/flake/*.cc) + +libexpr-tests_EXTRA_INCLUDES = \ + -I src/libexpr-test-support \ + -I src/libstore-test-support \ + -I src/libutil-test-support \ + $(INCLUDE_libexpr) \ + $(INCLUDE_libexprc) \ + $(INCLUDE_libfetchers) \ + $(INCLUDE_libstore) \ + $(INCLUDE_libstorec) \ + $(INCLUDE_libutil) \ + $(INCLUDE_libutilc) + +libexpr-tests_CXXFLAGS += $(libexpr-tests_EXTRA_INCLUDES) + +libexpr-tests_LIBS = \ + libexpr-test-support libstore-test-support libutil-test-support \ + libexpr libexprc libfetchers libstore libstorec libutil libutilc + +libexpr-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) -lgmock + +ifdef HOST_WINDOWS + # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space + libexpr-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) +endif diff --git a/src/libexpr/local.mk b/src/libexpr/local.mk new file mode 100644 index 000000000..68518e184 --- /dev/null +++ b/src/libexpr/local.mk @@ -0,0 +1,50 @@ +libraries += libexpr + +libexpr_NAME = libnixexpr + +libexpr_DIR := $(d) + +libexpr_SOURCES := \ + $(wildcard $(d)/*.cc) \ + $(wildcard $(d)/value/*.cc) \ + $(wildcard $(d)/primops/*.cc) \ + $(d)/lexer-tab.cc \ + $(d)/parser-tab.cc +# Not just for this library itself, but also for downstream libraries using this library + +INCLUDE_libexpr := -I $(d) + +libexpr_CXXFLAGS += \ + $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libfetchers) $(INCLUDE_libexpr) \ + -DGC_THREADS + +libexpr_LIBS = libutil libstore libfetchers + +libexpr_LDFLAGS += -lboost_context $(THREAD_LDFLAGS) +ifdef HOST_LINUX + libexpr_LDFLAGS += -ldl +endif + +# The dependency on libgc must be propagated (i.e. meaning that +# programs/libraries that use libexpr must explicitly pass -lgc), +# because inline functions in libexpr's header files call libgc. +libexpr_LDFLAGS_PROPAGATED = $(BDW_GC_LIBS) + +libexpr_ORDER_AFTER := $(d)/parser-tab.cc $(d)/parser-tab.hh $(d)/lexer-tab.cc $(d)/lexer-tab.hh + +$(d)/parser-tab.cc $(d)/parser-tab.hh: $(d)/parser.y + $(trace-gen) bison -v -o $(libexpr_DIR)/parser-tab.cc $< -d + +$(d)/lexer-tab.cc $(d)/lexer-tab.hh: $(d)/lexer.l + $(trace-gen) flex --outfile $(libexpr_DIR)/lexer-tab.cc --header-file=$(libexpr_DIR)/lexer-tab.hh $< + +clean-files += $(d)/parser-tab.cc $(d)/parser-tab.hh $(d)/lexer-tab.cc $(d)/lexer-tab.hh + +$(eval $(call install-file-in, $(buildprefix)$(d)/nix-expr.pc, $(libdir)/pkgconfig, 0644)) + +$(foreach i, $(wildcard src/libexpr/value/*.hh), \ + $(eval $(call install-file-in, $(i), $(includedir)/nix/value, 0644))) + +$(d)/primops.cc: $(d)/imported-drv-to-derivation.nix.gen.hh + +$(d)/eval.cc: $(d)/primops/derivation.nix.gen.hh $(d)/fetchurl.nix.gen.hh $(d)/call-flake.nix.gen.hh diff --git a/src/libexpr/nix-expr.pc.in b/src/libexpr/nix-expr.pc.in new file mode 100644 index 000000000..60ffb5dba --- /dev/null +++ b/src/libexpr/nix-expr.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Nix +Description: Nix Package Manager +Version: @PACKAGE_VERSION@ +Requires: nix-store bdw-gc +Libs: -L${libdir} -lnixexpr +Cflags: -I${includedir}/nix -std=c++2a diff --git a/src/libexpr/package.nix b/src/libexpr/package.nix index d97e7f3a8..ca1f8bf21 100644 --- a/src/libexpr/package.nix +++ b/src/libexpr/package.nix @@ -71,10 +71,6 @@ mkMesonLibrary (finalAttrs: { nix-util nix-store nix-fetchers - ] ++ finalAttrs.passthru.externalPropagatedBuildInputs; - - # Hack for sake of the dev shell - passthru.externalPropagatedBuildInputs = [ boost nlohmann_json ] ++ lib.optional enableGC boehmgc; diff --git a/src/libfetchers-tests/local.mk b/src/libfetchers-tests/local.mk new file mode 100644 index 000000000..5c90f1fc7 --- /dev/null +++ b/src/libfetchers-tests/local.mk @@ -0,0 +1,37 @@ +check: libfetchers-tests_RUN + +programs += libfetchers-tests + +libfetchers-tests_NAME = libnixfetchers-tests + +libfetchers-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libfetchers-tests.xml + +libfetchers-tests_DIR := $(d) + +ifeq ($(INSTALL_UNIT_TESTS), yes) + libfetchers-tests_INSTALL_DIR := $(checkbindir) +else + libfetchers-tests_INSTALL_DIR := +endif + +libfetchers-tests_SOURCES := $(wildcard $(d)/*.cc) + +libfetchers-tests_EXTRA_INCLUDES = \ + -I src/libstore-test-support \ + -I src/libutil-test-support \ + $(INCLUDE_libfetchers) \ + $(INCLUDE_libstore) \ + $(INCLUDE_libutil) + +libfetchers-tests_CXXFLAGS += $(libfetchers-tests_EXTRA_INCLUDES) + +libfetchers-tests_LIBS = \ + libstore-test-support libutil-test-support \ + libfetchers libstore libutil + +libfetchers-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) $(LIBGIT2_LIBS) + +ifdef HOST_WINDOWS + # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space + libfetchers-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) +endif diff --git a/src/libfetchers/local.mk b/src/libfetchers/local.mk new file mode 100644 index 000000000..e229a0993 --- /dev/null +++ b/src/libfetchers/local.mk @@ -0,0 +1,17 @@ +libraries += libfetchers + +libfetchers_NAME = libnixfetchers + +libfetchers_DIR := $(d) + +libfetchers_SOURCES := $(wildcard $(d)/*.cc) + +# Not just for this library itself, but also for downstream libraries using this library + +INCLUDE_libfetchers := -I $(d) + +libfetchers_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libfetchers) + +libfetchers_LDFLAGS += $(THREAD_LDFLAGS) $(LIBGIT2_LIBS) -larchive + +libfetchers_LIBS = libutil libstore diff --git a/src/libflake-tests/local.mk b/src/libflake-tests/local.mk new file mode 100644 index 000000000..8599b43f6 --- /dev/null +++ b/src/libflake-tests/local.mk @@ -0,0 +1,43 @@ +check: libflake-tests_RUN + +programs += libflake-tests + +libflake-tests_NAME := libnixflake-tests + +libflake-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libflake-tests.xml + +libflake-tests_DIR := $(d) + +ifeq ($(INSTALL_UNIT_TESTS), yes) + libflake-tests_INSTALL_DIR := $(checkbindir) +else + libflake-tests_INSTALL_DIR := +endif + +libflake-tests_SOURCES := \ + $(wildcard $(d)/*.cc) \ + $(wildcard $(d)/value/*.cc) \ + $(wildcard $(d)/flake/*.cc) + +libflake-tests_EXTRA_INCLUDES = \ + -I src/libflake-test-support \ + -I src/libstore-test-support \ + -I src/libutil-test-support \ + $(INCLUDE_libflake) \ + $(INCLUDE_libexpr) \ + $(INCLUDE_libfetchers) \ + $(INCLUDE_libstore) \ + $(INCLUDE_libutil) \ + +libflake-tests_CXXFLAGS += $(libflake-tests_EXTRA_INCLUDES) + +libflake-tests_LIBS = \ + libexpr-test-support libstore-test-support libutil-test-support \ + libflake libexpr libfetchers libstore libutil + +libflake-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) -lgmock + +ifdef HOST_WINDOWS + # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space + libflake-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) +endif diff --git a/src/libflake/flake/nix-flake.pc.in b/src/libflake/flake/nix-flake.pc.in new file mode 100644 index 000000000..10c52f5e9 --- /dev/null +++ b/src/libflake/flake/nix-flake.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Nix +Description: Nix Package Manager +Version: @PACKAGE_VERSION@ +Requires: nix-util nix-store nix-expr +Libs: -L${libdir} -lnixflake +Cflags: -I${includedir}/nix -std=c++2a diff --git a/src/libflake/local.mk b/src/libflake/local.mk new file mode 100644 index 000000000..5e604ef3a --- /dev/null +++ b/src/libflake/local.mk @@ -0,0 +1,22 @@ +libraries += libflake + +libflake_NAME = libnixflake + +libflake_DIR := $(d) + +libflake_SOURCES := $(wildcard $(d)/*.cc $(d)/flake/*.cc) + +# Not just for this library itself, but also for downstream libraries using this library + +INCLUDE_libflake := -I $(d) + +libflake_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libfetchers) $(INCLUDE_libexpr) $(INCLUDE_libflake) + +libflake_LDFLAGS += $(THREAD_LDFLAGS) + +libflake_LIBS = libutil libstore libfetchers libexpr + +$(eval $(call install-file-in, $(buildprefix)$(d)/flake/nix-flake.pc, $(libdir)/pkgconfig, 0644)) + +$(foreach i, $(wildcard src/libflake/flake/*.hh), \ + $(eval $(call install-file-in, $(i), $(includedir)/nix/flake, 0644))) diff --git a/src/libmain/local.mk b/src/libmain/local.mk new file mode 100644 index 000000000..d41c49dd7 --- /dev/null +++ b/src/libmain/local.mk @@ -0,0 +1,22 @@ +libraries += libmain + +libmain_NAME = libnixmain + +libmain_DIR := $(d) + +libmain_SOURCES := $(wildcard $(d)/*.cc) +ifdef HOST_UNIX + libmain_SOURCES += $(wildcard $(d)/unix/*.cc) +endif + +INCLUDE_libmain := -I $(d) + +libmain_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libmain) + +libmain_LDFLAGS += $(OPENSSL_LIBS) + +libmain_LIBS = libstore libutil + +libmain_ALLOW_UNDEFINED = 1 + +$(eval $(call install-file-in, $(buildprefix)$(d)/nix-main.pc, $(libdir)/pkgconfig, 0644)) diff --git a/src/libmain/nix-main.pc.in b/src/libmain/nix-main.pc.in new file mode 100644 index 000000000..fb3ead6fa --- /dev/null +++ b/src/libmain/nix-main.pc.in @@ -0,0 +1,9 @@ +prefix=@prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Nix +Description: Nix Package Manager +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lnixmain +Cflags: -I${includedir}/nix -std=c++2a diff --git a/src/libstore-c/local.mk b/src/libstore-c/local.mk new file mode 100644 index 000000000..5e3eff06a --- /dev/null +++ b/src/libstore-c/local.mk @@ -0,0 +1,21 @@ +libraries += libstorec + +libstorec_NAME = libnixstorec + +libstorec_DIR := $(d) + +libstorec_SOURCES := $(wildcard $(d)/*.cc) + +libstorec_LIBS = libutil libstore libutilc + +libstorec_LDFLAGS += $(THREAD_LDFLAGS) + +# Not just for this library itself, but also for downstream libraries using this library + +INCLUDE_libstorec := -I $(d) +libstorec_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libutilc) \ + $(INCLUDE_libstore) $(INCLUDE_libstorec) + +$(eval $(call install-file-in, $(d)/nix-store-c.pc, $(libdir)/pkgconfig, 0644)) + +libstorec_FORCE_INSTALL := 1 diff --git a/src/libstore-c/nix-store-c.pc.in b/src/libstore-c/nix-store-c.pc.in new file mode 100644 index 000000000..de3c7b4c6 --- /dev/null +++ b/src/libstore-c/nix-store-c.pc.in @@ -0,0 +1,9 @@ +prefix=@prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Nix +Description: Nix Store - C API +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lnixstorec -lnixutilc +Cflags: -I${includedir}/nix diff --git a/src/libstore-test-support/local.mk b/src/libstore-test-support/local.mk new file mode 100644 index 000000000..56dedd825 --- /dev/null +++ b/src/libstore-test-support/local.mk @@ -0,0 +1,21 @@ +libraries += libstore-test-support + +libstore-test-support_NAME = libnixstore-test-support + +libstore-test-support_DIR := $(d) + +ifeq ($(INSTALL_UNIT_TESTS), yes) + libstore-test-support_INSTALL_DIR := $(checklibdir) +else + libstore-test-support_INSTALL_DIR := +endif + +libstore-test-support_SOURCES := $(wildcard $(d)/tests/*.cc) + +libstore-test-support_CXXFLAGS += $(libstore-tests_EXTRA_INCLUDES) + +libstore-test-support_LIBS = \ + libutil-test-support \ + libstore libutil + +libstore-test-support_LDFLAGS := $(THREAD_LDFLAGS) -lrapidcheck diff --git a/src/libstore-tests/local.mk b/src/libstore-tests/local.mk new file mode 100644 index 000000000..b565ff0be --- /dev/null +++ b/src/libstore-tests/local.mk @@ -0,0 +1,38 @@ +check: libstore-tests_RUN + +programs += libstore-tests + +libstore-tests_NAME = libnixstore-tests + +libstore-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libstore-tests.xml + +libstore-tests_DIR := $(d) + +ifeq ($(INSTALL_UNIT_TESTS), yes) + libstore-tests_INSTALL_DIR := $(checkbindir) +else + libstore-tests_INSTALL_DIR := +endif + +libstore-tests_SOURCES := $(wildcard $(d)/*.cc) + +libstore-tests_EXTRA_INCLUDES = \ + -I src/libstore-test-support \ + -I src/libutil-test-support \ + $(INCLUDE_libstore) \ + $(INCLUDE_libstorec) \ + $(INCLUDE_libutil) \ + $(INCLUDE_libutilc) + +libstore-tests_CXXFLAGS += $(libstore-tests_EXTRA_INCLUDES) + +libstore-tests_LIBS = \ + libstore-test-support libutil-test-support \ + libstore libstorec libutil libutilc + +libstore-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) + +ifdef HOST_WINDOWS + # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space + libstore-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) +endif diff --git a/src/libstore/local.mk b/src/libstore/local.mk new file mode 100644 index 000000000..43d8993ba --- /dev/null +++ b/src/libstore/local.mk @@ -0,0 +1,103 @@ +libraries += libstore + +libstore_NAME = libnixstore + +libstore_DIR := $(d) + +libstore_SOURCES := $(wildcard $(d)/*.cc $(d)/builtins/*.cc $(d)/build/*.cc) +ifdef HOST_UNIX + libstore_SOURCES += $(wildcard $(d)/unix/*.cc $(d)/unix/build/*.cc) +endif +ifdef HOST_LINUX + libstore_SOURCES += $(wildcard $(d)/linux/*.cc) +endif +ifdef HOST_WINDOWS + libstore_SOURCES += $(wildcard $(d)/windows/*.cc) +endif + +libstore_LIBS = libutil + +libstore_LDFLAGS += $(SQLITE3_LIBS) $(LIBCURL_LIBS) $(THREAD_LDFLAGS) +ifdef HOST_LINUX + libstore_LDFLAGS += -ldl +endif +ifdef HOST_WINDOWS + libstore_LDFLAGS += -lws2_32 +endif + +$(foreach file,$(libstore_FILES),$(eval $(call install-data-in,$(d)/$(file),$(datadir)/nix/sandbox))) + +ifeq ($(ENABLE_S3), 1) + libstore_LDFLAGS += -laws-cpp-sdk-transfer -laws-cpp-sdk-s3 -laws-cpp-sdk-core -laws-crt-cpp +endif + +ifdef HOST_SOLARIS + libstore_LDFLAGS += -lsocket +endif + +ifeq ($(HAVE_SECCOMP), 1) + libstore_LDFLAGS += $(LIBSECCOMP_LIBS) +endif + +# Not just for this library itself, but also for downstream libraries using this library + +INCLUDE_libstore := -I $(d) -I $(d)/build +ifdef HOST_UNIX + INCLUDE_libstore += -I $(d)/unix -I $(d)/unix/build +endif +ifdef HOST_LINUX + INCLUDE_libstore += -I $(d)/linux +endif +ifdef HOST_WINDOWS + INCLUDE_libstore += -I $(d)/windows +endif + +ifdef HOST_WINDOWS +NIX_ROOT = N:\\\\ +else +NIX_ROOT = +endif + +# Prefix all but `NIX_STORE_DIR`, since we aren't doing a local store +# yet so a "logical" store dir that is the same as unix is preferred. +# +# Also, it keeps the unit tests working. + +libstore_CXXFLAGS += \ + $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libstore) \ + -DNIX_PREFIX=\"$(NIX_ROOT)$(prefix)\" \ + -DNIX_STORE_DIR=\"$(storedir)\" \ + -DNIX_DATA_DIR=\"$(NIX_ROOT)$(datadir)\" \ + -DNIX_STATE_DIR=\"$(NIX_ROOT)$(localstatedir)/nix\" \ + -DNIX_LOG_DIR=\"$(NIX_ROOT)$(localstatedir)/log/nix\" \ + -DNIX_CONF_DIR=\"$(NIX_ROOT)$(sysconfdir)/nix\" \ + -DNIX_MAN_DIR=\"$(NIX_ROOT)$(mandir)\" \ + -DLSOF=\"$(NIX_ROOT)$(lsof)\" + +ifeq ($(embedded_sandbox_shell),yes) +libstore_CXXFLAGS += -DSANDBOX_SHELL=\"__embedded_sandbox_shell__\" + +$(d)/unix/build/local-derivation-goal.cc: $(d)/unix/embedded-sandbox-shell.gen.hh + +$(d)/unix/embedded-sandbox-shell.gen.hh: $(sandbox_shell) + $(trace-gen) hexdump -v -e '1/1 "0x%x," "\n"' < $< > $@.tmp + @mv $@.tmp $@ +else + ifneq ($(sandbox_shell),) + libstore_CXXFLAGS += -DSANDBOX_SHELL="\"$(sandbox_shell)\"" + endif +endif + +$(d)/local-store.cc: $(d)/schema.sql.gen.hh $(d)/ca-specific-schema.sql.gen.hh + +$(d)/unix/build.cc: + +clean-files += $(d)/schema.sql.gen.hh $(d)/ca-specific-schema.sql.gen.hh + +$(eval $(call install-file-in, $(buildprefix)$(d)/nix-store.pc, $(libdir)/pkgconfig, 0644)) + +$(foreach i, $(wildcard src/libstore/builtins/*.hh), \ + $(eval $(call install-file-in, $(i), $(includedir)/nix/builtins, 0644))) + +$(foreach i, $(wildcard src/libstore/build/*.hh), \ + $(eval $(call install-file-in, $(i), $(includedir)/nix/build, 0644))) diff --git a/src/libstore/nix-store.pc.in b/src/libstore/nix-store.pc.in new file mode 100644 index 000000000..cd3f2b8da --- /dev/null +++ b/src/libstore/nix-store.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Nix +Description: Nix Package Manager +Version: @PACKAGE_VERSION@ +Requires: nix-util +Libs: -L${libdir} -lnixstore +Cflags: -I${includedir}/nix -std=c++2a diff --git a/src/libutil-c/local.mk b/src/libutil-c/local.mk new file mode 100644 index 000000000..f2df1ef43 --- /dev/null +++ b/src/libutil-c/local.mk @@ -0,0 +1,18 @@ +libraries += libutilc + +libutilc_NAME = libnixutilc + +libutilc_DIR := $(d) + +libutilc_SOURCES := $(wildcard $(d)/*.cc) + +# Not just for this library itself, but also for downstream libraries using this library + +INCLUDE_libutilc := -I $(d) +libutilc_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libutilc) + +libutilc_LIBS = libutil + +libutilc_LDFLAGS += $(THREAD_LDFLAGS) + +libutilc_FORCE_INSTALL := 1 diff --git a/src/libutil-c/nix-util-c.pc.in b/src/libutil-c/nix-util-c.pc.in new file mode 100644 index 000000000..0ccae3f8a --- /dev/null +++ b/src/libutil-c/nix-util-c.pc.in @@ -0,0 +1,9 @@ +prefix=@prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Nix libutil C API +Description: Common functions for the Nix C API, such as error handling +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lnixutil +Cflags: -I${includedir}/nix -std=c++2a diff --git a/src/libutil-test-support/local.mk b/src/libutil-test-support/local.mk new file mode 100644 index 000000000..5f7835c9f --- /dev/null +++ b/src/libutil-test-support/local.mk @@ -0,0 +1,19 @@ +libraries += libutil-test-support + +libutil-test-support_NAME = libnixutil-test-support + +libutil-test-support_DIR := $(d) + +ifeq ($(INSTALL_UNIT_TESTS), yes) + libutil-test-support_INSTALL_DIR := $(checklibdir) +else + libutil-test-support_INSTALL_DIR := +endif + +libutil-test-support_SOURCES := $(wildcard $(d)/tests/*.cc) + +libutil-test-support_CXXFLAGS += $(libutil-tests_EXTRA_INCLUDES) + +libutil-test-support_LIBS = libutil + +libutil-test-support_LDFLAGS := $(THREAD_LDFLAGS) -lrapidcheck diff --git a/src/libutil-tests/local.mk b/src/libutil-tests/local.mk new file mode 100644 index 000000000..c747863a4 --- /dev/null +++ b/src/libutil-tests/local.mk @@ -0,0 +1,37 @@ +check: libutil-tests_RUN + +programs += libutil-tests + +libutil-tests_NAME = libnixutil-tests + +libutil-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libutil-tests.xml + +libutil-tests_DIR := $(d) + +ifeq ($(INSTALL_UNIT_TESTS), yes) + libutil-tests_INSTALL_DIR := $(checkbindir) +else + libutil-tests_INSTALL_DIR := +endif + +libutil-tests_SOURCES := $(wildcard $(d)/*.cc) + +libutil-tests_EXTRA_INCLUDES = \ + -I src/libutil-test-support \ + $(INCLUDE_libutil) \ + $(INCLUDE_libutilc) + +libutil-tests_CXXFLAGS += $(libutil-tests_EXTRA_INCLUDES) + +libutil-tests_LIBS = libutil-test-support libutil libutilc + +libutil-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) + +ifdef HOST_WINDOWS + # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space + libutil-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) +endif + +check: $(d)/data/git/check-data.sh.test + +$(eval $(call run-test,$(d)/data/git/check-data.sh)) diff --git a/src/libutil/local.mk b/src/libutil/local.mk new file mode 100644 index 000000000..e9b498e65 --- /dev/null +++ b/src/libutil/local.mk @@ -0,0 +1,44 @@ +libraries += libutil + +libutil_NAME = libnixutil + +libutil_DIR := $(d) + +libutil_SOURCES := $(wildcard $(d)/*.cc $(d)/signature/*.cc) +ifdef HOST_UNIX + libutil_SOURCES += $(wildcard $(d)/unix/*.cc) +endif +ifdef HOST_LINUX + libutil_SOURCES += $(wildcard $(d)/linux/*.cc) +endif +ifdef HOST_WINDOWS + libutil_SOURCES += $(wildcard $(d)/windows/*.cc) +endif + +# Not just for this library itself, but also for downstream libraries using this library + +INCLUDE_libutil := -I $(d) +ifdef HOST_UNIX + INCLUDE_libutil += -I $(d)/unix +endif +ifdef HOST_LINUX + INCLUDE_libutil += -I $(d)/linux +endif +ifdef HOST_WINDOWS + INCLUDE_libutil += -I $(d)/windows +endif +libutil_CXXFLAGS += $(INCLUDE_libutil) + +libutil_LDFLAGS += $(THREAD_LDFLAGS) $(LIBCURL_LIBS) $(SODIUM_LIBS) $(OPENSSL_LIBS) $(LIBBROTLI_LIBS) $(LIBARCHIVE_LIBS) $(BOOST_LDFLAGS) -lboost_context + +$(foreach i, $(wildcard $(d)/args/*.hh), \ + $(eval $(call install-file-in, $(i), $(includedir)/nix/args, 0644))) +$(foreach i, $(wildcard $(d)/signature/*.hh), \ + $(eval $(call install-file-in, $(i), $(includedir)/nix/signature, 0644))) + + +ifeq ($(HAVE_LIBCPUID), 1) + libutil_LDFLAGS += -lcpuid +endif + +$(eval $(call install-file-in, $(buildprefix)$(d)/nix-util.pc, $(libdir)/pkgconfig, 0644)) diff --git a/src/libutil/nix-util.pc.in b/src/libutil/nix-util.pc.in new file mode 100644 index 000000000..85bb1e70e --- /dev/null +++ b/src/libutil/nix-util.pc.in @@ -0,0 +1,9 @@ +prefix=@prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: Nix +Description: Nix Package Manager +Version: @PACKAGE_VERSION@ +Libs: -L${libdir} -lnixutil +Cflags: -I${includedir}/nix -std=c++2a diff --git a/src/nix/local.mk b/src/nix/local.mk new file mode 100644 index 000000000..b57f6b3e2 --- /dev/null +++ b/src/nix/local.mk @@ -0,0 +1,59 @@ +programs += nix + +nix_DIR := $(d) + +nix_SOURCES := \ + $(wildcard $(d)/*.cc) \ + $(wildcard src/nix-build/*.cc) \ + $(wildcard src/nix-env/*.cc) \ + $(wildcard src/nix-instantiate/*.cc) \ + $(wildcard src/nix-store/*.cc) + +ifdef HOST_UNIX +nix_SOURCES += \ + $(wildcard $(d)/unix/*.cc) \ + $(wildcard src/build-remote/*.cc) \ + $(wildcard src/nix-channel/*.cc) \ + $(wildcard src/nix-collect-garbage/*.cc) \ + $(wildcard src/nix-copy-closure/*.cc) \ + $(wildcard src/nix-daemon/*.cc) +endif + +INCLUDE_nix := -I $(d) +ifdef HOST_UNIX + INCLUDE_nix += -I $(d)/unix +endif + +nix_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libfetchers) $(INCLUDE_libexpr) $(INCLUDE_libflake) $(INCLUDE_libmain) -I src/libcmd -I doc/manual $(INCLUDE_nix) + +nix_CXXFLAGS += -DNIX_BIN_DIR=\"$(NIX_ROOT)$(bindir)\" + +nix_LIBS = libexpr libmain libfetchers libflake libstore libutil libcmd + +nix_LDFLAGS = $(THREAD_LDFLAGS) $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) $(LOWDOWN_LIBS) + +ifdef HOST_WINDOWS + # Increase the default reserved stack size to 65 MB so Nix doesn't run out of space + nix_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024))) +endif + +$(foreach name, \ + nix-build nix-channel nix-collect-garbage nix-copy-closure nix-daemon nix-env nix-hash nix-instantiate nix-prefetch-url nix-shell nix-store, \ + $(eval $(call install-symlink, nix, $(bindir)/$(name)))) +$(eval $(call install-symlink, $(bindir)/nix, $(libexecdir)/nix/build-remote)) + +src/nix-env/user-env.cc: src/nix-env/buildenv.nix.gen.hh + +$(d)/develop.cc: $(d)/get-env.sh.gen.hh + +src/nix-channel/nix-channel.cc: src/nix-channel/unpack-channel.nix.gen.hh + +$(d)/main.cc: \ + doc/manual/generate-manpage.nix.gen.hh \ + doc/manual/utils.nix.gen.hh doc/manual/generate-settings.nix.gen.hh \ + doc/manual/generate-store-info.nix.gen.hh \ + $(d)/help-stores.md.gen.hh + +$(d)/profile.cc: $(d)/profile.md + +$(d)/profile.md: $(d)/profiles.md.gen.hh diff --git a/src/perl/package.nix b/src/perl/package.nix index 5ee0df13c..fe617fd47 100644 --- a/src/perl/package.nix +++ b/src/perl/package.nix @@ -40,10 +40,6 @@ perl.pkgs.toPerlModule (mkMesonDerivation (finalAttrs: { buildInputs = [ nix-store - ] ++ finalAttrs.passthru.externalBuildInputs; - - # Hack for sake of the dev shell - passthru.externalBuildInputs = [ bzip2 libsodium ]; diff --git a/tests/functional/build-hook-ca-fixed.nix b/tests/functional/build-hook-ca-fixed.nix index 0ce6d9b12..427ec2c31 100644 --- a/tests/functional/build-hook-ca-fixed.nix +++ b/tests/functional/build-hook-ca-fixed.nix @@ -1,6 +1,6 @@ { busybox }: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let diff --git a/tests/functional/build-hook.nix b/tests/functional/build-hook.nix index 99a13aee4..1f0e17a3b 100644 --- a/tests/functional/build-hook.nix +++ b/tests/functional/build-hook.nix @@ -1,6 +1,6 @@ { busybox, contentAddressed ? false }: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let diff --git a/tests/functional/ca/config.nix b/tests/functional/ca/config.nix deleted file mode 100644 index 451fbae4f..000000000 --- a/tests/functional/ca/config.nix +++ /dev/null @@ -1,2 +0,0 @@ -# Shim to get generated file -import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/ca/config.nix" diff --git a/tests/functional/ca/content-addressed.nix b/tests/functional/ca/content-addressed.nix index 2559c562f..411ebb86b 100644 --- a/tests/functional/ca/content-addressed.nix +++ b/tests/functional/ca/content-addressed.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/ca/config.nix"; let mkCADerivation = args: mkDerivation ({ __contentAddressed = true; diff --git a/tests/functional/ca/local.mk b/tests/functional/ca/local.mk new file mode 100644 index 000000000..7c2fcc451 --- /dev/null +++ b/tests/functional/ca/local.mk @@ -0,0 +1,29 @@ +ca-tests := \ + $(d)/build-with-garbage-path.sh \ + $(d)/build.sh \ + $(d)/build-cache.sh \ + $(d)/concurrent-builds.sh \ + $(d)/derivation-json.sh \ + $(d)/duplicate-realisation-in-closure.sh \ + $(d)/eval-store.sh \ + $(d)/gc.sh \ + $(d)/import-from-derivation.sh \ + $(d)/new-build-cmd.sh \ + $(d)/nix-copy.sh \ + $(d)/nix-run.sh \ + $(d)/nix-shell.sh \ + $(d)/post-hook.sh \ + $(d)/recursive.sh \ + $(d)/repl.sh \ + $(d)/selfref-gc.sh \ + $(d)/signatures.sh \ + $(d)/substitute.sh \ + $(d)/why-depends.sh + +install-tests-groups += ca + +clean-files += \ + $(d)/config.nix + +test-deps += \ + tests/functional/ca/config.nix diff --git a/tests/functional/ca/nix-run.sh b/tests/functional/ca/nix-run.sh index e6638cc91..21c09117e 100755 --- a/tests/functional/ca/nix-run.sh +++ b/tests/functional/ca/nix-run.sh @@ -6,4 +6,7 @@ flakeDir="$TEST_HOME/flake" mkdir -p "${flakeDir}" cp flake.nix "${_NIX_TEST_BUILD_DIR}/ca/config.nix" content-addressed.nix "${flakeDir}" +# `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. +removeBuildDirRef "$flakeDir"/*.nix + nix run --no-write-lock-file "path:${flakeDir}#runnable" diff --git a/tests/functional/ca/nondeterministic.nix b/tests/functional/ca/nondeterministic.nix index d6d099a3e..740be4bd2 100644 --- a/tests/functional/ca/nondeterministic.nix +++ b/tests/functional/ca/nondeterministic.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/ca/config.nix"; let mkCADerivation = args: mkDerivation ({ __contentAddressed = true; diff --git a/tests/functional/ca/racy.nix b/tests/functional/ca/racy.nix index 555a15484..cadd98675 100644 --- a/tests/functional/ca/racy.nix +++ b/tests/functional/ca/racy.nix @@ -2,7 +2,7 @@ # build it at once. -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/ca/config.nix"; mkDerivation { name = "simple"; diff --git a/tests/functional/check-refs.nix b/tests/functional/check-refs.nix index 89690e456..54957f635 100644 --- a/tests/functional/check-refs.nix +++ b/tests/functional/check-refs.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { diff --git a/tests/functional/check-reqs.nix b/tests/functional/check-reqs.nix index 41436cb48..4e059f5a4 100644 --- a/tests/functional/check-reqs.nix +++ b/tests/functional/check-reqs.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { dep1 = mkDerivation { diff --git a/tests/functional/check.nix b/tests/functional/check.nix index ddab8eea9..13638eae8 100644 --- a/tests/functional/check.nix +++ b/tests/functional/check.nix @@ -1,6 +1,6 @@ {checkBuildId ? 0}: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; { nondeterministic = mkDerivation { diff --git a/tests/functional/chroot-store.sh b/tests/functional/chroot-store.sh index 46e91f0aa..8c2a969d3 100755 --- a/tests/functional/chroot-store.sh +++ b/tests/functional/chroot-store.sh @@ -39,6 +39,9 @@ EOF cp simple.nix shell.nix simple.builder.sh "${config_nix}" "$flakeDir/" + # `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. + removeBuildDirRef "$flakeDir"/*.nix + TODO_NixOS outPath=$(nix build --print-out-paths --no-link --sandbox-paths '/nix? /bin? /lib? /lib64? /usr?' --store "$TEST_ROOT/x" path:"$flakeDir") diff --git a/tests/functional/common/functions.sh b/tests/functional/common/functions.sh index 7195149cb..286bb58e8 100644 --- a/tests/functional/common/functions.sh +++ b/tests/functional/common/functions.sh @@ -343,6 +343,15 @@ count() { echo $# } +# Sometimes, e.g. due to pure eval, restricted eval, or sandboxing, we +# cannot look up `config.nix` in the build dir, and have to instead get +# it from the current directory. (In this case, the current directly +# will be somewhere in `$TEST_ROOT`.) +removeBuildDirRef() { + # shellcheck disable=SC2016 # The ${} in this is Nix, not shell + sed -i -e 's,"${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/[^ ]*config.nix",./config.nix,' "$@" +} + trap onError ERR fi # COMMON_FUNCTIONS_SH_SOURCED diff --git a/tests/functional/config.nix b/tests/functional/config.nix deleted file mode 100644 index 5d1cb74ec..000000000 --- a/tests/functional/config.nix +++ /dev/null @@ -1,2 +0,0 @@ -# Shim to get generated file -import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix" diff --git a/tests/functional/dependencies.nix b/tests/functional/dependencies.nix index be1a7ae9a..db06321da 100644 --- a/tests/functional/dependencies.nix +++ b/tests/functional/dependencies.nix @@ -1,5 +1,5 @@ { hashInvalidator ? "" }: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let { diff --git a/tests/functional/dyn-drv/config.nix b/tests/functional/dyn-drv/config.nix deleted file mode 100644 index 8ec2c67ea..000000000 --- a/tests/functional/dyn-drv/config.nix +++ /dev/null @@ -1,2 +0,0 @@ -# Shim to get generated file -import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/dyn-drv/config.nix" diff --git a/tests/functional/dyn-drv/local.mk b/tests/functional/dyn-drv/local.mk new file mode 100644 index 000000000..c87534944 --- /dev/null +++ b/tests/functional/dyn-drv/local.mk @@ -0,0 +1,15 @@ +dyn-drv-tests := \ + $(d)/text-hashed-output.sh \ + $(d)/recursive-mod-json.sh \ + $(d)/build-built-drv.sh \ + $(d)/eval-outputOf.sh \ + $(d)/dep-built-drv.sh \ + $(d)/old-daemon-error-hack.sh + +install-tests-groups += dyn-drv + +clean-files += \ + $(d)/config.nix + +test-deps += \ + tests/functional/dyn-drv/config.nix diff --git a/tests/functional/dyn-drv/old-daemon-error-hack.nix b/tests/functional/dyn-drv/old-daemon-error-hack.nix index c9d4a62d4..7d3ccf7e4 100644 --- a/tests/functional/dyn-drv/old-daemon-error-hack.nix +++ b/tests/functional/dyn-drv/old-daemon-error-hack.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/dyn-drv/config.nix"; # A simple content-addressed derivation. # The derivation can be arbitrarily modified by passing a different `seed`, diff --git a/tests/functional/dyn-drv/recursive-mod-json.nix b/tests/functional/dyn-drv/recursive-mod-json.nix index c6a24ca4f..0e778aa7f 100644 --- a/tests/functional/dyn-drv/recursive-mod-json.nix +++ b/tests/functional/dyn-drv/recursive-mod-json.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/dyn-drv/config.nix"; let innerName = "foo"; in diff --git a/tests/functional/dyn-drv/text-hashed-output.nix b/tests/functional/dyn-drv/text-hashed-output.nix index 99203b518..aa46fff61 100644 --- a/tests/functional/dyn-drv/text-hashed-output.nix +++ b/tests/functional/dyn-drv/text-hashed-output.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/dyn-drv/config.nix"; # A simple content-addressed derivation. # The derivation can be arbitrarily modified by passing a different `seed`, diff --git a/tests/functional/export-graph.nix b/tests/functional/export-graph.nix index 64fe36bd1..97ffe73a9 100644 --- a/tests/functional/export-graph.nix +++ b/tests/functional/export-graph.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { diff --git a/tests/functional/extra-sandbox-profile.nix b/tests/functional/extra-sandbox-profile.nix index aa680b918..5f0e4753f 100644 --- a/tests/functional/extra-sandbox-profile.nix +++ b/tests/functional/extra-sandbox-profile.nix @@ -1,6 +1,6 @@ { destFile, seed }: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; mkDerivation { name = "simple"; diff --git a/tests/functional/failing.nix b/tests/functional/failing.nix index d25e2d6b6..8b7990679 100644 --- a/tests/functional/failing.nix +++ b/tests/functional/failing.nix @@ -1,5 +1,5 @@ { busybox }: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let mkDerivation = args: diff --git a/tests/functional/filter-source.nix b/tests/functional/filter-source.nix index 907163639..dcef9c4e2 100644 --- a/tests/functional/filter-source.nix +++ b/tests/functional/filter-source.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; mkDerivation { name = "filter"; diff --git a/tests/functional/fixed.nix b/tests/functional/fixed.nix index a920a2167..f70b89091 100644 --- a/tests/functional/fixed.nix +++ b/tests/functional/fixed.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { diff --git a/tests/functional/flakes/bundle.sh b/tests/functional/flakes/bundle.sh index 2946aea35..61aa040e7 100755 --- a/tests/functional/flakes/bundle.sh +++ b/tests/functional/flakes/bundle.sh @@ -4,6 +4,9 @@ source common.sh cp ../simple.nix ../simple.builder.sh "${config_nix}" "$TEST_HOME" +# `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. +removeBuildDirRef "$TEST_HOME"/*.nix + cd "$TEST_HOME" cat < flake.nix diff --git a/tests/functional/flakes/common.sh b/tests/functional/flakes/common.sh index cc9b2e466..8af72f2ad 100644 --- a/tests/functional/flakes/common.sh +++ b/tests/functional/flakes/common.sh @@ -35,6 +35,9 @@ writeSimpleFlake() { EOF cp ../simple.nix ../shell.nix ../simple.builder.sh "${config_nix}" "$flakeDir/" + + # `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. + removeBuildDirRef "$flakeDir"/*.nix } createSimpleGitFlake() { diff --git a/tests/functional/flakes/config.sh b/tests/functional/flakes/config.sh index ab2d9f47c..48f1c7a85 100755 --- a/tests/functional/flakes/config.sh +++ b/tests/functional/flakes/config.sh @@ -3,6 +3,7 @@ source common.sh cp ../simple.nix ../simple.builder.sh "${config_nix}" $TEST_HOME +removeBuildDirRef "$TEST_HOME/simple.nix" cd $TEST_HOME diff --git a/tests/functional/flakes/develop.sh b/tests/functional/flakes/develop.sh index b3e438e99..2e75081d4 100755 --- a/tests/functional/flakes/develop.sh +++ b/tests/functional/flakes/develop.sh @@ -27,6 +27,9 @@ EOF mkdir -p "$TEST_HOME/nixpkgs" cp "${config_nix}" ../shell.nix "$TEST_HOME/nixpkgs" +# `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. +removeBuildDirRef "$TEST_HOME/nixpkgs"/*.nix + cat <"$TEST_HOME/nixpkgs/flake.nix" { outputs = {self}: { diff --git a/tests/functional/flakes/local.mk b/tests/functional/flakes/local.mk new file mode 100644 index 000000000..a37840240 --- /dev/null +++ b/tests/functional/flakes/local.mk @@ -0,0 +1,25 @@ +flake-tests := \ + $(d)/flakes.sh \ + $(d)/develop.sh \ + $(d)/edit.sh \ + $(d)/run.sh \ + $(d)/mercurial.sh \ + $(d)/circular.sh \ + $(d)/init.sh \ + $(d)/inputs.sh \ + $(d)/follow-paths.sh \ + $(d)/bundle.sh \ + $(d)/check.sh \ + $(d)/unlocked-override.sh \ + $(d)/absolute-paths.sh \ + $(d)/absolute-attr-paths.sh \ + $(d)/build-paths.sh \ + $(d)/flake-in-submodule.sh \ + $(d)/prefetch.sh \ + $(d)/eval-cache.sh \ + $(d)/search-root.sh \ + $(d)/config.sh \ + $(d)/show.sh \ + $(d)/dubious-query.sh + +install-tests-groups += flake diff --git a/tests/functional/flakes/run.sh b/tests/functional/flakes/run.sh index c92ddca2b..2077c965b 100755 --- a/tests/functional/flakes/run.sh +++ b/tests/functional/flakes/run.sh @@ -8,6 +8,8 @@ clearStore rm -rf $TEST_HOME/.cache $TEST_HOME/.config $TEST_HOME/.local cp ../shell-hello.nix "${config_nix}" $TEST_HOME +# `config.nix` cannot be gotten via build dir / env var (runs afoul pure eval). Instead get from flake. +removeBuildDirRef "$TEST_HOME"/*.nix cd $TEST_HOME cat < flake.nix diff --git a/tests/functional/fod-failing.nix b/tests/functional/fod-failing.nix index 37c04fe12..7881a3fbf 100644 --- a/tests/functional/fod-failing.nix +++ b/tests/functional/fod-failing.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { x1 = mkDerivation { name = "x1"; diff --git a/tests/functional/gc-concurrent.nix b/tests/functional/gc-concurrent.nix index 0aba1f983..a5c3c97c3 100644 --- a/tests/functional/gc-concurrent.nix +++ b/tests/functional/gc-concurrent.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; { lockFifo ? null }: diff --git a/tests/functional/gc-runtime.nix b/tests/functional/gc-runtime.nix index ee5980bdf..2603fafdf 100644 --- a/tests/functional/gc-runtime.nix +++ b/tests/functional/gc-runtime.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; mkDerivation { name = "gc-runtime"; diff --git a/tests/functional/git-hashing/local.mk b/tests/functional/git-hashing/local.mk new file mode 100644 index 000000000..ebec01940 --- /dev/null +++ b/tests/functional/git-hashing/local.mk @@ -0,0 +1,7 @@ +git-hashing-tests := \ + $(d)/simple.sh + +install-tests-groups += git-hashing + +clean-files += \ + $(d)/config.nix diff --git a/tests/functional/hermetic.nix b/tests/functional/hermetic.nix index d1dccdff3..dafe8ad9f 100644 --- a/tests/functional/hermetic.nix +++ b/tests/functional/hermetic.nix @@ -5,7 +5,7 @@ , withFinalRefs ? false }: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let contentAddressedByDefault = builtins.getEnv "NIX_TESTS_CA_BY_DEFAULT" == "1"; diff --git a/tests/functional/ifd.nix b/tests/functional/ifd.nix index d0b9b54ad..c84ffbc66 100644 --- a/tests/functional/ifd.nix +++ b/tests/functional/ifd.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; import ( mkDerivation { name = "foo"; diff --git a/tests/functional/import-from-derivation.nix b/tests/functional/import-from-derivation.nix index cc53451cf..8864fb30a 100644 --- a/tests/functional/import-from-derivation.nix +++ b/tests/functional/import-from-derivation.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { bar = mkDerivation { diff --git a/tests/functional/impure-derivations.nix b/tests/functional/impure-derivations.nix index 98547e6c1..04710323f 100644 --- a/tests/functional/impure-derivations.nix +++ b/tests/functional/impure-derivations.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { diff --git a/tests/functional/impure-env.nix b/tests/functional/impure-env.nix index 2b0380ed7..6b9e5a825 100644 --- a/tests/functional/impure-env.nix +++ b/tests/functional/impure-env.nix @@ -1,6 +1,6 @@ { var, value }: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; mkDerivation { name = "test"; diff --git a/tests/functional/linux-sandbox-cert-test.nix b/tests/functional/linux-sandbox-cert-test.nix index 2fc083ea9..e506b6a0f 100644 --- a/tests/functional/linux-sandbox-cert-test.nix +++ b/tests/functional/linux-sandbox-cert-test.nix @@ -1,6 +1,6 @@ { mode }: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; mkDerivation ( { diff --git a/tests/functional/local-overlay-store/local.mk b/tests/functional/local-overlay-store/local.mk new file mode 100644 index 000000000..6348a4423 --- /dev/null +++ b/tests/functional/local-overlay-store/local.mk @@ -0,0 +1,14 @@ +local-overlay-store-tests := \ + $(d)/check-post-init.sh \ + $(d)/redundant-add.sh \ + $(d)/build.sh \ + $(d)/bad-uris.sh \ + $(d)/add-lower.sh \ + $(d)/delete-refs.sh \ + $(d)/delete-duplicate.sh \ + $(d)/gc.sh \ + $(d)/verify.sh \ + $(d)/optimise.sh \ + $(d)/stale-file-handle.sh + +install-tests-groups += local-overlay-store diff --git a/tests/functional/local.mk b/tests/functional/local.mk new file mode 100644 index 000000000..e50b5eaf1 --- /dev/null +++ b/tests/functional/local.mk @@ -0,0 +1,146 @@ +nix_tests = \ + test-infra.sh \ + gc.sh \ + nix-collect-garbage-d.sh \ + remote-store.sh \ + legacy-ssh-store.sh \ + lang.sh \ + lang-gc.sh \ + characterisation-test-infra.sh \ + experimental-features.sh \ + fetchMercurial.sh \ + gc-auto.sh \ + user-envs.sh \ + user-envs-migration.sh \ + binary-cache.sh \ + multiple-outputs.sh \ + nix-build.sh \ + gc-concurrent.sh \ + repair.sh \ + fixed.sh \ + export-graph.sh \ + timeout.sh \ + fetchGitRefs.sh \ + gc-runtime.sh \ + tarball.sh \ + fetchGit.sh \ + fetchurl.sh \ + fetchPath.sh \ + fetchTree-file.sh \ + simple.sh \ + referrers.sh \ + optimise-store.sh \ + substitute-with-invalid-ca.sh \ + signing.sh \ + hash-convert.sh \ + hash-path.sh \ + gc-non-blocking.sh \ + check.sh \ + nix-shell.sh \ + check-refs.sh \ + build-remote-input-addressed.sh \ + secure-drv-outputs.sh \ + restricted.sh \ + fetchGitSubmodules.sh \ + fetchGitVerification.sh \ + readfile-context.sh \ + nix-channel.sh \ + recursive.sh \ + dependencies.sh \ + check-reqs.sh \ + build-remote-content-addressed-fixed.sh \ + build-remote-content-addressed-floating.sh \ + build-remote-trustless-should-pass-0.sh \ + build-remote-trustless-should-pass-1.sh \ + build-remote-trustless-should-pass-2.sh \ + build-remote-trustless-should-pass-3.sh \ + build-remote-trustless-should-fail-0.sh \ + build-remote-with-mounted-ssh-ng.sh \ + nar-access.sh \ + impure-eval.sh \ + pure-eval.sh \ + eval.sh \ + repl.sh \ + binary-cache-build-remote.sh \ + search.sh \ + logging.sh \ + export.sh \ + config.sh \ + add.sh \ + chroot-store.sh \ + filter-source.sh \ + misc.sh \ + dump-db.sh \ + linux-sandbox.sh \ + supplementary-groups.sh \ + build-dry.sh \ + structured-attrs.sh \ + shell.sh \ + brotli.sh \ + zstd.sh \ + compression-levels.sh \ + nix-copy-ssh.sh \ + nix-copy-ssh-ng.sh \ + post-hook.sh \ + function-trace.sh \ + fmt.sh \ + eval-store.sh \ + why-depends.sh \ + derivation-json.sh \ + derivation-advanced-attributes.sh \ + import-from-derivation.sh \ + nix_path.sh \ + nars.sh \ + placeholders.sh \ + ssh-relay.sh \ + build.sh \ + build-delete.sh \ + output-normalization.sh \ + selfref-gc.sh \ + db-migration.sh \ + bash-profile.sh \ + pass-as-file.sh \ + nix-profile.sh \ + suggestions.sh \ + store-info.sh \ + fetchClosure.sh \ + completions.sh \ + impure-derivations.sh \ + path-from-hash-part.sh \ + path-info.sh \ + toString-path.sh \ + read-only-store.sh \ + nested-sandboxing.sh \ + impure-env.sh \ + debugger.sh \ + extra-sandbox-profile.sh \ + +ifeq ($(HAVE_LIBCPUID), 1) + nix_tests += compute-levels.sh +endif + +ifeq ($(ENABLE_BUILD), yes) + nix_tests += test-libstoreconsumer.sh + + ifeq ($(BUILD_SHARED_LIBS), 1) + nix_tests += plugins.sh + endif +endif + +ifeq ($(ENABLE_DOC_GEN), yes) + nix_tests += help.sh +endif + +$(d)/test-libstoreconsumer.sh.test $(d)/test-libstoreconsumer.sh.test-debug: \ + $(buildprefix)$(d)/test-libstoreconsumer/test-libstoreconsumer +$(d)/plugins.sh.test $(d)/plugins.sh.test-debug: \ + $(buildprefix)$(d)/plugins/libplugintest.$(SO_EXT) + +install-tests += $(foreach x, $(nix_tests), $(d)/$(x)) + +test-clean-files := \ + $(d)/common/subst-vars.sh \ + $(d)/config.nix + +clean-files += $(test-clean-files) +test-deps += $(test-clean-files) diff --git a/tests/functional/multiple-outputs.nix b/tests/functional/multiple-outputs.nix index 6ba7c523d..19ae2a45d 100644 --- a/tests/functional/multiple-outputs.nix +++ b/tests/functional/multiple-outputs.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { diff --git a/tests/functional/nar-access.nix b/tests/functional/nar-access.nix index 9948abe59..78972bd36 100644 --- a/tests/functional/nar-access.nix +++ b/tests/functional/nar-access.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { a = mkDerivation { diff --git a/tests/functional/nix-build-examples.nix b/tests/functional/nix-build-examples.nix index e54dbbf62..aaea8fc07 100644 --- a/tests/functional/nix-build-examples.nix +++ b/tests/functional/nix-build-examples.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { diff --git a/tests/functional/parallel.nix b/tests/functional/parallel.nix index 23f142059..1f2411c92 100644 --- a/tests/functional/parallel.nix +++ b/tests/functional/parallel.nix @@ -1,6 +1,6 @@ {sleepTime ? 3}: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let diff --git a/tests/functional/path.nix b/tests/functional/path.nix index 883c3c41b..b23300f90 100644 --- a/tests/functional/path.nix +++ b/tests/functional/path.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; mkDerivation { name = "filter"; diff --git a/tests/functional/plugins/local.mk b/tests/functional/plugins/local.mk new file mode 100644 index 000000000..2314e1341 --- /dev/null +++ b/tests/functional/plugins/local.mk @@ -0,0 +1,11 @@ +libraries += libplugintest + +libplugintest_DIR := $(d) + +libplugintest_SOURCES := $(d)/plugintest.cc + +libplugintest_ALLOW_UNDEFINED := 1 + +libplugintest_EXCLUDE_FROM_LIBRARY_LIST := 1 + +libplugintest_CXXFLAGS := $(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libexpr) $(INCLUDE_libfetchers) diff --git a/tests/functional/readfile-context.nix b/tests/functional/readfile-context.nix index 54cd1afd9..b8f4a4c27 100644 --- a/tests/functional/readfile-context.nix +++ b/tests/functional/readfile-context.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let diff --git a/tests/functional/restricted.sh b/tests/functional/restricted.sh index 00ee4ddc8..63bf56cd7 100755 --- a/tests/functional/restricted.sh +++ b/tests/functional/restricted.sh @@ -12,6 +12,10 @@ mkdir -p "$TEST_ROOT/nix" cp ./simple.nix "$TEST_ROOT/nix" cp ./simple.builder.sh "$TEST_ROOT/nix" cp "${config_nix}" "$TEST_ROOT/nix" +simple_nix="$TEST_ROOT/nix/simple.nix" +# N.B. redefine +config_nix="$TEST_ROOT/nix/config.nix" +removeBuildDirRef "${simple_nix}" cd "$TEST_ROOT/nix" nix-instantiate --restrict-eval ./simple.nix -I src=. diff --git a/tests/functional/search.nix b/tests/functional/search.nix index fea6e7a7a..3c3564bda 100644 --- a/tests/functional/search.nix +++ b/tests/functional/search.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; { hello = mkDerivation rec { diff --git a/tests/functional/secure-drv-outputs.nix b/tests/functional/secure-drv-outputs.nix index b4ac8ff53..cd111c315 100644 --- a/tests/functional/secure-drv-outputs.nix +++ b/tests/functional/secure-drv-outputs.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; { diff --git a/tests/functional/shell-hello.nix b/tests/functional/shell-hello.nix index c920d7cb4..fa02e2bb4 100644 --- a/tests/functional/shell-hello.nix +++ b/tests/functional/shell-hello.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; rec { hello = mkDerivation { diff --git a/tests/functional/shell.nix b/tests/functional/shell.nix index 9cae14b78..f6622a487 100644 --- a/tests/functional/shell.nix +++ b/tests/functional/shell.nix @@ -1,6 +1,6 @@ { inNixShell ? false, contentAddressed ? false, fooContents ? "foo" }: -let cfg = import ./config.nix; in +let cfg = import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; in with cfg; let diff --git a/tests/functional/simple-failing.nix b/tests/functional/simple-failing.nix index d176c9c51..228971734 100644 --- a/tests/functional/simple-failing.nix +++ b/tests/functional/simple-failing.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; mkDerivation { name = "simple-failing"; diff --git a/tests/functional/simple.nix b/tests/functional/simple.nix index 2035ca294..96237695c 100644 --- a/tests/functional/simple.nix +++ b/tests/functional/simple.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; mkDerivation { name = "simple"; diff --git a/tests/functional/structured-attrs-shell.nix b/tests/functional/structured-attrs-shell.nix index 57c1e6bd2..7ed28c03f 100644 --- a/tests/functional/structured-attrs-shell.nix +++ b/tests/functional/structured-attrs-shell.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let dep = mkDerivation { name = "dep"; diff --git a/tests/functional/structured-attrs.nix b/tests/functional/structured-attrs.nix index e93139a44..ae461c21a 100644 --- a/tests/functional/structured-attrs.nix +++ b/tests/functional/structured-attrs.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let diff --git a/tests/functional/symlink-derivation.nix b/tests/functional/symlink-derivation.nix index e9a74cdce..96765d355 100644 --- a/tests/functional/symlink-derivation.nix +++ b/tests/functional/symlink-derivation.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; let foo_in_store = builtins.toFile "foo" "foo"; diff --git a/tests/functional/test-libstoreconsumer/local.mk b/tests/functional/test-libstoreconsumer/local.mk new file mode 100644 index 000000000..3e8581c57 --- /dev/null +++ b/tests/functional/test-libstoreconsumer/local.mk @@ -0,0 +1,15 @@ +programs += test-libstoreconsumer + +test-libstoreconsumer_DIR := $(d) + +# do not install +test-libstoreconsumer_INSTALL_DIR := + +test-libstoreconsumer_SOURCES := \ + $(wildcard $(d)/*.cc) \ + +test-libstoreconsumer_CXXFLAGS += $(INCLUDE_libutil) $(INCLUDE_libstore) + +test-libstoreconsumer_LIBS = libstore libutil + +test-libstoreconsumer_LDFLAGS = $(THREAD_LDFLAGS) $(SODIUM_LIBS) $(EDITLINE_LIBS) $(BOOST_LDFLAGS) $(LOWDOWN_LIBS) diff --git a/tests/functional/timeout.nix b/tests/functional/timeout.nix index d0e949e31..ad71e61e2 100644 --- a/tests/functional/timeout.nix +++ b/tests/functional/timeout.nix @@ -1,4 +1,4 @@ -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; { diff --git a/tests/functional/user-envs.nix b/tests/functional/user-envs.nix index 46f8b51dd..c8e846d4b 100644 --- a/tests/functional/user-envs.nix +++ b/tests/functional/user-envs.nix @@ -2,7 +2,7 @@ { foo ? "foo" }: -with import ./config.nix; +with import "${builtins.getEnv "_NIX_TEST_BUILD_DIR"}/config.nix"; assert foo == "foo";