How to have a derivation not clash with derived environment in Nix? - nix

I get the following collision error when attempting to build an environment that, as far as I can see, shouldn't have a collision (in this case, scala-env depends on ideaLocal, so it shouldn't conflict with it):
...
idea-IU-172.4155.36/bin/libyjpagent-linux.so
idea-IU-172.4155.36/bin/libyjpagent-linux64.so
idea-IU-172.4155.36/help/ideahelp.jar
idea-IU-172.4155.36/lib/libpty/linux/x86/libpty.so
idea-IU-172.4155.36/lib/libpty/linux/x86_64/libpty.so
idea-IU-172.4155.36/bin/format.sh
idea-IU-172.4155.36/bin/fsnotifier
idea-IU-172.4155.36/bin/fsnotifier-arm
idea-IU-172.4155.36/bin/fsnotifier64
idea-IU-172.4155.36/bin/idea.sh
idea-IU-172.4155.36/bin/inspect.sh
idea-IU-172.4155.36/bin/printenv.py
idea-IU-172.4155.36/bin/restart.py
building path(s) ‘/nix/store/29g92lnpi0kywy9x7vcgl9yivwa2blm6-scala-env’
created 696 symlinks in user environment
building path(s) ‘/nix/store/qrnbff8nhpmxlzkmv508aymz5razbhgf-user-environment’
Wide character in die at /nix/store/64jc9gd2rkbgdb4yjx3nrgc91bpjj5ky-buildenv.pl line 79.
collision between ‘/nix/store/75sz9nklqmrmzxvf0faxmf6zamgaznfv-idea-local/bin/idea’ and ‘/nix/store/29g92lnpi0kywy9x7vcgl9yivwa2blm6-scala-env/bin/idea’; use ‘nix-env --set-flag priority NUMBER PKGNAME’ to change the priority of one of the conflicting packages
builder for ‘/nix/store/8hp5kdicxy9i02fa07vx85p1gvh4i1bq-user-environment.drv’ failed with exit code 255
error: build of ‘/nix/store/8hp5kdicxy9i02fa07vx85p1gvh4i1bq-user-environment.drv’ failed
Here is the nix expression (most of which can be ignored, but it isn't too long so I'll paste the whole thing):
with import <nixpkgs> { };
let
ideaLocal = stdenv.mkDerivation {
name = "idea-local";
buildInputs = [ ];
builder = builtins.toFile "builder.sh" ''
source $stdenv/setup
mkdir -p $out/bin
tar zxvf $src -C $out/
ln -sf $out/idea-IU* $out/idea
ln -sf $out/idea/bin/idea.sh $out/bin/idea
'';
shellHook = ''
IDEA_JDK=/usr/lib/jvm/zulu-8-amd64
'';
src = fetchurl {
url = https://download.jetbrains.com/idea/ideaIU-2017.2.4-no-jdk.tar.gz;
sha256 = "15a4799ffde294d0f2fce0b735bbfe370e3d0327380a0efc45905241729898e3";
};
priority = 5;
};
in
buildEnv {
name = "scala-env";
paths = [
ammonite
boehmgc
clang
dbus # needed non-explicitly by vscode
emacs
git
# idea.idea-ultimate # disabled temporarily
ideaLocal
less
libunwind
openjdk
openssh
re2
rsync
sbt
stdenv
syncthing # for syncrhonizing data between containers
tmux
unzip
vscode
zlib
];
# builder = builtins.toFile "builder.sh" ''
# source $stdenv/setup
# mkdir -p $out
# echo "" > $out/Done
# echo "Done setting up Scala environment."
# '';
buildInputs = [ makeWrapper ];
# TODO: better filter, use ammonite script?:
postBuild = ''
for f in $(ls -d $out/bin/* | grep "idea"); do
sed -i '/IDEA_JDK/d' $f
wrapProgram $f \
--set IDEA_JDK "/usr/lib/jvm/zulu-8-amd64" \
--set CLANG_PATH "${clang}/bin/clang" \
--set CLANCPP_PATH "${clang}/bin/clang++"
done
'';
}
Edit:
(DevContainer)which idea
/home/brandon/.nix-profile/bin/idea
(DevContainer)ls -last /home/brandon/.nix-profile/bin/idea
4 lrwxrwxrwx 1 brandon brandon 63 Jan 1 1970 /home/brandon/.nix-profile/bin/idea -> /nix/store/75sz9nklqmrmzxvf0faxmf6zamgaznfv-idea-local/bin/idea
So it looks like ideaLocal is being imported as an environment - what's the right way to just have it installed as a package that is a dependency of scalaEnv?

Apparently the solution was to specify the profile, which I think of as the name of the environment, so that both environments aren't installed simultaneously:
nix-env -if scala-default.nix -p scala-env

Related

How do I reference / import a derivation from a file in Nix?

I'm trying to use this project: https://github.com/mpickering/old-ghc-nix
I'm assuming I'm meant to 'import' the ghc.nix (which generates a derivation?):
shell.nix:
with (import <nixpkgs> {});
# let ghc = nur.repos.mpickering.ghc.ghc841;
let ghc = import /home/chris/temp/old-ghc-nix/ghc.nix;
in haskell.lib.buildStackProject {
inherit ghc;
name = "myEnv";
buildInputs = [ pcre ];
}
However this gives me an error of:
...
error: cannot coerce a function to a string, at /home/chris/fromLaptopt/usbflash/Haskell/CeriumYankeeAvocado/shell.nix:6:3
...
How do I "execute" the function / build the derivation?
ghc.nix:
{ stdenv
, fetchurl, perl, gcc, llvm_39
, ncurses5, gmp, glibc, libiconv
}: { version, url, hash, ...}:
# Prebuilt only does native
assert stdenv.targetPlatform == stdenv.hostPlatform;
let
libPath = stdenv.lib.makeLibraryPath ([
ncurses5 gmp
] ++ stdenv.lib.optional (stdenv.hostPlatform.isDarwin) libiconv);
libEnvVar = stdenv.lib.optionalString stdenv.hostPlatform.isDarwin "DY"
+ "LD_LIBRARY_PATH";
glibcDynLinker = assert stdenv.isLinux;
if stdenv.hostPlatform.libc == "glibc" then
# Could be stdenv.cc.bintools.dynamicLinker, keeping as-is to avoid rebuild.
''"$(cat $NIX_CC/nix-support/dynamic-linker)"''
else
"${stdenv.lib.getLib glibc}/lib/ld-linux*";
in
stdenv.mkDerivation rec {
name = "ghc-${version}-binary";
src = fetchurl {
url = url;
sha256 = hash;
};
nativeBuildInputs = [ perl ];
buildInputs = stdenv.lib.optionals (stdenv.targetPlatform.isAarch32 || stdenv.targetPlatform.isAarch64) [ llvm_39 ];
# Cannot patchelf beforehand due to relative RPATHs that anticipate
# the final install location/
${libEnvVar} = libPath;
postUnpack =
# GHC has dtrace probes, which causes ld to try to open /usr/lib/libdtrace.dylib
# during linking
stdenv.lib.optionalString stdenv.isDarwin ''
export NIX_LDFLAGS+=" -no_dtrace_dof"
# not enough room in the object files for the full path to libiconv :(
for exe in $(find . -type f -executable); do
isScript $exe && continue
ln -fs ${libiconv}/lib/libiconv.dylib $(dirname $exe)/libiconv.dylib
install_name_tool -change /usr/lib/libiconv.2.dylib #executable_path/libiconv.dylib -change /usr/local/lib/gcc/6/libgcc_s.1.dylib ${gcc.cc.lib}/lib/libgcc_s.1.dylib $exe
done
'' +
# Some scripts used during the build need to have their shebangs patched
''
patchShebangs ghc-${version}/utils/
patchShebangs ghc-${version}/configure
'' +
# Strip is harmful, see also below. It's important that this happens
# first. The GHC Cabal build system makes use of strip by default and
# has hardcoded paths to /usr/bin/strip in many places. We replace
# those below, making them point to our dummy script.
''
mkdir "$TMP/bin"
for i in strip; do
echo '#! ${stdenv.shell}' > "$TMP/bin/$i"
chmod +x "$TMP/bin/$i"
done
PATH="$TMP/bin:$PATH"
'' +
# We have to patch the GMP paths for the integer-gmp package.
''
find . -name integer-gmp.buildinfo \
-exec sed -i "s#extra-lib-dirs: #extra-lib-dirs: ${gmp.out}/lib#" {} \;
'' + stdenv.lib.optionalString stdenv.isDarwin ''
find . -name base.buildinfo \
-exec sed -i "s#extra-lib-dirs: #extra-lib-dirs: ${libiconv}/lib#" {} \;
'' +
# Rename needed libraries and binaries, fix interpreter
stdenv.lib.optionalString stdenv.isLinux ''
find . -type f -perm -0100 -exec patchelf \
--replace-needed libncurses${stdenv.lib.optionalString stdenv.is64bit "w"}.so.5 libncurses.so \
--replace-needed libtinfo.so libtinfo.so.5 \
--interpreter ${glibcDynLinker} {} \;
sed -i "s|/usr/bin/perl|perl\x00 |" ghc-${version}/ghc/stage2/build/tmp/ghc-stage2
sed -i "s|/usr/bin/gcc|gcc\x00 |" ghc-${version}/ghc/stage2/build/tmp/ghc-stage2
'';
configurePlatforms = [ ];
configureFlags = [
"--with-gmp-libraries=${stdenv.lib.getLib gmp}/lib"
"--with-gmp-includes=${stdenv.lib.getDev gmp}/include"
] ++ stdenv.lib.optional stdenv.isDarwin "--with-gcc=${./gcc-clang-wrapper.sh}"
++ stdenv.lib.optional stdenv.hostPlatform.isMusl "--disable-ld-override";
# Stripping combined with patchelf breaks the executables (they die
# with a segfault or the kernel even refuses the execve). (NIXPKGS-85)
dontStrip = true;
# No building is necessary, but calling make without flags ironically
# calls install-strip ...
dontBuild = true;
# On Linux, use patchelf to modify the executables so that they can
# find editline/gmp.
preFixup = stdenv.lib.optionalString stdenv.isLinux ''
for p in $(find "$out" -type f -executable); do
if isELF "$p"; then
echo "Patchelfing $p"
patchelf --set-rpath "${libPath}:$(patchelf --print-rpath $p)" $p
fi
done
'' + stdenv.lib.optionalString stdenv.isDarwin ''
# not enough room in the object files for the full path to libiconv :(
for exe in $(find "$out" -type f -executable); do
isScript $exe && continue
ln -fs ${libiconv}/lib/libiconv.dylib $(dirname $exe)/libiconv.dylib
install_name_tool -change /usr/lib/libiconv.2.dylib #executable_path/libiconv.dylib -change /usr/local/lib/gcc/6/libgcc_s.1.dylib ${gcc.cc.lib}/lib/libgcc_s.1.dylib $exe
done
for file in $(find "$out" -name setup-config); do
substituteInPlace $file --replace /usr/bin/ranlib "$(type -P ranlib)"
done
'';
doInstallCheck = true;
installCheckPhase = ''
unset ${libEnvVar}
# Sanity check, can ghc create executables?
cd $TMP
mkdir test-ghc; cd test-ghc
cat > main.hs << EOF
{-# LANGUAGE TemplateHaskell #-}
module Main where
main = putStrLn \$([|"yes"|])
EOF
$out/bin/ghc --make main.hs || exit 1
echo compilation ok
[ $(./main) == "yes" ]
'';
passthru = {
targetPrefix = "";
enableShared = true;
};
meta.license = stdenv.lib.licenses.bsd3;
meta.platforms = ["x86_64-linux" "i686-linux" "x86_64-darwin"];
}
First, some generic notes not specific to old-ghc-nix: If a .nix file you import starts with {...}:, that ... is the definition of an attrset used as a function argument; you need to actually call the imported function with that argument to get... well... whatever that function evaluates to.
Now on to the specifics. :)
old-ghc-nix provides a default.nix that looks up definitions for your old GHC versions in the accompanying JSON files. It makes sense to use that entry-point -- if you directly inherit ghc.nix, you need to provide the version, checksum and URL for the specific version of GHC you want to build.
Personally, I would write this as:
let
pkgs = (import <nixpkgs> {});
ghcOld = (import ../old-ghc-nix) { inherit pkgs; };
in with pkgs; haskell.lib.buildStackProject {
ghc = ghcOld.ghc841;
name = "myEnv";
buildInputs = [ pcre ];
}

Failed when `nix-build hello.nix`

I followed the steps on http://lethalman.blogspot.com/2014/08/nix-pill-8-generic-builders.html to build GNU Hello, and here is the files I used to build GNU hello 2.9:
$ wget -c http://ftp.gnu.org/gnu/hello/hello-2.9.tar.gz
hello.nix:
$ cat hello.nix
let
pkgs = import <nixpkgs> {};
mkDerivation = import ./autotools.nix pkgs;
in mkDerivation {
name = "hello";
src = ./hello-2.9.tar.gz;
}
autotools.nix:
$ cat autotools.nix
pkgs: attrs:
with pkgs;
let defaultAttrs = {
builder = "${bash}/bin/bash";
args = [ ./builder.sh ];
baseInputs = [ gnutar gzip gnumake gcc binutils coreutils gawk gnused gnugrep ];
buildInputs = [];
system = builtins.currentSystem;
};
in
derivation (defaultAttrs // attrs)
builder.sh:
$ cat builder.sh
set -e
unset PATH
for p in $buildInputs; do
export PATH=$p/bin${PATH:+:}$PATH
done
tar -xf $src
for d in *; do
if [ -d "$d" ]; then
cd "$d"
break
fi
done
./configure --prefix=$out
make
make install
Error messages:
$ nix-build hello.nix
these derivations will be built:
/nix/store/d84l57agx3rmw00lxs8gjlw8srmx1bh9-hello.drv
building '/nix/store/d84l57agx3rmw00lxs8gjlw8srmx1bh9-hello.drv'...
/nix/store/vv3xqdggviqqbvym25jf2pwv575y9j1r-builder.sh: line 7: tar: No such file or directory
builder for '/nix/store/d84l57agx3rmw00lxs8gjlw8srmx1bh9-hello.drv' failed with exit code 127
error: build of '/nix/store/d84l57agx3rmw00lxs8gjlw8srmx1bh9-hello.drv' failed
It seems there is gnutar in the autotools.nix but builder still complains tar: No such file or directory, why is this?
The problem is probably that gnutar is in the baseInputs list, while the buildInputs list you are building your PATH from is totally empty so nothing will be on your PATH. Try changing the for line in your shell script so that it uses the concatentation of both lists to build the path:
for p in $baseInputs $buildInputs; do
You can add echo $PATH to your builder script to debug issues like this.
That is what the blog post author was asking you to do in this sentence from the post:
Complete the new builder.sh by adding $baseInputs in the for loop together with $buildInputs.

using the nix typing system with `nix-instantiate`

myservice
i've written a nixos service in myservice.nix and i include it in /etc/nixos/configuration.nix with:
imports [ /path/to/myservice.nix ];
and later i'm using it inside configuration.nix:
services.myservice.enable = true;
question
in one scenario i can't use nixos-rebuild switch but because typing in nix is linked to the options system using foo = mkOption { type = types.int; ...} i'm forced to use the options systems even though i just want to compute a configuration file for nginx using nix.
how to evaluate that nginx.conf only?
#aszlig wrote me this command:
nix-instantiate --eval --strict -E '(import <nixpkgs/nixos> { configuration = { imports = [ nixcloud-reverse-proxy/nixcloud-reverse-proxy.nix ]; services.nixcloud-reverse-proxy.enable = true; }; }).config.system.build.configsFromPath'
execution results in
nix-instantiate --eval --strict -E '(import <nixpkgs/nixos> { configuration = { imports = [ ./nixcloud-reverse-proxy.nix ]; services.nixcloud-reverse-proxy.enable = true; }; }).config.system.build.configsFromPath'
error: attribute ‘configsFromPath’ missing, at (string):1:1
(use ‘--show-trace’ to show detailed location information)
update
nix-build '<nixpkgs/nixos>' -A config.systemd.services.nixcloud-reverse-proxy.runner -I nixos-config=./configuration.nix
...
/nix/store/lp2jbb1wahhlr7qkq81rmfvk84mjk1vk-nixcloud-reverse-proxy-runner
now i can use that to grep the conf file:
cat /nix/store/lp2jbb1wahhlr7qkq81rmfvk84mjk1vk-nixcloud-reverse-proxy-runner | grep -o ' /nix/store/.*nginx-reverse-proxy.conf'
... kind of a workaround but not very precise! i'd rather like a config file in a directory.
I see your file name is nginx-reverse-proxy.conf, so it isn't built with fancy NixOS module system, but with some other ways. In that case (you control how you build your file) you can include it globally:
environment.etc."myconfigs"."nginx-reverse-proxy.conf".text = ...content of that file;
Which your refer then with
$ nix-instantiate --eval -E '
with import <nixpkgs/nixos> {
configuration = { ... };
};
config.environment.etc."myconfigs"."nginx-reverse-proxy.conf".text
'
You probably need to decode that output though using trick described in https://gist.github.com/danbst/a9fc068ff26e31d88de9709965daa2bd
which is itself a convoluted way to do
$ cat $(nix-build -E '
with import <nixpkgs/nixos> {
configuration = { ... };
};
config.environment.etc."myconfigs"."nginx-reverse-proxy.conf".source
')
In case your proxy config is part of general nginx.conf script, then you still can get it using
$ cat $(cat $(nix-build -E '
with import <nixpkgs/nixos> {
configuration = ...;
};
config.system.build.units."nginx.service".unit
')/nginx.service \
| grep nginx.conf \
| sed -r 's/.* (.*nginx.conf).*/\1/g'
)
Because nginx.conf file is private to nginx module, we can't reference it directly, but have to extract it directly from usage site.
Overall, NixOS lacks a good interface to introspect its internals, but it is still possible.

Override scripts in nix derivations

Is there a way to override scripts and/or configs in an existing derivation without having to recompile the whole package?
I'd like to create a new version of gnome-session with modified $out/share/gnome-session/sessions/gnome.session modified. Using overridePackage I can change the preFixup phase, but this causes the whole gnome-session package to be recompiled.
A simple solution to problem is creating a new derivation without any sources. The trick is to create links to every file and directory in the base derivation, except for any file(s) in need of modification. These files are handled explicitly according to needs.
The snippet below shows how to create a new gnome-session with xmonad instead of gnome-shell.
{ nixpkgs ? import <nixpkgs> {} }:
let
inherit (nixpkgs) pkgs;
in
pkgs.stdenv.mkDerivation {
name = "gnome-session";
builder = pkgs.writeText "builder.sh" ''
# source standard environment
. $stdenv/setup
# shorthands
refpkg=${pkgs.gnome3.gnome_session}
file=share/gnome-session/sessions/gnome.session
# create output dirs for new derivation
mkdir -p $out/share
mkdir -p $out/share/gnome-session/sessions
# link unchanged files from the original gnome-session
ln -sf $refpkg/bin $out
ln -sf $refpkg/libexec $out
find $refpkg/share -maxdepth 1 \
-not -name gnome-session -exec ln -sf {} $out/share \;
# change gnome-shell to xmonad
sed 's/org.gnome.Shell/xmonad/' $refpkg/$file > $out/$file
'';
# make sure gnome-session is installed before deriving it!
buildInputs = [ pkgs.gnome3.gnome_session ];
}

How to install a lua module in a subdirectory of libdir with the autotools

I have written a little lua module that I complile using the autotools and I want to modify its organization:
Now I have this in the main directory:
autogen.sh
configure.ac
Makefile.am
src
file1.c
file2.c
file3.c
the autogen.sh
#!/bin/sh
echo "Running aclocal..." ; aclocal $ACLOCAL_FLAGS || exit 1
echo "Running libtoolize..."; libtoolize --copy --automake || exit 1;
echo "Running autoheader..." ; autoheader || exit 1
echo "Running autoconf..." ; autoconf || exit 1
echo "Running automake..." ; automake --add-missing --copy --gnu || exit 1
./configure "$#"
The configure.ac
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69])
AC_INIT([lua-clangc], [0.0.1], [cedlemo#gmx.com])
AC_CONFIG_SRCDIR([configure.ac])
AC_CONFIG_HEADERS([config.h])
# Checks for programs.
AC_PROG_CC(clang gcc)
# Checks for libraries.
PKG_CHECK_MODULES([DEPS], [lua])
#LUA_VERSION = $(pkg-config --version)
#AC_SUBST([LUA_VERSION])
# Checks for header files.
AC_CHECK_HEADERS([string.h stdlib.h clang-c/Index.h])
# Checks for typedefs, structures, and compiler characteristics.
# Checks for library functions.
AM_INIT_AUTOMAKE(1.13 dist-bzip2 foreign subdir-objects)
LT_PREREQ(2.4)
LT_INIT
AC_CONFIG_FILES([
Makefile
])
AC_OUTPUT
and the Makefile.am
MAINTAINERCLEANFILES = \
Makefile.in aclocal.m4 config.h.in configure \
depcomp install-sh missing compile config.sub \
config.guess ltmain.sh compile
lib_LTLIBRARIES = src/clangc.la
src_clangc_la_SOURCES = src/clangc.c src/indexlib.c src/translationunitlib.c src/constants.c src/clangc_module_functions.c
src_clangc_la_LDFLAGS = -module -avoid-version -shared -llua -lm -lclang -fPIC
I use this commands to compile and install the lua module:
./autogen.sh --libdir=/usr/lib/lua/5.3
make
sudo make install
My files are installed in /usr/lib/lua/5.3
/usr/lib/lua/5.3/clangc.so
/usr/lib/lua/5.3/clangc.la
I would like to just use
./autogen.sh --prefix=/usr
And that the configure.ac script build libdir like this:
libdir=prefix + /lib/lua/ + LUA_VERSION + /clangc/
(I have already a way to get the LUA_VERSION in the configure.ac)
As always I answer to myself:
I just have to modify my configure.ac like this:
AC_PREREQ([2.69])
AC_INIT([lua-clangc], [0.0.1], [cedlemo#gmx.com])
AC_CONFIG_SRCDIR([configure.ac])
AC_CONFIG_HEADERS([config.h])
# Checks for programs.
AC_PROG_CC(clang gcc)
# Checks for libraries.
PKG_CHECK_MODULES([DEPS], [lua])
LUA_VERSION=$(pkg-config --modversion lua | awk -F "." '{print $1"."$2}')
AC_SUBST([LUA_VERSION])
libdir=$prefix/lib/lua/$LUA_VERSION/clangc
# Checks for header files.
AC_CHECK_HEADERS([string.h stdlib.h clang-c/Index.h])
# Checks for typedefs, structures, and compiler characteristics.
# Checks for library functions.
AM_INIT_AUTOMAKE(1.13 dist-bzip2 foreign subdir-objects)
LT_PREREQ(2.4)
LT_INIT
AC_CONFIG_FILES([
Makefile
])
AC_OUTPUT
First I had to find the current lua version:
LUA_VERSION=$(pkg-config --modversion lua | awk -F "." '{print $1"."$2}')
On my system:
pkg-config --modversion lua returns 5.3.1
awk -F "." '{print $1"."$2}' returns 5.3
Then the line:
libdir=$prefix/lib/lua/$LUA_VERSION/clangc
Do all the magic.
When I use:
./autogen.sh --prefix=/usr
My lib is installed in:
/usr/lib/lua/5.3/clangc

Resources