Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #94442 from Atemu/buildFHSUserEnvBw
- Loading branch information
Showing
7 changed files
with
309 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
123 changes: 123 additions & 0 deletions
123
pkgs/build-support/build-fhs-userenv-bubblewrap/default.nix
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
{ callPackage, runCommandLocal, writeShellScriptBin, stdenv, coreutils, bubblewrap }: | ||
|
||
let buildFHSEnv = callPackage ./env.nix { }; in | ||
|
||
args @ { | ||
name, | ||
runScript ? "bash", | ||
extraInstallCommands ? "", | ||
meta ? {}, | ||
passthru ? {}, | ||
... | ||
}: | ||
|
||
with builtins; | ||
let | ||
env = buildFHSEnv (removeAttrs args [ | ||
"runScript" "extraInstallCommands" "meta" "passthru" | ||
]); | ||
|
||
chrootenv = callPackage ./chrootenv {}; | ||
|
||
etcBindFlags = let | ||
files = [ | ||
# NixOS Compatibility | ||
"static" | ||
# Users, Groups, NSS | ||
"passwd" | ||
"group" | ||
"shadow" | ||
"hosts" | ||
"resolv.conf" | ||
"nsswitch.conf" | ||
# Sudo & Su | ||
"login.defs" | ||
"sudoers" | ||
"sudoers.d" | ||
# Time | ||
"localtime" | ||
"zoneinfo" | ||
# Other Core Stuff | ||
"machine-id" | ||
"os-release" | ||
# PAM | ||
"pam.d" | ||
# Fonts | ||
"fonts" | ||
# ALSA | ||
"asound.conf" | ||
# SSL | ||
"ssl/certs" | ||
"pki" | ||
]; | ||
in concatStringsSep " \\\n " | ||
(map (file: "--ro-bind-try /etc/${file} /etc/${file}") files); | ||
|
||
init = run: writeShellScriptBin "${name}-init" '' | ||
source /etc/profile | ||
exec ${run} "$@" | ||
''; | ||
|
||
bwrapCmd = { initArgs ? "" }: '' | ||
blacklist="/nix /dev /proc /etc" | ||
ro_mounts="" | ||
for i in ${env}/*; do | ||
path="/''${i##*/}" | ||
if [[ $path == '/etc' ]]; then | ||
continue | ||
fi | ||
ro_mounts="$ro_mounts --ro-bind $i $path" | ||
blacklist="$blacklist $path" | ||
done | ||
if [[ -d ${env}/etc ]]; then | ||
for i in ${env}/etc/*; do | ||
path="/''${i##*/}" | ||
ro_mounts="$ro_mounts --ro-bind $i /etc$path" | ||
done | ||
fi | ||
auto_mounts="" | ||
# loop through all directories in the root | ||
for dir in /*; do | ||
# if it is a directory and it is not in the blacklist | ||
if [[ -d "$dir" ]] && grep -v "$dir" <<< "$blacklist" >/dev/null; then | ||
# add it to the mount list | ||
auto_mounts="$auto_mounts --bind $dir $dir" | ||
fi | ||
done | ||
exec ${bubblewrap}/bin/bwrap \ | ||
--dev-bind /dev /dev \ | ||
--proc /proc \ | ||
--chdir "$(pwd)" \ | ||
--unshare-all \ | ||
--share-net \ | ||
--die-with-parent \ | ||
--ro-bind /nix /nix \ | ||
${etcBindFlags} \ | ||
$ro_mounts \ | ||
$auto_mounts \ | ||
${init runScript}/bin/${name}-init ${initArgs} | ||
''; | ||
|
||
bin = writeShellScriptBin name (bwrapCmd { initArgs = ''"$@"''; }); | ||
|
||
in runCommandLocal name { | ||
inherit meta; | ||
|
||
passthru = passthru // { | ||
env = runCommandLocal "${name}-shell-env" { | ||
shellHook = bwrapCmd {}; | ||
} '' | ||
echo >&2 "" | ||
echo >&2 "*** User chroot 'env' attributes are intended for interactive nix-shell sessions, not for building! ***" | ||
echo >&2 "" | ||
exit 1 | ||
''; | ||
}; | ||
} '' | ||
mkdir -p $out/bin | ||
ln -s ${bin}/bin/${name} $out/bin/${name} | ||
${extraInstallCommands} | ||
'' |
167 changes: 167 additions & 0 deletions
167
pkgs/build-support/build-fhs-userenv-bubblewrap/env.nix
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
{ stdenv, buildEnv, writeText, pkgs, pkgsi686Linux }: | ||
|
||
{ name, profile ? "" | ||
, targetPkgs ? pkgs: [], multiPkgs ? pkgs: [] | ||
, extraBuildCommands ? "", extraBuildCommandsMulti ? "" | ||
, extraOutputsToInstall ? [] | ||
}: | ||
|
||
# HOWTO: | ||
# All packages (most likely programs) returned from targetPkgs will only be | ||
# installed once--matching the host's architecture (64bit on x86_64 and 32bit on | ||
# x86). | ||
# | ||
# Packages (most likely libraries) returned from multiPkgs are installed | ||
# once on x86 systems and twice on x86_64 systems. | ||
# On x86 they are merged with packages from targetPkgs. | ||
# On x86_64 they are added to targetPkgs and in addition their 32bit | ||
# versions are also installed. The final directory structure looks as | ||
# follows: | ||
# /lib32 will include 32bit libraries from multiPkgs | ||
# /lib64 will include 64bit libraries from multiPkgs and targetPkgs | ||
# /lib will link to /lib32 | ||
|
||
let | ||
is64Bit = stdenv.hostPlatform.parsed.cpu.bits == 64; | ||
isMultiBuild = multiPkgs != null && is64Bit; | ||
isTargetBuild = !isMultiBuild; | ||
|
||
# list of packages (usually programs) which are only be installed for the | ||
# host's architecture | ||
targetPaths = targetPkgs pkgs ++ (if multiPkgs == null then [] else multiPkgs pkgs); | ||
|
||
# list of packages which are installed for both x86 and x86_64 on x86_64 | ||
# systems | ||
multiPaths = multiPkgs pkgsi686Linux; | ||
|
||
# base packages of the chroot | ||
# these match the host's architecture, glibc_multi is used for multilib | ||
# builds. glibcLocales must be before glibc or glibc_multi as otherwiese | ||
# the wrong LOCALE_ARCHIVE will be used where only C.UTF-8 is available. | ||
basePkgs = with pkgs; | ||
[ glibcLocales | ||
(if isMultiBuild then glibc_multi else glibc) | ||
(toString gcc.cc.lib) bashInteractive coreutils less shadow su | ||
gawk diffutils findutils gnused gnugrep | ||
gnutar gzip bzip2 xz | ||
]; | ||
baseMultiPkgs = with pkgsi686Linux; | ||
[ (toString gcc.cc.lib) | ||
]; | ||
|
||
etcProfile = writeText "profile" '' | ||
export PS1='${name}-chrootenv:\u@\h:\w\$ ' | ||
export LOCALE_ARCHIVE='/usr/lib/locale/locale-archive' | ||
export LD_LIBRARY_PATH="/run/opengl-driver/lib:/run/opengl-driver-32/lib:/usr/lib:/usr/lib32''${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH" | ||
export PATH="/run/wrappers/bin:/usr/bin:/usr/sbin:$PATH" | ||
export TZDIR='/etc/zoneinfo' | ||
# Force compilers and other tools to look in default search paths | ||
unset NIX_ENFORCE_PURITY | ||
export NIX_CC_WRAPPER_TARGET_HOST_${stdenv.cc.suffixSalt}=1 | ||
export NIX_CFLAGS_COMPILE='-idirafter /usr/include' | ||
export NIX_CFLAGS_LINK='-L/usr/lib -L/usr/lib32' | ||
export NIX_LDFLAGS='-L/usr/lib -L/usr/lib32' | ||
export PKG_CONFIG_PATH=/usr/lib/pkgconfig | ||
export ACLOCAL_PATH=/usr/share/aclocal | ||
${profile} | ||
''; | ||
|
||
# Compose /etc for the chroot environment | ||
etcPkg = stdenv.mkDerivation { | ||
name = "${name}-chrootenv-etc"; | ||
buildCommand = '' | ||
mkdir -p $out/etc | ||
cd $out/etc | ||
# environment variables | ||
ln -s ${etcProfile} profile | ||
# symlink /etc/mtab -> /proc/mounts (compat for old userspace progs) | ||
ln -s /proc/mounts mtab | ||
''; | ||
}; | ||
|
||
# Composes a /usr-like directory structure | ||
staticUsrProfileTarget = buildEnv { | ||
name = "${name}-usr-target"; | ||
paths = [ etcPkg ] ++ basePkgs ++ targetPaths; | ||
extraOutputsToInstall = [ "out" "lib" "bin" ] ++ extraOutputsToInstall; | ||
ignoreCollisions = true; | ||
}; | ||
|
||
staticUsrProfileMulti = buildEnv { | ||
name = "${name}-usr-multi"; | ||
paths = baseMultiPkgs ++ multiPaths; | ||
extraOutputsToInstall = [ "out" "lib" ] ++ extraOutputsToInstall; | ||
ignoreCollisions = true; | ||
}; | ||
|
||
# setup library paths only for the targeted architecture | ||
setupLibDirsTarget = '' | ||
# link content of targetPaths | ||
cp -rsHf ${staticUsrProfileTarget}/lib lib | ||
ln -s lib lib${if is64Bit then "64" else "32"} | ||
''; | ||
|
||
# setup /lib, /lib32 and /lib64 | ||
setupLibDirsMulti = '' | ||
mkdir -m0755 lib32 | ||
mkdir -m0755 lib64 | ||
ln -s lib64 lib | ||
# copy glibc stuff | ||
cp -rsHf ${staticUsrProfileTarget}/lib/32/* lib32/ && chmod u+w -R lib32/ | ||
# copy content of multiPaths (32bit libs) | ||
[ -d ${staticUsrProfileMulti}/lib ] && cp -rsHf ${staticUsrProfileMulti}/lib/* lib32/ && chmod u+w -R lib32/ | ||
# copy content of targetPaths (64bit libs) | ||
cp -rsHf ${staticUsrProfileTarget}/lib/* lib64/ && chmod u+w -R lib64/ | ||
# symlink 32-bit ld-linux.so | ||
ln -Ls ${staticUsrProfileTarget}/lib/32/ld-linux.so.2 lib/ | ||
''; | ||
|
||
setupLibDirs = if isTargetBuild then setupLibDirsTarget | ||
else setupLibDirsMulti; | ||
|
||
# the target profile is the actual profile that will be used for the chroot | ||
setupTargetProfile = '' | ||
mkdir -m0755 usr | ||
cd usr | ||
${setupLibDirs} | ||
for i in bin sbin share include; do | ||
if [ -d "${staticUsrProfileTarget}/$i" ]; then | ||
cp -rsHf "${staticUsrProfileTarget}/$i" "$i" | ||
fi | ||
done | ||
cd .. | ||
for i in var etc; do | ||
if [ -d "${staticUsrProfileTarget}/$i" ]; then | ||
cp -rsHf "${staticUsrProfileTarget}/$i" "$i" | ||
fi | ||
done | ||
for i in usr/{bin,sbin,lib,lib32,lib64}; do | ||
if [ -d "$i" ]; then | ||
ln -s "$i" | ||
fi | ||
done | ||
''; | ||
|
||
in stdenv.mkDerivation { | ||
name = "${name}-fhs"; | ||
buildCommand = '' | ||
mkdir -p $out | ||
cd $out | ||
${setupTargetProfile} | ||
cd $out | ||
${extraBuildCommands} | ||
cd $out | ||
${if isMultiBuild then extraBuildCommandsMulti else ""} | ||
''; | ||
preferLocalBuild = true; | ||
allowSubstitutes = false; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters