waagent: 2.11.1.12 -> 2.12.0.2 (#357728)
[NixPkgs.git] / pkgs / build-support / build-fhsenv-bubblewrap / buildFHSEnv.nix
blobdc8ee68e8783fca368f1d144cd449628e49c284e
1 { lib
2 , stdenv
3 , runCommandLocal
4 , buildEnv
5 , writeText
6 , writeShellScriptBin
7 , pkgs
8 , pkgsi686Linux
9 }:
11 { profile ? ""
12 , targetPkgs ? pkgs: []
13 , multiPkgs ? pkgs: []
14 , multiArch ? false # Whether to include 32bit packages
15 , includeClosures ? false # Whether to include closures of all packages
16 , nativeBuildInputs ? []
17 , extraBuildCommands ? ""
18 , extraBuildCommandsMulti ? ""
19 , extraOutputsToInstall ? []
20 , ... # for name, or pname+version
21 } @ args:
23 # HOWTO:
24 # All packages (most likely programs) returned from targetPkgs will only be
25 # installed once--matching the host's architecture (64bit on x86_64 and 32bit on
26 # x86).
28 # Packages (most likely libraries) returned from multiPkgs are installed
29 # once on x86 systems and twice on x86_64 systems.
30 # On x86 they are merged with packages from targetPkgs.
31 # On x86_64 they are added to targetPkgs and in addition their 32bit
32 # versions are also installed. The final directory structure looks as
33 # follows:
34 # /lib32 will include 32bit libraries from multiPkgs
35 # /lib64 will include 64bit libraries from multiPkgs and targetPkgs
36 # /lib will link to /lib64
38 let
39   name = if (args ? pname && args ? version)
40     then "${args.pname}-${args.version}"
41     else args.name;
43   # "use of glibc_multi is only supported on x86_64-linux"
44   isMultiBuild = multiArch && stdenv.system == "x86_64-linux";
46   # list of packages (usually programs) which match the host's architecture
47   # (which includes stuff from multiPkgs)
48   targetPaths = targetPkgs pkgs ++ (if multiPkgs == null then [] else multiPkgs pkgs);
50   # list of packages which are for x86 (only multiPkgs, only for x86_64 hosts)
51   multiPaths = multiPkgs pkgsi686Linux;
53   # base packages of the fhsenv
54   # these match the host's architecture, glibc_multi is used for multilib
55   # builds. glibcLocales must be before glibc or glibc_multi as otherwiese
56   # the wrong LOCALE_ARCHIVE will be used where only C.UTF-8 is available.
57   baseTargetPaths = with pkgs; [
58     glibcLocales
59     (if isMultiBuild then glibc_multi else glibc)
60     gcc.cc.lib
61     bashInteractiveFHS
62     coreutils
63     less
64     shadow
65     su
66     gawk
67     diffutils
68     findutils
69     gnused
70     gnugrep
71     gnutar
72     gzip
73     bzip2
74     xz
75   ];
76   baseMultiPaths = with pkgsi686Linux; [
77     gcc.cc.lib
78   ];
80   ldconfig = writeShellScriptBin "ldconfig" ''
81     # due to a glibc bug, 64-bit ldconfig complains about patchelf'd 32-bit libraries, so we use 32-bit ldconfig when we have them
82     exec ${if isMultiBuild then pkgsi686Linux.glibc.bin else pkgs.glibc.bin}/bin/ldconfig -f /etc/ld.so.conf -C /etc/ld.so.cache "$@"
83   '';
85   etcProfile = pkgs.writeTextFile {
86     name = "${name}-fhsenv-profile";
87     destination = "/etc/profile";
88     text = ''
89       export PS1='${name}-fhsenv:\u@\h:\w\$ '
90       export LOCALE_ARCHIVE="''${LOCALE_ARCHIVE:-/usr/lib/locale/locale-archive}"
91       export PATH="/run/wrappers/bin:/usr/bin:/usr/sbin:$PATH"
92       export TZDIR='/etc/zoneinfo'
94       # XDG_DATA_DIRS is used by pressure-vessel (steam proton) and vulkan loaders to find the corresponding icd
95       export XDG_DATA_DIRS=$XDG_DATA_DIRS''${XDG_DATA_DIRS:+:}/run/opengl-driver/share:/run/opengl-driver-32/share
97       # Following XDG spec [1], XDG_DATA_DIRS should default to "/usr/local/share:/usr/share".
98       # In nix, it is commonly set without containing these values, so we add them as fallback.
99       #
100       # [1] <https://specifications.freedesktop.org/basedir-spec/latest>
101       case ":$XDG_DATA_DIRS:" in
102         *:/usr/local/share:*) ;;
103         *) export XDG_DATA_DIRS="$XDG_DATA_DIRS''${XDG_DATA_DIRS:+:}/usr/local/share" ;;
104       esac
105       case ":$XDG_DATA_DIRS:" in
106         *:/usr/share:*) ;;
107         *) export XDG_DATA_DIRS="$XDG_DATA_DIRS''${XDG_DATA_DIRS:+:}/usr/share" ;;
108       esac
110       # Force compilers and other tools to look in default search paths
111       unset NIX_ENFORCE_PURITY
112       export NIX_BINTOOLS_WRAPPER_TARGET_HOST_${stdenv.cc.suffixSalt}=1
113       export NIX_CC_WRAPPER_TARGET_HOST_${stdenv.cc.suffixSalt}=1
114       export NIX_CFLAGS_COMPILE='-idirafter /usr/include'
115       export NIX_CFLAGS_LINK='-L/usr/lib -L/usr/lib32'
116       export NIX_LDFLAGS='-L/usr/lib -L/usr/lib32'
117       export PKG_CONFIG_PATH=/usr/lib/pkgconfig
118       export ACLOCAL_PATH=/usr/share/aclocal
120       # GStreamer searches for plugins relative to its real binary's location
121       # https://gitlab.freedesktop.org/gstreamer/gstreamer/-/commit/bd97973ce0f2c5495bcda5cccd4f7ef7dcb7febc
122       export GST_PLUGIN_SYSTEM_PATH_1_0=/usr/lib/gstreamer-1.0:/usr/lib32/gstreamer-1.0
124       ${profile}
125     '';
126   };
128   ensureGsettingsSchemasIsDirectory = runCommandLocal "fhsenv-ensure-gsettings-schemas-directory" {} ''
129     mkdir -p $out/share/glib-2.0/schemas
130     touch $out/share/glib-2.0/schemas/.keep
131   '';
133   # Shamelessly stolen (and cleaned up) from original buildEnv.
134   # Should be semantically equivalent, except we also take
135   # a list of default extra outputs that will be installed
136   # for derivations that don't explicitly specify one.
137   # Note that this is not the same as `extraOutputsToInstall`,
138   # as that will apply even to derivations with an output
139   # explicitly specified, so this does change the behavior
140   # very slightly for that particular edge case.
141   pickOutputs = let
142     pickOutputsOne = outputs: drv:
143       let
144         isSpecifiedOutput = drv.outputSpecified or false;
145         outputsToInstall = drv.meta.outputsToInstall or null;
146         pickedOutputs = if isSpecifiedOutput || outputsToInstall == null
147           then [ drv ]
148           else map (out: drv.${out} or null) (outputsToInstall ++ outputs);
149         extraOutputs = map (out: drv.${out} or null) extraOutputsToInstall;
150         cleanOutputs = lib.filter (o: o != null) (pickedOutputs ++ extraOutputs);
151       in {
152         paths = cleanOutputs;
153         priority = drv.meta.priority or lib.meta.defaultPriority;
154       };
155   in paths: outputs: map (pickOutputsOne outputs) paths;
157   paths = let
158     basePaths = [
159       etcProfile
160       # ldconfig wrapper must come first so it overrides the original ldconfig
161       ldconfig
162       # magic package that just creates a directory, to ensure that
163       # the entire directory can't be a symlink, as we will write
164       # compiled schemas to it
165       ensureGsettingsSchemasIsDirectory
166     ] ++ baseTargetPaths ++ targetPaths;
167   in pickOutputs basePaths ["out" "lib" "bin"];
169   paths32 = lib.optionals isMultiBuild (
170     let
171       basePaths = baseMultiPaths ++ multiPaths;
172     in pickOutputs basePaths ["out" "lib"]
173   );
175   allPaths = paths ++ paths32;
177   rootfs-builder = pkgs.rustPlatform.buildRustPackage {
178     name = "fhs-rootfs-bulder";
179     src = ./rootfs-builder;
180     cargoLock.lockFile = ./rootfs-builder/Cargo.lock;
181     doCheck = false;
182   };
184   rootfs = pkgs.runCommand "${name}-fhsenv-rootfs" {
185     __structuredAttrs = true;
186     exportReferencesGraph.graph = lib.concatMap (p: p.paths) allPaths;
187     inherit paths paths32 isMultiBuild includeClosures;
188     nativeBuildInputs = [ pkgs.jq ];
189   } ''
190     ${rootfs-builder}/bin/rootfs-builder
192     # create a bunch of symlinks for usrmerge
193     ln -s /usr/bin $out/bin
194     ln -s /usr/sbin $out/sbin
195     ln -s /usr/lib $out/lib
196     ln -s /usr/lib32 $out/lib32
197     ln -s /usr/lib64 $out/lib64
198     ln -s /usr/lib64 $out/usr/lib
200     # symlink 32-bit ld-linux so it's visible in /lib
201     if [ -e $out/usr/lib32/ld-linux.so.2 ]; then
202       ln -s /usr/lib32/ld-linux.so.2 $out/usr/lib64/ld-linux.so.2
203     fi
205     # symlink /etc/mtab -> /proc/mounts (compat for old userspace progs)
206     ln -s /proc/mounts $out/etc/mtab
208     if [[ -d $out/usr/share/gsettings-schemas/ ]]; then
209       for d in $out/usr/share/gsettings-schemas/*; do
210         # Force symlink, in case there are duplicates
211         ln -fsr $d/glib-2.0/schemas/*.xml $out/usr/share/glib-2.0/schemas
212         ln -fsr $d/glib-2.0/schemas/*.gschema.override $out/usr/share/glib-2.0/schemas
213       done
214       ${pkgs.glib.dev}/bin/glib-compile-schemas $out/usr/share/glib-2.0/schemas
215     fi
217     ${extraBuildCommands}
218     ${lib.optionalString isMultiBuild extraBuildCommandsMulti}
219   '';
220 in rootfs