lol
1#!/usr/bin/env nix-shell
2#!nix-shell --pure --keep NIX_PATH -i perl -p cacert nix perl
3
4# Usage: manually update tarballs.list then run: ./generate-expr-from-tarballs.pl tarballs.list
5
6use strict;
7use warnings;
8
9use File::Basename;
10use File::Spec::Functions;
11use File::Temp;
12
13
14my %pkgURLs;
15my %pkgHashes;
16my %pkgNames;
17my %pkgVersions;
18my %pkgRequires;
19my %pkgNativeRequires;
20
21my %pcProvides;
22my %pcMap;
23
24my %extraAttrs;
25
26
27my @missingPCs = ("fontconfig", "libdrm", "libXaw", "zlib", "perl", "python3", "mkfontscale", "bdftopcf", "libxslt", "openssl", "gperf", "m4", "libinput", "libevdev", "mtdev", "xorgproto", "cairo", "gettext", "meson", "ninja", "wrapWithXFileSearchPathHook" );
28$pcMap{$_} = $_ foreach @missingPCs;
29$pcMap{"freetype2"} = "freetype";
30$pcMap{"libpng12"} = "libpng";
31$pcMap{"libpng"} = "libpng";
32$pcMap{"dbus-1"} = "dbus";
33$pcMap{"uuid"} = "libuuid";
34$pcMap{"libudev"} = "udev";
35$pcMap{"gl"} = "libGL";
36$pcMap{"GL"} = "libGL";
37$pcMap{"gbm"} = "libgbm";
38$pcMap{"hwdata"} = "hwdata";
39$pcMap{"dmx"} = "libdmx";
40$pcMap{"fontenc"} = "libfontenc";
41$pcMap{"fontutil"} = "fontutil";
42$pcMap{"ice"} = "libICE";
43$pcMap{"libfs"} = "libFS";
44$pcMap{"pciaccess"} = "libpciaccess";
45$pcMap{"pthread-stubs"} = "libpthreadstubs";
46$pcMap{"sm"} = "libSM";
47$pcMap{"x11"} = "libX11";
48$pcMap{"x11-xcb"} = "libX11";
49$pcMap{"xau"} = "libXau";
50$pcMap{"xaw6"} = "libXaw";
51$pcMap{"xaw7"} = "libXaw";
52$pcMap{"xbitmaps"} = "xbitmaps";
53$pcMap{"xcb-atom"} = "xcbutil";
54$pcMap{"xcb-aux"} = "xcbutil";
55$pcMap{"xcb-errors"} = "xcbutilerrors";
56$pcMap{"xcb-event"} = "xcbutil";
57$pcMap{"xcb-ewmh"} = "xcbutilwm";
58$pcMap{"xcb-icccm"} = "xcbutilwm";
59$pcMap{"xcb-image"} = "xcbutilimage";
60$pcMap{"xcb-keysyms"} = "xcbutilkeysyms";
61$pcMap{"xcb-proto"} = "xcbproto";
62$pcMap{"xcb-renderutil"} = "xcbutilrenderutil";
63$pcMap{"xcb-util"} = "xcbutil";
64$pcMap{"xcursor"} = "libXcursor";
65$pcMap{"xdmcp"} = "libXdmcp";
66$pcMap{"xext"} = "libXext";
67$pcMap{"xfixes"} = "libXfixes";
68$pcMap{"xmu"} = "libXmu";
69$pcMap{"xmuu"} = "libXmu";
70$pcMap{"xpm"} = "libXpm";
71$pcMap{"xrandr"} = "libXrandr";
72$pcMap{"xrender"} = "libXrender";
73$pcMap{"xt"} = "libXt";
74$pcMap{"xtrans"} = "xtrans";
75$pcMap{"xv"} = "libXv";
76$pcMap{"xvmc"} = "libXvMC";
77$pcMap{"xvmc-wrapper"} = "libXvMC";
78$pcMap{"xxf86dga"} = "libXxf86dga";
79$pcMap{"xxf86misc"} = "libXxf86misc";
80$pcMap{"xxf86vm"} = "libXxf86vm";
81$pcMap{"\$PIXMAN"} = "pixman";
82$pcMap{"\$RENDERPROTO"} = "xorgproto";
83$pcMap{"\$DRI3PROTO"} = "xorgproto";
84$pcMap{"\$DRI2PROTO"} = "xorgproto";
85$pcMap{"\${XKBMODULE}"} = "libxkbfile";
86foreach my $mod ("xcb", "xcb-composite", "xcb-damage", "xcb-dpms", "xcb-dri2", "xcb-dri3",
87 "xcb-glx", "xcb-present", "xcb-randr", "xcb-record", "xcb-render", "xcb-res", "xcb-screensaver",
88 "xcb-shape", "xcb-shm", "xcb-sync", "xcb-xf86dri", "xcb-xfixes", "xcb-xinerama", "xcb-xinput",
89 "xcb-xkb", "xcb-xtest", "xcb-xv", "xcb-xvmc") {
90 $pcMap{$mod} = "libxcb";
91}
92foreach my $mod ("applewmproto", "bigreqsproto", "compositeproto", "damageproto", "dmxproto",
93 "dpmsproto", "dri2proto", "dri3proto", "evieproto", "fixesproto", "fontcacheproto",
94 "fontsproto", "glproto", "inputproto", "kbproto", "lg3dproto", "presentproto",
95 "printproto", "randrproto", "recordproto", "renderproto", "resourceproto", "scrnsaverproto",
96 "trapproto", "videoproto", "windowswmproto", "xcalibrateproto", "xcmiscproto", "xextproto",
97 "xf86bigfontproto", "xf86dgaproto", "xf86driproto", "xf86miscproto", "xf86rushproto",
98 "xf86vidmodeproto", "xineramaproto", "xproto", "xproxymngproto", "xwaylandproto") {
99 $pcMap{$mod} = "xorgproto";
100}
101
102
103my $downloadCache = "./download-cache";
104mkdir $downloadCache, 0755;
105
106
107while (<>) {
108 chomp;
109 my $tarball = "$_";
110 print "\nDOING TARBALL $tarball\n";
111
112 my $pkg;
113 if ($tarball =~ s/:([a-zA-Z0-9_]+)$//) {
114 $pkg = $1;
115 } else {
116 $tarball =~ /\/((?:(?:[A-Za-z0-9]|(?:-[^0-9])|(?:-[0-9]*[a-z]))+))[^\/]*$/;
117 die unless defined $1;
118 $pkg = $1;
119 $pkg =~ s/(-|[a-f0-9]{40})//g; # Remove hyphen-minus and SHA-1
120 #next unless $pkg eq "xcbutil";
121 }
122
123 $tarball =~ /\/([^\/]*)\.(tar\.(bz2|gz|xz)|tgz)$/;
124 my $pkgName = $1;
125
126 print " $pkg $pkgName\n";
127
128 if (defined $pkgNames{$pkg}) {
129 print " SKIPPING\n";
130 next;
131 }
132
133 # Split by first occurrence of hyphen followed by only numbers, ends line, another hyphen follows, or SHA-1
134 my ($name, $version) = split(/-(?=[.0-9]+(?:$|-)|[a-f0-9]{40})/, $pkgName, 2);
135
136 $pkgURLs{$pkg} = $tarball;
137 $pkgNames{$pkg} = $name;
138 $pkgVersions{$pkg} = $version;
139
140 my $cachePath = catdir($downloadCache, basename($tarball));
141 my $hash;
142 my $path;
143 if (-e $cachePath) {
144 $path = readlink($cachePath);
145 $hash = `nix-hash --type sha256 --base32 --flat $cachePath`;
146 }
147 else {
148 ($hash, $path) = `PRINT_PATH=1 QUIET=1 nix-prefetch-url '$tarball'`;
149 `nix-store --realise --add-root $cachePath --indirect $path`;
150 }
151 chomp $hash;
152 chomp $path;
153 $pkgHashes{$pkg} = $hash;
154
155 print "\nunpacking $path\n";
156 my $tmpDir = File::Temp->newdir();
157 system "cd '$tmpDir' && tar xf '$path'";
158 die "cannot unpack `$path'" if $? != 0;
159 print "\n";
160
161 my $pkgDir = `echo $tmpDir/*`;
162 chomp $pkgDir;
163
164 my $provides = `find $pkgDir -name "*.pc.in"`;
165 my @provides2 = split '\n', $provides;
166 my @requires = ();
167 my @nativeRequires = ();
168
169 foreach my $pcFile (@provides2) {
170 my $pc = $pcFile;
171 $pc =~ s/.*\///;
172 $pc =~ s/.pc.in//;
173 push @{$pcProvides{$pkg}}, $pc;
174 print "PROVIDES $pc\n";
175 die "collision with $pcMap{$pc}" if defined $pcMap{$pc};
176 $pcMap{$pc} = $pkg;
177
178 open FOO, "<$pcFile" or die;
179 while (<FOO>) {
180 if (/Requires:(.*)/) {
181 my @reqs = split ' ', $1;
182 foreach my $req (@reqs) {
183 next unless $req =~ /^[a-z]+$/;
184 print "REQUIRE (from $pc): $req\n";
185 push @requires, $req;
186 }
187 }
188 }
189 close FOO;
190
191 }
192
193 my $file;
194 {
195 local $/;
196 open FOO, "cd '$tmpDir'/* && grep -v '^ *#' configure.ac |";
197 $file = <FOO>;
198 close FOO;
199 }
200
201 if ($file =~ /XAW_CHECK_XPRINT_SUPPORT/) {
202 push @requires, "libXaw";
203 }
204
205 if ($file =~ /zlib is required/ || $file =~ /AC_CHECK_LIB\(z\,/) {
206 push @requires, "zlib";
207 }
208
209 if ($file =~ /Perl is required/) {
210 push @requires, "perl";
211 }
212
213 if ($file =~ /AC_PATH_PROG\(BDFTOPCF/) {
214 push @nativeRequires, "bdftopcf";
215 }
216
217 if ($file =~ /AC_PATH_PROG\(MKFONTSCALE/ || $file =~ /XORG_FONT_REQUIRED_PROG\(MKFONTSCALE/) {
218 push @nativeRequires, "mkfontscale";
219 }
220
221 if ($file =~ /AC_PATH_PROG\(MKFONTDIR/) {
222 push @nativeRequires, "mkfontscale";
223 }
224
225 if ($file =~ /AM_PATH_PYTHON/) {
226 push @nativeRequires, "python3";
227 }
228
229 if ($file =~ /AC_PATH_PROG\(FCCACHE/) {
230 # Don't run fc-cache.
231 die if defined $extraAttrs{$pkg};
232 push @{$extraAttrs{$pkg}}, "preInstall = \"installFlags=(FCCACHE=true)\";";
233 }
234
235 my $isFont;
236
237 if ($file =~ /XORG_FONT_BDF_UTILS/) {
238 push @nativeRequires, "bdftopcf", "mkfontscale";
239 $isFont = 1;
240 }
241
242 if ($file =~ /XORG_FONT_SCALED_UTILS/) {
243 push @nativeRequires, "mkfontscale";
244 $isFont = 1;
245 }
246
247 if ($file =~ /XORG_FONT_UCS2ANY/) {
248 push @nativeRequires, "fontutil", "mkfontscale";
249 $isFont = 1;
250 }
251
252 if ($isFont) {
253 push @requires, "fontutil";
254 push @{$extraAttrs{$pkg}}, "configureFlags = [ \"--with-fontrootdir=\$(out)/lib/X11/fonts\" ];";
255 push @{$extraAttrs{$pkg}}, "postPatch = ''substituteInPlace configure --replace 'MAPFILES_PATH=`pkg-config' 'MAPFILES_PATH=`\$PKG_CONFIG' '';";
256 }
257
258 if (@@ = glob("$tmpDir/*/app-defaults/")) {
259 push @nativeRequires, "wrapWithXFileSearchPathHook";
260 }
261
262 sub process {
263 my $requires = shift;
264 my $s = shift;
265 $s =~ s/\[/\ /g;
266 $s =~ s/\]/\ /g;
267 $s =~ s/\,/\ /g;
268 foreach my $req (split / /, $s) {
269 next if $req eq ">=";
270 #next if $req =~ /^\$/;
271 next if $req =~ /^[0-9]/;
272 next if $req =~ /^\s*$/;
273 next if $req eq '$REQUIRED_MODULES';
274 next if $req eq '$REQUIRED_LIBS';
275 next if $req eq '$XDMCP_MODULES';
276 next if $req eq '$XORG_MODULES';
277 print "REQUIRE: $req\n";
278 push @{$requires}, $req;
279 }
280 }
281
282 #process \@requires, $1 while $file =~ /PKG_CHECK_MODULES\([^,]*,\s*[\[]?([^\)\[]*)/g;
283 process \@requires, $1 while $file =~ /PKG_CHECK_MODULES\([^,]*,([^\)\,]*)/g;
284 process \@requires, $1 while $file =~ /AC_SEARCH_LIBS\([^,]*,([^\)\,]*)/g;
285 process \@requires, $1 while $file =~ /MODULES=\"(.*)\"/g;
286 process \@requires, $1 while $file =~ /REQUIRED_LIBS=\"(.*)\"/g;
287 process \@requires, $1 while $file =~ /REQUIRED_MODULES=\"(.*)\"/g;
288 process \@requires, $1 while $file =~ /REQUIRES=\"(.*)\"/g;
289 process \@requires, $1 while $file =~ /X11_REQUIRES=\'(.*)\'/g;
290 process \@requires, $1 while $file =~ /XDMCP_MODULES=\"(.*)\"/g;
291 process \@requires, $1 while $file =~ /XORG_MODULES=\"(.*)\"/g;
292 process \@requires, $1 while $file =~ /NEEDED=\"(.*)\"/g;
293 process \@requires, $1 while $file =~ /ivo_requires=\"(.*)\"/g;
294 process \@requires, $1 while $file =~ /XORG_DRIVER_CHECK_EXT\([^,]*,([^\)]*)\)/g;
295
296 push @nativeRequires, "gettext" if $file =~ /USE_GETTEXT/;
297 push @requires, "libxslt" if $pkg =~ /libxcb/;
298 push @nativeRequires, "meson", "ninja" if $pkg =~ /libxcvt/;
299 push @nativeRequires, "m4" if $pkg =~ /xcbutil/;
300 push @requires, "gperf", "xorgproto" if $pkg =~ /xcbutil/;
301
302 print "REQUIRES $pkg => @requires\n";
303 print "NATIVE_REQUIRES $pkg => @nativeRequires\n";
304 $pkgRequires{$pkg} = \@requires;
305 $pkgNativeRequires{$pkg} = \@nativeRequires;
306
307 print "done\n";
308}
309
310
311print "\nWRITE OUT\n";
312
313open OUT, ">default.nix";
314
315print OUT "";
316print OUT <<EOF;
317# THIS IS A GENERATED FILE. DO NOT EDIT!
318{
319 lib,
320 bdftopcf,
321 font-adobe-100dpi,
322 font-adobe-75dpi,
323 font-adobe-utopia-100dpi,
324 font-adobe-utopia-75dpi,
325 font-adobe-utopia-type1,
326 font-alias,
327 font-bh-ttf,
328 font-bh-type1,
329 font-encodings,
330 font-mutt-misc,
331 font-util,
332 gccmakedep,
333 ico,
334 imake,
335 libapplewm,
336 libdmx,
337 libfontenc,
338 libfs,
339 libice,
340 libpciaccess,
341 libpthread-stubs,
342 libsm,
343 libx11,
344 libxau,
345 libxaw,
346 libxcb,
347 libxcb-errors,
348 libxcb-image,
349 libxcb-keysyms,
350 libxcb-render-util,
351 libxcb-util,
352 libxcb-wm,
353 libxcvt,
354 libxcursor,
355 libxdmcp,
356 libxext,
357 libxfixes,
358 libxmu,
359 libxpm,
360 libxrandr,
361 libxrender,
362 libxt,
363 libxv,
364 libxvmc,
365 libxxf86dga,
366 libxxf86misc,
367 libxxf86vm,
368 lndir,
369 luit,
370 makedepend,
371 mkfontscale,
372 pixman,
373 sessreg,
374 transset,
375 util-macros,
376 xbitmaps,
377 xcb-proto,
378 xcmsdb,
379 xcursorgen,
380 xcursor-themes,
381 xdriinfo,
382 xev,
383 xfsinfo,
384 xgamma,
385 xgc,
386 xhost,
387 xkbutils,
388 xkeyboard-config,
389 xkill,
390 xlsatoms,
391 xlsclients,
392 xlsfonts,
393 xmodmap,
394 xorg-cf-files,
395 xorg-docs,
396 xorgproto,
397 xorg-sgml-doctools,
398 xprop,
399 xrandr,
400 xrefresh,
401 xtrans,
402 xvinfo,
403 xwininfo,
404 xwud,
405}:
406
407self: with self; {
408
409 inherit
410 bdftopcf
411 gccmakedep
412 ico
413 imake
414 libdmx
415 libfontenc
416 libpciaccess
417 libxcb
418 libxcvt
419 lndir
420 luit
421 makedepend
422 mkfontscale
423 pixman
424 sessreg
425 transset
426 xbitmaps
427 xcmsdb
428 xcursorgen
429 xdriinfo
430 xev
431 xfsinfo
432 xgamma
433 xgc
434 xhost
435 xkbutils
436 xkill
437 xlsatoms
438 xlsclients
439 xlsfonts
440 xmodmap
441 xorgproto
442 xprop
443 xrandr
444 xrefresh
445 xtrans
446 xvinfo
447 xwininfo
448 xwud
449 ;
450 encodings = font-encodings;
451 fontadobe100dpi = font-adobe-100dpi;
452 fontadobe75dpi = font-adobe-75dpi;
453 fontadobeutopia100dpi = font-adobe-utopia-100dpi;
454 fontadobeutopia75dpi = font-adobe-utopia-75dpi;
455 fontadobeutopiatype1 = font-adobe-utopia-type1;
456 fontalias = font-alias;
457 fontbhttf = font-bh-ttf;
458 fontbhtype1 = font-bh-type1;
459 fontmuttmisc = font-mutt-misc;
460 fontutil = font-util;
461 libAppleWM = libapplewm;
462 libFS = libfs;
463 libICE = libice;
464 libpthreadstubs = libpthread-stubs;
465 libSM = libsm;
466 libX11 = libx11;
467 libXau = libxau;
468 libXaw = libxaw;
469 libXcursor = libxcursor;
470 libXdmcp = libxdmcp;
471 libXext = libxext;
472 libXfixes = libxfixes;
473 libXmu = libxmu;
474 libXpm = libxpm;
475 libXrandr = libxrandr;
476 libXrender = libxrender;
477 libXt = libxt;
478 libXv = libxv;
479 libXvMC = libxvmc;
480 libXxf86dga = libxxf86dga;
481 libXxf86misc = libxxf86misc;
482 libXxf86vm = libxxf86vm;
483 utilmacros = util-macros;
484 xcbproto = xcb-proto;
485 xcbutilerrors = libxcb-errors;
486 xcbutilimage = libxcb-image;
487 xcbutilkeysyms = libxcb-keysyms;
488 xcbutil = libxcb-util;
489 xcbutilrenderutil = libxcb-render-util;
490 xcbutilwm = libxcb-wm;
491 xkeyboardconfig = xkeyboard-config;
492 xcursorthemes = xcursor-themes;
493 xorgcffiles = xorg-cf-files;
494 xorgdocs = xorg-docs;
495 xorgsgmldoctools = xorg-sgml-doctools;
496
497EOF
498
499
500foreach my $pkg (sort (keys %pkgURLs)) {
501 print "$pkg\n";
502
503 my %nativeRequires = ();
504 my @nativeBuildInputs;
505 foreach my $req (sort @{$pkgNativeRequires{$pkg}}) {
506 if (defined $pcMap{$req}) {
507 # Some packages have .pc that depends on itself.
508 next if $pcMap{$req} eq $pkg;
509 if (!defined $nativeRequires{$pcMap{$req}}) {
510 push @nativeBuildInputs, $pcMap{$req};
511 $nativeRequires{$pcMap{$req}} = 1;
512 }
513 } else {
514 print " NOT FOUND: $req\n";
515 }
516 }
517 my %requires = ();
518 my @buildInputs;
519 foreach my $req (sort @{$pkgRequires{$pkg}}) {
520 if (defined $pcMap{$req}) {
521 # Some packages have .pc that depends on itself.
522 next if $pcMap{$req} eq $pkg;
523 if (!defined $requires{$pcMap{$req}}) {
524 push @buildInputs, $pcMap{$req};
525 $requires{$pcMap{$req}} = 1;
526 }
527 } else {
528 print " NOT FOUND: $req\n";
529 }
530 }
531
532 my $nativeBuildInputsStr = join "", map { $_ . " " } @nativeBuildInputs;
533 my $buildInputsStr = join "", map { $_ . " " } @buildInputs;
534
535 sub uniq {
536 my %seen;
537 my @res = ();
538 foreach my $s (@_) {
539 if (!defined $seen{$s}) {
540 $seen{$s} = 1;
541 push @res, $s;
542 }
543 }
544 return @res;
545 }
546
547 my @arguments = @buildInputs;
548 push @arguments, @nativeBuildInputs;
549 unshift @arguments, "stdenv", "pkg-config", "fetchurl";
550 my $argumentsStr = join ", ", uniq @arguments;
551
552 my $extraAttrsStr = "";
553 if (defined $extraAttrs{$pkg}) {
554 $extraAttrsStr = join "", map { "\n " . $_ } @{$extraAttrs{$pkg}};
555 }
556
557 my $pcProvidesStr = "";
558 if (defined $pcProvides{$pkg}) {
559 $pcProvidesStr = join "", map { "\"" . $_ . "\" " } (sort @{$pcProvides{$pkg}});
560 }
561
562 print OUT <<EOF
563 # THIS IS A GENERATED FILE. DO NOT EDIT!
564 $pkg = callPackage ({ $argumentsStr, testers }: stdenv.mkDerivation (finalAttrs: {
565 pname = "$pkgNames{$pkg}";
566 version = "$pkgVersions{$pkg}";
567 builder = ./builder.sh;
568 src = fetchurl {
569 url = "$pkgURLs{$pkg}";
570 sha256 = "$pkgHashes{$pkg}";
571 };
572 hardeningDisable = [ "bindnow" "relro" ];
573 strictDeps = true;
574 nativeBuildInputs = [ pkg-config $nativeBuildInputsStr];
575 buildInputs = [ $buildInputsStr];$extraAttrsStr
576 passthru.tests.pkg-config = testers.testMetaPkgConfig finalAttrs.finalPackage;
577 meta = {
578 pkgConfigModules = [ $pcProvidesStr];
579 platforms = lib.platforms.unix;
580 };
581 })) {};
582
583EOF
584}
585
586print OUT "}\n";
587
588close OUT;