Merge pull request #94442 from Atemu/buildFHSUserEnvBw

This commit is contained in:
Jörg Thalheim 2020-08-19 17:28:02 +01:00 committed by GitHub
commit bd0e645f02
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 309 additions and 8 deletions

View File

@ -1,4 +1,4 @@
{ callPackage, makeFontsConf, gnome2 }:
{ callPackage, makeFontsConf, gnome2, buildFHSUserEnv }:
let
mkStudio = opts: callPackage (import ./common.nix opts) {
@ -6,6 +6,7 @@ let
fontDirectories = [];
};
inherit (gnome2) GConf gnome_vfs;
inherit buildFHSUserEnv;
};
stableVersion = {
version = "4.0.1.0"; # "Android Studio 4.0.1"

View File

@ -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}
''

View File

@ -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;
}

View File

@ -1,4 +1,4 @@
{ pkgs, newScope }:
{ pkgs, newScope, buildFHSUserEnv }:
let
callPackage = newScope self;
@ -12,12 +12,13 @@ let
steam-runtime-wrapped = callPackage ./runtime-wrapped.nix { };
steam = callPackage ./steam.nix { };
steam-fonts = callPackage ./fonts.nix { };
steam-chrootenv = callPackage ./chrootenv.nix {
steam-fhsenv = callPackage ./fhsenv.nix {
glxinfo-i686 = pkgs.pkgsi686Linux.glxinfo;
steam-runtime-wrapped-i686 =
if steamArch == "amd64"
then pkgs.pkgsi686Linux.steamPackages.steam-runtime-wrapped
else null;
inherit buildFHSUserEnv;
};
steamcmd = callPackage ./steamcmd.nix { };
};

View File

@ -155,7 +155,10 @@ in
buildEnv = callPackage ../build-support/buildenv { }; # not actually a package
buildFHSUserEnv = callPackage ../build-support/build-fhs-userenv { };
# TODO: eventually migrate everything to buildFHSUserEnvBubblewrap
buildFHSUserEnv = buildFHSUserEnvChroot;
buildFHSUserEnvChroot = callPackage ../build-support/build-fhs-userenv { };
buildFHSUserEnvBubblewrap = callPackage ../build-support/build-fhs-userenv-bubblewrap { };
buildMaven = callPackage ../build-support/build-maven.nix {};
@ -19197,7 +19200,9 @@ in
amsn = callPackage ../applications/networking/instant-messengers/amsn { };
androidStudioPackages = recurseIntoAttrs
(callPackage ../applications/editors/android-studio { });
(callPackage ../applications/editors/android-studio {
buildFHSUserEnv = buildFHSUserEnvBubblewrap;
});
android-studio = androidStudioPackages.stable;
animbar = callPackage ../applications/graphics/animbar { };
@ -21343,7 +21348,9 @@ in
inherit (gnome3) gnome-desktop libgnome-keyring;
wine = wineWowPackages.staging;
};
lutris = callPackage ../applications/misc/lutris/chrootenv.nix { };
lutris = callPackage ../applications/misc/lutris/fhsenv.nix {
buildFHSUserEnv = buildFHSUserEnvBubblewrap;
};
lutris-free = lutris.override {
steamSupport = false;
};
@ -24796,9 +24803,11 @@ in
stockfish = callPackage ../games/stockfish { };
steamPackages = dontRecurseIntoAttrs (callPackage ../games/steam { });
steamPackages = dontRecurseIntoAttrs (callPackage ../games/steam {
buildFHSUserEnv = buildFHSUserEnvBubblewrap;
});
steam = steamPackages.steam-chrootenv;
steam = steamPackages.steam-fhsenv;
steam-run = steam.run;
steam-run-native = (steam.override {