lol
1{ pkgs ? import ../../.. {} }:
2
3let
4 libc = pkgs.stdenv.cc.libc;
5 patchelf = pkgs.patchelf.overrideAttrs(previousAttrs: {
6 NIX_CFLAGS_COMPILE = (previousAttrs.NIX_CFLAGS_COMPILE or []) ++ [ "-static-libgcc" "-static-libstdc++" ];
7 NIX_CFLAGS_LINK = (previousAttrs.NIX_CFLAGS_LINK or []) ++ [ "-static-libgcc" "-static-libstdc++" ];
8 });
9in with pkgs; rec {
10
11
12 coreutilsMinimal = coreutils.override (args: {
13 # We want coreutils without ACL/attr support.
14 aclSupport = false;
15 attrSupport = false;
16 # Our tooling currently can't handle scripts in bin/, only ELFs and symlinks.
17 singleBinary = "symlinks";
18 });
19
20 tarMinimal = gnutar.override { acl = null; };
21
22 busyboxMinimal = busybox.override {
23 useMusl = lib.meta.availableOn stdenv.hostPlatform musl;
24 enableStatic = true;
25 enableMinimal = true;
26 extraConfig = ''
27 CONFIG_ASH y
28 CONFIG_ASH_ECHO y
29 CONFIG_ASH_TEST y
30 CONFIG_ASH_OPTIMIZE_FOR_SIZE y
31 CONFIG_MKDIR y
32 CONFIG_TAR y
33 CONFIG_UNXZ y
34 '';
35 };
36
37 bootGCC = gcc.cc.override { enableLTO = false; };
38 bootBinutils = binutils.bintools.override {
39 withAllTargets = false;
40 # Don't need two linkers, disable whatever's not primary/default.
41 enableGold = false;
42 # bootstrap is easier w/static
43 enableShared = false;
44 };
45
46 build =
47 let
48 # ${libc.src}/sysdeps/unix/sysv/linux/loongarch/lp64/libnsl.abilist does not exist!
49 withLibnsl = !stdenv.hostPlatform.isLoongArch64;
50 in
51 stdenv.mkDerivation {
52 name = "stdenv-bootstrap-tools";
53
54 meta = {
55 # Increase priority to unblock nixpkgs-unstable
56 # https://github.com/NixOS/nixpkgs/pull/104679#issuecomment-732267288
57 schedulingPriority = 200;
58 };
59
60 nativeBuildInputs = [ buildPackages.nukeReferences buildPackages.cpio ];
61
62 buildCommand = ''
63 set -x
64 mkdir -p $out/bin $out/lib $out/libexec
65
66 '' + (if (stdenv.hostPlatform.libc == "glibc") then ''
67 # Copy what we need of Glibc.
68 cp -d ${libc.out}/lib/ld*.so* $out/lib
69 cp -d ${libc.out}/lib/libc*.so* $out/lib
70 cp -d ${libc.out}/lib/libc_nonshared.a $out/lib
71 cp -d ${libc.out}/lib/libm*.so* $out/lib
72 cp -d ${libc.out}/lib/libdl*.so* $out/lib
73 cp -d ${libc.out}/lib/librt*.so* $out/lib
74 cp -d ${libc.out}/lib/libpthread*.so* $out/lib
75 '' + lib.optionalString withLibnsl ''
76 cp -d ${libc.out}/lib/libnsl*.so* $out/lib
77 '' + ''
78 cp -d ${libc.out}/lib/libutil*.so* $out/lib
79 cp -d ${libc.out}/lib/libnss*.so* $out/lib
80 cp -d ${libc.out}/lib/libresolv*.so* $out/lib
81 # Copy all runtime files to enable non-PIE, PIE, static PIE and profile-generated builds
82 cp -d ${libc.out}/lib/*.o $out/lib
83
84 # Hacky compat with our current unpack-bootstrap-tools.sh
85 ln -s librt.so "$out"/lib/librt-dummy.so
86
87 cp -rL ${libc.dev}/include $out
88 chmod -R u+w "$out"
89
90 # libc can contain linker scripts: find them, copy their deps,
91 # and get rid of absolute paths (nuke-refs would make them useless)
92 local lScripts=$(grep --files-with-matches --max-count=1 'GNU ld script' -R "$out/lib")
93 cp -d -t "$out/lib/" $(cat $lScripts | tr " " "\n" | grep -F '${libc.out}' | sort -u)
94 for f in $lScripts; do
95 substituteInPlace "$f" --replace '${libc.out}/lib/' ""
96 done
97
98 # Hopefully we won't need these.
99 rm -rf $out/include/mtd $out/include/rdma $out/include/sound $out/include/video
100 find $out/include -name .install -exec rm {} \;
101 find $out/include -name ..install.cmd -exec rm {} \;
102 mv $out/include $out/include-glibc
103 '' else if (stdenv.hostPlatform.libc == "musl") then ''
104 # Copy what we need from musl
105 cp ${libc.out}/lib/* $out/lib
106 cp -rL ${libc.dev}/include $out
107 chmod -R u+w "$out"
108
109 rm -rf $out/include/mtd $out/include/rdma $out/include/sound $out/include/video
110 find $out/include -name .install -exec rm {} \;
111 find $out/include -name ..install.cmd -exec rm {} \;
112 mv $out/include $out/include-libc
113 '' else throw "unsupported libc for bootstrap tools")
114 + ''
115 # Copy coreutils, bash, etc.
116 cp -d ${coreutilsMinimal.out}/bin/* $out/bin
117 (cd $out/bin && rm vdir dir sha*sum pinky factor pathchk runcon shuf who whoami shred users)
118
119 cp ${bash.out}/bin/bash $out/bin
120 cp ${findutils.out}/bin/find $out/bin
121 cp ${findutils.out}/bin/xargs $out/bin
122 cp -d ${diffutils.out}/bin/* $out/bin
123 cp -d ${gnused.out}/bin/* $out/bin
124 cp -d ${gnugrep.out}/bin/grep $out/bin
125 cp ${gawk.out}/bin/gawk $out/bin
126 cp -d ${gawk.out}/bin/awk $out/bin
127 cp ${tarMinimal.out}/bin/tar $out/bin
128 cp ${gzip.out}/bin/.gzip-wrapped $out/bin/gzip
129 cp ${bzip2.bin}/bin/bzip2 $out/bin
130 cp -d ${gnumake.out}/bin/* $out/bin
131 cp -d ${patch}/bin/* $out/bin
132 cp ${patchelf}/bin/* $out/bin
133
134 cp -d ${gnugrep.pcre2.out}/lib/libpcre2*.so* $out/lib # needed by grep
135
136 # Copy what we need of GCC.
137 cp -d ${bootGCC.out}/bin/gcc $out/bin
138 cp -d ${bootGCC.out}/bin/cpp $out/bin
139 cp -d ${bootGCC.out}/bin/g++ $out/bin
140 cp ${bootGCC.lib}/lib/libgcc_s.so* $out/lib
141 cp -d ${bootGCC.lib}/lib/libstdc++.so* $out/lib
142 cp -d ${bootGCC.out}/lib/libssp.a* $out/lib
143 cp -d ${bootGCC.out}/lib/libssp_nonshared.a $out/lib
144 cp -rd ${bootGCC.out}/lib/gcc $out/lib
145 chmod -R u+w $out/lib
146 rm -f $out/lib/gcc/*/*/include*/linux
147 rm -f $out/lib/gcc/*/*/include*/sound
148 rm -rf $out/lib/gcc/*/*/include*/root
149 rm -f $out/lib/gcc/*/*/include-fixed/asm
150 rm -rf $out/lib/gcc/*/*/plugin
151 #rm -f $out/lib/gcc/*/*/*.a
152 cp -rd ${bootGCC.out}/libexec/* $out/libexec
153 chmod -R u+w $out/libexec
154 rm -rf $out/libexec/gcc/*/*/plugin
155 mkdir -p $out/include
156 cp -rd ${bootGCC.out}/include/c++ $out/include
157 chmod -R u+w $out/include
158 rm -rf $out/include/c++/*/ext/pb_ds
159 rm -rf $out/include/c++/*/ext/parallel
160
161 cp -d ${gmpxx.out}/lib/libgmp*.so* $out/lib
162 cp -d ${isl.out}/lib/libisl*.so* $out/lib
163 cp -d ${mpfr.out}/lib/libmpfr*.so* $out/lib
164 cp -d ${libmpc.out}/lib/libmpc*.so* $out/lib
165 cp -d ${zlib.out}/lib/libz.so* $out/lib
166
167 '' + lib.optionalString (stdenv.hostPlatform.isRiscV) ''
168 # libatomic is required on RiscV platform for C/C++ atomics and pthread
169 # even though they may be translated into native instructions.
170 cp -d ${bootGCC.out}/lib/libatomic.a* $out/lib
171
172 '' + ''
173 cp -d ${bzip2.out}/lib/libbz2.so* $out/lib
174
175 # Copy binutils.
176 for i in as ld ar ranlib nm strip readelf objdump; do
177 cp ${bootBinutils.out}/bin/$i $out/bin
178 done
179 cp -r '${lib.getLib binutils.bintools}'/lib/* "$out/lib/"
180
181 chmod -R u+w $out
182
183 # Strip executables even further.
184 for i in $out/bin/* $out/libexec/gcc/*/*/*; do
185 if test -x $i -a ! -L $i; then
186 chmod +w $i
187 $STRIP -s $i || true
188 fi
189 done
190
191 nuke-refs $out/bin/*
192 nuke-refs $out/lib/*
193 nuke-refs $out/lib/*/*
194 nuke-refs $out/libexec/gcc/*/*/*
195 nuke-refs $out/lib/gcc/*/*/*
196 nuke-refs $out/lib/gcc/*/*/include-fixed/*{,/*}
197
198 mkdir $out/.pack
199 mv $out/* $out/.pack
200 mv $out/.pack $out/pack
201
202 mkdir $out/on-server
203 XZ_OPT="-9 -e" tar cvJf $out/on-server/bootstrap-tools.tar.xz --hard-dereference --sort=name --numeric-owner --owner=0 --group=0 --mtime=@1 -C $out/pack .
204 cp ${busyboxMinimal}/bin/busybox $out/on-server
205 chmod u+w $out/on-server/busybox
206 nuke-refs $out/on-server/busybox
207 ''; # */
208
209 # The result should not contain any references (store paths) so
210 # that we can safely copy them out of the store and to other
211 # locations in the store.
212 allowedReferences = [];
213 };
214
215 dist = stdenv.mkDerivation {
216 name = "stdenv-bootstrap-tools";
217
218 meta = {
219 # Increase priority to unblock nixpkgs-unstable
220 # https://github.com/NixOS/nixpkgs/pull/104679#issuecomment-732267288
221 schedulingPriority = 200;
222 };
223
224 buildCommand = ''
225 mkdir -p $out/nix-support
226 echo "file tarball ${build}/on-server/bootstrap-tools.tar.xz" >> $out/nix-support/hydra-build-products
227 echo "file busybox ${build}/on-server/busybox" >> $out/nix-support/hydra-build-products
228 '';
229 };
230
231 bootstrapFiles = {
232 # Make them their own store paths to test that busybox still works when the binary is named /nix/store/HASH-busybox
233 busybox = runCommand "busybox" {} "cp ${build}/on-server/busybox $out";
234 bootstrapTools = runCommand "bootstrap-tools.tar.xz" {} "cp ${build}/on-server/bootstrap-tools.tar.xz $out";
235 };
236
237 bootstrapTools =
238 let extraAttrs = lib.optionalAttrs
239 config.contentAddressedByDefault
240 {
241 __contentAddressed = true;
242 outputHashAlgo = "sha256";
243 outputHashMode = "recursive";
244 };
245 in
246 if (stdenv.hostPlatform.libc == "glibc") then
247 import ./bootstrap-tools {
248 inherit (stdenv.buildPlatform) system; # Used to determine where to build
249 inherit bootstrapFiles extraAttrs;
250 }
251 else if (stdenv.hostPlatform.libc == "musl") then
252 import ./bootstrap-tools-musl {
253 inherit (stdenv.buildPlatform) system; # Used to determine where to build
254 inherit bootstrapFiles extraAttrs;
255 }
256 else throw "unsupported libc";
257
258 test = derivation {
259 name = "test-bootstrap-tools";
260 inherit (stdenv.hostPlatform) system; # We cannot "cross test"
261 builder = bootstrapFiles.busybox;
262 args = [ "ash" "-e" "-c" "eval \"$buildCommand\"" ];
263
264 buildCommand = ''
265 export PATH=${bootstrapTools}/bin
266
267 ls -l
268 mkdir $out
269 mkdir $out/bin
270 sed --version
271 find --version
272 diff --version
273 patch --version
274 make --version
275 awk --version
276 grep --version
277 gcc --version
278
279 '' + lib.optionalString (stdenv.hostPlatform.libc == "glibc") ''
280 rtld=$(echo ${bootstrapTools}/lib/${builtins.unsafeDiscardStringContext /* only basename */ (builtins.baseNameOf binutils.dynamicLinker)})
281 libc_includes=${bootstrapTools}/include-glibc
282 '' + lib.optionalString (stdenv.hostPlatform.libc == "musl") ''
283 rtld=$(echo ${bootstrapTools}/lib/ld-musl*.so.?)
284 libc_includes=${bootstrapTools}/include-libc
285 '' + ''
286 # path to version-specific libraries, like libstdc++.so
287 cxx_libs=$(echo ${bootstrapTools}/lib/gcc/*/*)
288 export CPP="cpp -idirafter $libc_includes -B${bootstrapTools}"
289 export CC="gcc -idirafter $libc_includes -B${bootstrapTools} -Wl,-dynamic-linker,$rtld -Wl,-rpath,${bootstrapTools}/lib -Wl,-rpath,$cxx_libs"
290 export CXX="g++ -idirafter $libc_includes -B${bootstrapTools} -Wl,-dynamic-linker,$rtld -Wl,-rpath,${bootstrapTools}/lib -Wl,-rpath,$cxx_libs"
291
292 echo '#include <stdio.h>' >> foo.c
293 echo '#include <limits.h>' >> foo.c
294 echo 'int main() { printf("Hello World\\n"); return 0; }' >> foo.c
295 $CC -o $out/bin/foo foo.c
296 $out/bin/foo
297
298 echo '#include <iostream>' >> bar.cc
299 echo 'int main() { std::cout << "Hello World\\n"; }' >> bar.cc
300 $CXX -v -o $out/bin/bar bar.cc
301 $out/bin/bar
302
303 tar xvf ${hello.src}
304 cd hello-*
305 ./configure --prefix=$out
306 make
307 make install
308 '';
309 };
310}