From b3ee378f5038886d08b2a17eb4ab5130ba7f77b8 Mon Sep 17 00:00:00 2001 From: Nikolay Amiantov Date: Thu, 5 Feb 2015 18:12:14 +0300 Subject: [PATCH] buildFHSChrootEnv: split environment and chroot scripts --- .../build-fhs-chrootenv/default.nix | 185 +----------------- .../build-fhs-chrootenv/destroy.sh.in | 4 +- .../build-support/build-fhs-chrootenv/env.nix | 176 +++++++++++++++++ .../build-fhs-chrootenv/init.sh.in | 6 +- pkgs/top-level/all-packages.nix | 14 +- 5 files changed, 194 insertions(+), 191 deletions(-) create mode 100644 pkgs/build-support/build-fhs-chrootenv/env.nix diff --git a/pkgs/build-support/build-fhs-chrootenv/default.nix b/pkgs/build-support/build-fhs-chrootenv/default.nix index a4ba456d7a53..8f24ab5e63c7 100644 --- a/pkgs/build-support/build-fhs-chrootenv/default.nix +++ b/pkgs/build-support/build-fhs-chrootenv/default.nix @@ -1,97 +1,6 @@ -{ buildEnv, nixpkgs, nixpkgs_i686, system -, stdenv, glibc, glibc_multi, glibcLocales -, bashInteractive, coreutils, less, shadow, su -, gawk, gcc, gcc_multi, diffutils, findutils, gnused, gnugrep -, gnutar, gzip, bzip2, xz -} : -{ name, pkgs ? [], profile ? "" -, targetPkgs ? null, multiPkgs ? null -, extraBuildCommands ? "", extraBuildCommandsMulti ? "" -}: - -assert pkgs != [] -> targetPkgs == null && multiPkgs == null; -assert targetPkgs != null -> multiPkgs != null; -assert multiPkgs != null -> targetPkgs != null; -assert targetPkgs != null -> pkgs == []; - - -# HOWTO: -# If pkgs is defined buildFHSChrootEnv will run in legacy mode. This means -# it will build all pkgs contained in pkgs and basePkgs and then just merge -# all of their contents together via buildEnv. -# -# The new way is to define both targetPkgs and multiPkgs. These two are -# functions which get a pkgs environment supplied and should then return a list -# of packages based this environment. -# For example: targetPkgs = pkgs: [ pkgs.nmap ]; -# -# All packages (most likeley programs) placed in targetPkgs will only be -# installed once--matching the hosts architecture (64bit on x86_64 and 32bit on -# x86). These packages will populate the chroot directory tree. -# -# Packages (most likeley libraries) defined in multiPkgs will be installed once -# on x86 systems and twice on x86_64 systems. -# On x86 they will just be merge with the packages defined in targetPkgs. -# On x86_64 they will be added to targetPkgs and in addition their 32bit -# versions will also be installed. The final directory should look as follows: -# /lib will include 32bit libraries from multiPkgs -# /lib32 will link to /lib -# /lib64 will include 64bit libraries from multiPkgs and targetPkgs -# /x86 will contain a complete 32bit environment composed by multiPkgs +{ stdenv } : { env } : let - is64Bit = system == "x86_64-linux"; - # enable multi builds on x86_64 hosts if pakgs_target/multi are defined - isMultiBuild = is64Bit && targetPkgs != null; - isTargetBuild = !isMultiBuild; - - # list of packages (usually programs) which will only be installed for the - # hosts architecture - targetPaths = if targetPkgs == null - then pkgs - else targetPkgs nixpkgs ++ multiPkgs nixpkgs; - - # list of pckages which should be build for both x86 and x86_64 on x86_64 - # systems - multiPaths = if isMultiBuild - then multiPkgs nixpkgs_i686 - else []; - - # base packages of the chroot - # these match the hosts architecture, gcc/glibc_multi will be choosen - # on multi builds - choosenGcc = if isMultiBuild then gcc_multi else gcc; - basePkgs = - [ (if isMultiBuild then glibc_multi else glibc) - choosenGcc - bashInteractive coreutils less shadow su - gawk diffutils findutils gnused gnugrep - gnutar gzip bzip2 xz - ]; - - # Compose a global profile for the chroot environment - profilePkg = nixpkgs.stdenv.mkDerivation { - name = "${name}-chrootenv-profile"; - buildCommand = '' - mkdir -p $out/etc - cat >> $out/etc/profile << "EOF" - export PS1='${name}-chrootenv:\u@\h:\w\$ ' - ${profile} - EOF - ''; - }; - - # Composes a /usr like directory structure - staticUsrProfileTarget = buildEnv { - name = "system-profile-target"; - paths = basePkgs ++ [ profilePkg ] ++ targetPaths; - }; - - staticUsrProfileMulti = buildEnv { - name = "system-profile-multi"; - paths = multiPaths; - }; - # References to shell scripts that set up or tear down the environment initSh = ./init.sh.in; mountSh = ./mount.sh.in; @@ -99,89 +8,15 @@ let umountSh = ./umount.sh.in; destroySh = ./destroy.sh.in; - linkProfile = profile: '' - for i in ${profile}/{etc,bin,sbin,share,var}; do - if [ -x "$i" ] - then - ln -s "$i" - fi - done - ''; - - # the target profile is the actual profile that will be used for the chroot - setupTargetProfile = '' - ${linkProfile staticUsrProfileTarget} - ${setupLibDirs} - - mkdir -m0755 usr - cd usr - ${linkProfile staticUsrProfileTarget} - ${setupLibDirs} - cd .. - ''; - - # this will happen on x86_64 host: - # /x86 -> links to the whole profile defined by multiPaths - # /lib, /lib32 -> links to 32bit binaries - # /lib64 -> links to 64bit binaries - # /usr/lib* -> same as above - setupMultiProfile = if isTargetBuild then "" else '' - mkdir -m0755 x86 - cd x86 - ${linkProfile staticUsrProfileMulti} - cd .. - ''; - - setupLibDirs = if isTargetBuild then setupLibDirs_target - else setupLibDirs_multi; - - # setup library paths only for the targeted architecture - setupLibDirs_target = '' - mkdir -m0755 lib - - # copy content of targetPaths - cp -rsf ${staticUsrProfileTarget}/lib/* lib/ - ''; - - # setup /lib, /lib32 and /lib64 - setupLibDirs_multi = '' - mkdir -m0755 lib - mkdir -m0755 lib64 - ln -s lib lib32 - - # copy glibc stuff - cp -rsf ${staticUsrProfileTarget}/lib/32/* lib/ - - # copy content of multiPaths (32bit libs) - cp -rsf ${staticUsrProfileMulti}/lib/* lib/ - - # copy content of targetPaths (64bit libs) - cp -rsf ${staticUsrProfileTarget}/lib/* lib64/ - - # most 64bit only libs put their stuff into /lib - # some pkgs (like gcc_multi) put 32bit libs into and /lib 64bit libs into /lib64 - # by overwriting these we will hopefully catch all these cases - # in the end /lib should only contain 32bit and /lib64 only 64bit libs - cp -rsf ${staticUsrProfileTarget}/lib64/* lib64/ - - # copy gcc libs (and may overwrite exitsting wrongly placed libs) - cp -rsf ${choosenGcc.cc}/lib/* lib/ - cp -rsf ${choosenGcc.cc}/lib64/* lib64/ - ''; + name = env.pname; in stdenv.mkDerivation { name = "${name}-chrootenv"; buildCommand = '' - mkdir -p "$out/sw" - cd "$out/sw" - ${setupTargetProfile} - ${setupMultiProfile} - cd .. + mkdir -p $out/bin + cd $out/bin - mkdir -p bin - cd bin - - sed -e "s|@chrootEnv@|$out|g" \ + sed -e "s|@chrootEnv@|${env}|g" \ -e "s|@name@|${name}|g" \ -e "s|@shell@|${stdenv.shell}|g" \ ${initSh} > init-${name}-chrootenv @@ -202,18 +37,10 @@ in stdenv.mkDerivation { ${umountSh} > umount-${name}-chrootenv chmod +x umount-${name}-chrootenv - sed -e "s|@chrootEnv@|$out|g" \ + sed -e "s|@chrootEnv@|${env}|g" \ -e "s|@shell@|${stdenv.shell}|g" \ -e "s|@name@|${name}|g" \ ${destroySh} > destroy-${name}-chrootenv chmod +x destroy-${name}-chrootenv - - cd .. - - cd "$out/sw" - ${extraBuildCommands} - cd "$out/sw" - ${if isMultiBuild then extraBuildCommandsMulti else ""} - cd .. ''; } diff --git a/pkgs/build-support/build-fhs-chrootenv/destroy.sh.in b/pkgs/build-support/build-fhs-chrootenv/destroy.sh.in index 8ddf350913eb..015f742d85a5 100644 --- a/pkgs/build-support/build-fhs-chrootenv/destroy.sh.in +++ b/pkgs/build-support/build-fhs-chrootenv/destroy.sh.in @@ -6,9 +6,9 @@ chrootenvDest=/run/chrootenv/@name@ rmdir $chrootenvDest/{dev,nix/store,nix,proc,sys,host-etc,home,var,run,tmp} # Remove symlinks to the software that should be part of the chroot system profile -for i in @chrootEnv@/sw/* +for i in @chrootEnv@/* do - if [ "$i" != "@chrootEnv@/sw/etc" ] && [ "$i" != "@chrootEnv@/sw/var" ] + if [ "$i" != "@chrootEnv@/etc" ] && [ "$i" != "@chrootEnv@/var" ] then rm $chrootenvDest/$(basename $i) fi diff --git a/pkgs/build-support/build-fhs-chrootenv/env.nix b/pkgs/build-support/build-fhs-chrootenv/env.nix new file mode 100644 index 000000000000..12c0fff7510a --- /dev/null +++ b/pkgs/build-support/build-fhs-chrootenv/env.nix @@ -0,0 +1,176 @@ +{ nixpkgs, nixpkgs_i686, system +} : +{ name, pkgs ? [], profile ? "" +, targetPkgs ? null, multiPkgs ? null +, extraBuildCommands ? "", extraBuildCommandsMulti ? "" +}: + +assert pkgs != [] -> targetPkgs == null && multiPkgs == null; +assert targetPkgs != null -> multiPkgs != null; +assert multiPkgs != null -> targetPkgs != null; +assert targetPkgs != null -> pkgs == []; + + +# HOWTO: +# If pkgs is defined buildFHSEnv will run in legacy mode. This means +# it will build all pkgs contained in pkgs and basePkgs and then just merge +# all of their contents together via buildEnv. +# +# The new way is to define both targetPkgs and multiPkgs. These two are +# functions which get a pkgs environment supplied and should then return a list +# of packages based this environment. +# For example: targetPkgs = pkgs: [ pkgs.nmap ]; +# +# All packages (most likely programs) placed in targetPkgs will only be +# installed once--matching the hosts architecture (64bit on x86_64 and 32bit on +# x86). These packages will populate the chroot directory tree. +# +# Packages (most likeley libraries) defined in multiPkgs will be installed once +# on x86 systems and twice on x86_64 systems. +# On x86 they will just be merge with the packages defined in targetPkgs. +# On x86_64 they will be added to targetPkgs and in addition their 32bit +# versions will also be installed. The final directory should look as follows: +# /lib will include 32bit libraries from multiPkgs +# /lib32 will link to /lib +# /lib64 will include 64bit libraries from multiPkgs and targetPkgs +# /x86 will contain a complete 32bit environment composed by multiPkgs + +let + is64Bit = system == "x86_64-linux"; + # enable multi builds on x86_64 hosts if pakgs_target/multi are defined + isMultiBuild = is64Bit && targetPkgs != null; + isTargetBuild = !isMultiBuild; + + # list of packages (usually programs) which will only be installed for the + # hosts architecture + targetPaths = if targetPkgs == null + then pkgs + else targetPkgs nixpkgs ++ multiPkgs nixpkgs; + + # list of pckages which should be build for both x86 and x86_64 on x86_64 + # systems + multiPaths = if isMultiBuild + then multiPkgs nixpkgs_i686 + else []; + + # base packages of the chroot + # these match the hosts architecture, gcc/glibc_multi will be choosen + # on multi builds + chosenGcc = if isMultiBuild then nixpkgs.gcc_multi else nixpkgs.gcc; + basePkgs = with nixpkgs; + [ (if isMultiBuild then glibc_multi else glibc) + chosenGcc + bashInteractive coreutils less shadow su + gawk diffutils findutils gnused gnugrep + gnutar gzip bzip2 xz + ]; + + # Compose a global profile for the chroot environment + profilePkg = nixpkgs.stdenv.mkDerivation { + name = "${name}-chrootenv-profile"; + buildCommand = '' + mkdir -p $out/etc + cat >> $out/etc/profile << "EOF" + export PS1='${name}-chrootenv:\u@\h:\w\$ ' + ${profile} + EOF + ''; + }; + + # Composes a /usr like directory structure + staticUsrProfileTarget = nixpkgs.buildEnv { + name = "system-profile-target"; + paths = basePkgs ++ [ profilePkg ] ++ targetPaths; + }; + + staticUsrProfileMulti = nixpkgs.buildEnv { + name = "system-profile-multi"; + paths = multiPaths; + }; + + linkProfile = profile: '' + for i in ${profile}/{etc,bin,sbin,share,var}; do + if [ -x "$i" ] + then + ln -s "$i" + fi + done + ''; + + # the target profile is the actual profile that will be used for the chroot + setupTargetProfile = '' + ${linkProfile staticUsrProfileTarget} + ${setupLibDirs} + + mkdir -m0755 usr + cd usr + ${linkProfile staticUsrProfileTarget} + ${setupLibDirs} + cd .. + ''; + + # this will happen on x86_64 host: + # /x86 -> links to the whole profile defined by multiPaths + # /lib, /lib32 -> links to 32bit binaries + # /lib64 -> links to 64bit binaries + # /usr/lib* -> same as above + setupMultiProfile = if isTargetBuild then "" else '' + mkdir -m0755 x86 + cd x86 + ${linkProfile staticUsrProfileMulti} + cd .. + ''; + + setupLibDirs = if isTargetBuild then setupLibDirs_target + else setupLibDirs_multi; + + # setup library paths only for the targeted architecture + setupLibDirs_target = '' + mkdir -m0755 lib + + # copy content of targetPaths + cp -rsf ${staticUsrProfileTarget}/lib/* lib/ + ''; + + # setup /lib, /lib32 and /lib64 + setupLibDirs_multi = '' + mkdir -m0755 lib + mkdir -m0755 lib64 + ln -s lib lib32 + + # copy glibc stuff + cp -rsf ${staticUsrProfileTarget}/lib/32/* lib/ + + # copy content of multiPaths (32bit libs) + cp -rsf ${staticUsrProfileMulti}/lib/* lib/ + + # copy content of targetPaths (64bit libs) + cp -rsf ${staticUsrProfileTarget}/lib/* lib64/ + + # most 64bit only libs put their stuff into /lib + # some pkgs (like gcc_multi) put 32bit libs into and /lib 64bit libs into /lib64 + # by overwriting these we will hopefully catch all these cases + # in the end /lib should only contain 32bit and /lib64 only 64bit libs + cp -rsf ${staticUsrProfileTarget}/lib64/* lib64/ + + # copy gcc libs (and may overwrite exitsting wrongly placed libs) + cp -rsf ${chosenGcc.cc}/lib/* lib/ + cp -rsf ${chosenGcc.cc}/lib64/* lib64/ + ''; + +in nixpkgs.stdenv.mkDerivation { + name = "${name}-fhs"; + buildCommand = '' + mkdir -p $out + cd $out + ${setupTargetProfile} + ${setupMultiProfile} + cd $out + ${extraBuildCommands} + cd $out + ${if isMultiBuild then extraBuildCommandsMulti else ""} + ''; + passthru = { + pname = name; + }; +} diff --git a/pkgs/build-support/build-fhs-chrootenv/init.sh.in b/pkgs/build-support/build-fhs-chrootenv/init.sh.in index 079ec09d60f7..f3bdad85fa74 100644 --- a/pkgs/build-support/build-fhs-chrootenv/init.sh.in +++ b/pkgs/build-support/build-fhs-chrootenv/init.sh.in @@ -6,9 +6,9 @@ chrootenvDest=/run/chrootenv/@name@ mkdir -p $chrootenvDest/{nix/store,dev,proc,sys,host-etc,home,var,run} # Symlink the software that should be part of the chroot system profile -for i in @chrootEnv@/sw/* +for i in @chrootEnv@/* do - if [ "$i" != "@chrootEnv@/sw/etc" ] && [ "$i" != "@chrootEnv@/sw/var" ] + if [ "$i" != "@chrootEnv@/etc" ] && [ "$i" != "@chrootEnv@/var" ] then ln -s "$i" "$chrootenvDest" fi @@ -18,7 +18,7 @@ done mkdir $chrootenvDest/etc -for i in @chrootEnv@/sw/etc/* +for i in @chrootEnv@/etc/* do ln -s "$i" $chrootenvDest/etc done diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 4ac6232575d2..16f2c4af7308 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -260,17 +260,17 @@ let inherit (pkgs) runCommand perl; }; - buildFHSChrootEnv = import ../build-support/build-fhs-chrootenv { - inherit buildEnv system; - inherit stdenv glibc glibc_multi glibcLocales; - inherit bashInteractive coreutils less shadow su; - inherit gawk gcc gcc_multi diffutils findutils gnused gnugrep; - inherit gnutar gzip bzip2 xz; - + buildFHSEnv = callPackage ../build-support/build-fhs-chrootenv/env.nix { nixpkgs = pkgs; nixpkgs_i686 = pkgsi686Linux; }; + chrootFHSEnv = callPackage ../build-support/build-fhs-chrootenv { }; + + buildFHSChrootEnv = args: chrootFHSEnv { + env = buildFHSEnv args; + }; + dotnetenv = import ../build-support/dotnetenv { inherit stdenv; dotnetfx = dotnetfx40;