1{ localSystem ? { system = builtins.currentSystem; }
2, crossSystem ? null
3}:
4
5let
6 pkgs = import ../../.. { inherit localSystem crossSystem; };
7 libc = pkgs.stdenv.cc.libc;
8in with pkgs; rec {
9
10
11 coreutilsMinimal = coreutils.override (args: {
12 # We want coreutils without ACL/attr support.
13 aclSupport = false;
14 attrSupport = false;
15 # Our tooling currently can't handle scripts in bin/, only ELFs and symlinks.
16 singleBinary = "symlinks";
17 });
18
19 tarMinimal = gnutar.override { acl = null; };
20
21 busyboxMinimal = busybox.override {
22 useMusl = !targetPlatform.isRiscV;
23 enableStatic = true;
24 enableMinimal = true;
25 extraConfig = ''
26 CONFIG_ASH y
27 CONFIG_ASH_ECHO y
28 CONFIG_ASH_TEST y
29 CONFIG_ASH_OPTIMIZE_FOR_SIZE y
30 CONFIG_MKDIR y
31 CONFIG_TAR y
32 CONFIG_UNXZ y
33 '';
34 };
35
36 build =
37
38 stdenv.mkDerivation {
39 name = "stdenv-bootstrap-tools";
40
41 nativeBuildInputs = [ buildPackages.nukeReferences buildPackages.cpio ];
42
43 buildCommand = ''
44 set -x
45 mkdir -p $out/bin $out/lib $out/libexec
46
47 '' + (if (hostPlatform.libc == "glibc") then ''
48 # Copy what we need of Glibc.
49 cp -d ${libc.out}/lib/ld*.so* $out/lib
50 cp -d ${libc.out}/lib/libc*.so* $out/lib
51 cp -d ${libc.out}/lib/libc_nonshared.a $out/lib
52 cp -d ${libc.out}/lib/libm*.so* $out/lib
53 cp -d ${libc.out}/lib/libdl*.so* $out/lib
54 cp -d ${libc.out}/lib/librt*.so* $out/lib
55 cp -d ${libc.out}/lib/libpthread*.so* $out/lib
56 cp -d ${libc.out}/lib/libnsl*.so* $out/lib
57 cp -d ${libc.out}/lib/libutil*.so* $out/lib
58 cp -d ${libc.out}/lib/libnss*.so* $out/lib
59 cp -d ${libc.out}/lib/libresolv*.so* $out/lib
60 cp -d ${libc.out}/lib/crt?.o $out/lib
61
62 cp -rL ${libc.dev}/include $out
63 chmod -R u+w "$out"
64
65 # libc can contain linker scripts: find them, copy their deps,
66 # and get rid of absolute paths (nuke-refs would make them useless)
67 local lScripts=$(grep --files-with-matches --max-count=1 'GNU ld script' -R "$out/lib")
68 cp -d -t "$out/lib/" $(cat $lScripts | tr " " "\n" | grep -F '${libc.out}' | sort -u)
69 for f in $lScripts; do
70 substituteInPlace "$f" --replace '${libc.out}/lib/' ""
71 done
72
73 # Hopefully we won't need these.
74 rm -rf $out/include/mtd $out/include/rdma $out/include/sound $out/include/video
75 find $out/include -name .install -exec rm {} \;
76 find $out/include -name ..install.cmd -exec rm {} \;
77 mv $out/include $out/include-glibc
78 '' else if (hostPlatform.libc == "musl") then ''
79 # Copy what we need from musl
80 cp ${libc.out}/lib/* $out/lib
81 cp -rL ${libc.dev}/include $out
82 chmod -R u+w "$out"
83
84 rm -rf $out/include/mtd $out/include/rdma $out/include/sound $out/include/video
85 find $out/include -name .install -exec rm {} \;
86 find $out/include -name ..install.cmd -exec rm {} \;
87 mv $out/include $out/include-libc
88 '' else throw "unsupported libc for bootstrap tools")
89 + ''
90 # Copy coreutils, bash, etc.
91 cp -d ${coreutilsMinimal.out}/bin/* $out/bin
92 (cd $out/bin && rm vdir dir sha*sum pinky factor pathchk runcon shuf who whoami shred users)
93
94 cp ${bash.out}/bin/bash $out/bin
95 cp ${findutils.out}/bin/find $out/bin
96 cp ${findutils.out}/bin/xargs $out/bin
97 cp -d ${diffutils.out}/bin/* $out/bin
98 cp -d ${gnused.out}/bin/* $out/bin
99 cp -d ${gnugrep.out}/bin/grep $out/bin
100 cp ${gawk.out}/bin/gawk $out/bin
101 cp -d ${gawk.out}/bin/awk $out/bin
102 cp ${tarMinimal.out}/bin/tar $out/bin
103 cp ${gzip.out}/bin/gzip $out/bin
104 cp ${bzip2.bin}/bin/bzip2 $out/bin
105 cp -d ${gnumake.out}/bin/* $out/bin
106 cp -d ${patch}/bin/* $out/bin
107 cp ${patchelf}/bin/* $out/bin
108
109 cp -d ${gnugrep.pcre.out}/lib/libpcre*.so* $out/lib # needed by grep
110
111 # Copy what we need of GCC.
112 cp -d ${gcc.cc.out}/bin/gcc $out/bin
113 cp -d ${gcc.cc.out}/bin/cpp $out/bin
114 cp -d ${gcc.cc.out}/bin/g++ $out/bin
115 cp -d ${gcc.cc.lib}/lib*/libgcc_s.so* $out/lib
116 cp -d ${gcc.cc.lib}/lib*/libstdc++.so* $out/lib
117 cp -rd ${gcc.cc.out}/lib/gcc $out/lib
118 chmod -R u+w $out/lib
119 rm -f $out/lib/gcc/*/*/include*/linux
120 rm -f $out/lib/gcc/*/*/include*/sound
121 rm -rf $out/lib/gcc/*/*/include*/root
122 rm -f $out/lib/gcc/*/*/include-fixed/asm
123 rm -rf $out/lib/gcc/*/*/plugin
124 #rm -f $out/lib/gcc/*/*/*.a
125 cp -rd ${gcc.cc.out}/libexec/* $out/libexec
126 chmod -R u+w $out/libexec
127 rm -rf $out/libexec/gcc/*/*/plugin
128 mkdir -p $out/include
129 cp -rd ${gcc.cc.out}/include/c++ $out/include
130 chmod -R u+w $out/include
131 rm -rf $out/include/c++/*/ext/pb_ds
132 rm -rf $out/include/c++/*/ext/parallel
133
134 cp -d ${gmpxx.out}/lib/libgmp*.so* $out/lib
135 cp -d ${mpfr.out}/lib/libmpfr*.so* $out/lib
136 cp -d ${libmpc.out}/lib/libmpc*.so* $out/lib
137 cp -d ${zlib.out}/lib/libz.so* $out/lib
138 cp -d ${libelf}/lib/libelf.so* $out/lib
139
140 '' + lib.optionalString (hostPlatform != buildPlatform) ''
141 # These needed for cross but not native tools because the stdenv
142 # GCC has certain things built in statically. See
143 # pkgs/stdenv/linux/default.nix for the details.
144 cp -d ${isl_0_17.out}/lib/libisl*.so* $out/lib
145
146 '' + ''
147 cp -d ${bzip2.out}/lib/libbz2.so* $out/lib
148
149 # Copy binutils.
150 for i in as ld ar ranlib nm strip readelf objdump; do
151 cp ${binutils.bintools.out}/bin/$i $out/bin
152 done
153
154 chmod -R u+w $out
155
156 # Strip executables even further.
157 for i in $out/bin/* $out/libexec/gcc/*/*/*; do
158 if test -x $i -a ! -L $i; then
159 chmod +w $i
160 $STRIP -s $i || true
161 fi
162 done
163
164 nuke-refs $out/bin/*
165 nuke-refs $out/lib/*
166 nuke-refs $out/libexec/gcc/*/*/*
167 nuke-refs $out/lib/gcc/*/*/*
168
169 mkdir $out/.pack
170 mv $out/* $out/.pack
171 mv $out/.pack $out/pack
172
173 mkdir $out/on-server
174 XZ_OPT=-9 tar cvJf $out/on-server/bootstrap-tools.tar.xz --hard-dereference --sort=name --numeric-owner --owner=0 --group=0 --mtime=@1 -C $out/pack .
175 cp ${busyboxMinimal}/bin/busybox $out/on-server
176 chmod u+w $out/on-server/busybox
177 nuke-refs $out/on-server/busybox
178 ''; # */
179
180 # The result should not contain any references (store paths) so
181 # that we can safely copy them out of the store and to other
182 # locations in the store.
183 allowedReferences = [];
184 };
185
186 dist = stdenv.mkDerivation {
187 name = "stdenv-bootstrap-tools";
188
189 buildCommand = ''
190 mkdir -p $out/nix-support
191 echo "file tarball ${build}/on-server/bootstrap-tools.tar.xz" >> $out/nix-support/hydra-build-products
192 echo "file busybox ${build}/on-server/busybox" >> $out/nix-support/hydra-build-products
193 '';
194 };
195
196 bootstrapFiles = {
197 # Make them their own store paths to test that busybox still works when the binary is named /nix/store/HASH-busybox
198 busybox = runCommand "busybox" {} "cp ${build}/on-server/busybox $out";
199 bootstrapTools = runCommand "bootstrap-tools.tar.xz" {} "cp ${build}/on-server/bootstrap-tools.tar.xz $out";
200 };
201
202 bootstrapTools = if (hostPlatform.libc == "glibc") then
203 import ./bootstrap-tools {
204 inherit (hostPlatform) system;
205 inherit bootstrapFiles;
206 }
207 else if (hostPlatform.libc == "musl") then
208 import ./bootstrap-tools-musl {
209 inherit (hostPlatform) system;
210 inherit bootstrapFiles;
211 }
212 else throw "unsupported libc";
213
214 test = derivation {
215 name = "test-bootstrap-tools";
216 inherit (hostPlatform) system;
217 builder = bootstrapFiles.busybox;
218 args = [ "ash" "-e" "-c" "eval \"$buildCommand\"" ];
219
220 buildCommand = ''
221 export PATH=${bootstrapTools}/bin
222
223 ls -l
224 mkdir $out
225 mkdir $out/bin
226 sed --version
227 find --version
228 diff --version
229 patch --version
230 make --version
231 awk --version
232 grep --version
233 gcc --version
234
235 '' + lib.optionalString (hostPlatform.libc == "glibc") ''
236 ldlinux=$(echo ${bootstrapTools}/lib/ld-linux*.so.?)
237 export CPP="cpp -idirafter ${bootstrapTools}/include-glibc -B${bootstrapTools}"
238 export CC="gcc -idirafter ${bootstrapTools}/include-glibc -B${bootstrapTools} -Wl,-dynamic-linker,$ldlinux -Wl,-rpath,${bootstrapTools}/lib"
239 export CXX="g++ -idirafter ${bootstrapTools}/include-glibc -B${bootstrapTools} -Wl,-dynamic-linker,$ldlinux -Wl,-rpath,${bootstrapTools}/lib"
240 '' + lib.optionalString (hostPlatform.libc == "musl") ''
241 ldmusl=$(echo ${bootstrapTools}/lib/ld-musl*.so.?)
242 export CPP="cpp -idirafter ${bootstrapTools}/include-libc -B${bootstrapTools}"
243 export CC="gcc -idirafter ${bootstrapTools}/include-libc -B${bootstrapTools} -Wl,-dynamic-linker,$ldmusl -Wl,-rpath,${bootstrapTools}/lib"
244 export CXX="g++ -idirafter ${bootstrapTools}/include-libc -B${bootstrapTools} -Wl,-dynamic-linker,$ldmusl -Wl,-rpath,${bootstrapTools}/lib"
245 '' + ''
246
247 echo '#include <stdio.h>' >> foo.c
248 echo '#include <limits.h>' >> foo.c
249 echo 'int main() { printf("Hello World\\n"); return 0; }' >> foo.c
250 $CC -o $out/bin/foo foo.c
251 $out/bin/foo
252
253 echo '#include <iostream>' >> bar.cc
254 echo 'int main() { std::cout << "Hello World\\n"; }' >> bar.cc
255 $CXX -v -o $out/bin/bar bar.cc
256 $out/bin/bar
257
258 tar xvf ${hello.src}
259 cd hello-*
260 ./configure --prefix=$out
261 make
262 make install
263 '';
264 };
265}