diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
 # cpkg
 
+## 0.2.1.0
+
+  * Add `SymlinkManpage` command
+
 ## 0.2.0.1
 
   * Pass `-p0` option to `patch`
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -255,14 +255,14 @@
 -------------------------------------------------------------------------------
  Language             Files       Lines         Code     Comments       Blanks
 -------------------------------------------------------------------------------
- Bash                     3          43           35            3            5
+ Bash                     5          52           44            3            5
  Cabal                    1         154          140            0           14
- Cabal Project            1          10            8            0            2
- Dhall                    3        4572         4111            1          460
- Haskell                 31        1728         1415           29          284
- Markdown                 3         487          407            0           80
- YAML                     4         156          141            0           15
+ Cabal Project            1           4            3            0            1
+ Dhall                    3        4660         4190            3          467
+ Haskell                 31        1741         1428           29          284
+ Markdown                 6         534          450            0           84
+ YAML                     4         157          142            0           15
 -------------------------------------------------------------------------------
- Total                   46        7150         6257           33          860
+ Total                   51        7302         6397           35          870
 -------------------------------------------------------------------------------
 ```
diff --git a/cpkg.cabal b/cpkg.cabal
--- a/cpkg.cabal
+++ b/cpkg.cabal
@@ -1,6 +1,6 @@
 cabal-version: 1.18
 name: cpkg
-version: 0.2.0.1
+version: 0.2.1.0
 license: BSD3
 license-file: LICENSE
 copyright: Copyright: (c) 2018-2019 Vanessa McHale
@@ -94,7 +94,8 @@
         filemanip -any,
         network-uri -any,
         megaparsec -any,
-        libarchive >=1.0.4.0
+        libarchive >=1.0.4.0,
+        dir-traverse >=0.2.1.0
 
     if (flag(development) && impl(ghc <=8.2))
         ghc-options: -Werror
diff --git a/dhall/cpkg-prelude.dhall b/dhall/cpkg-prelude.dhall
--- a/dhall/cpkg-prelude.dhall
+++ b/dhall/cpkg-prelude.dhall
@@ -183,6 +183,10 @@
     types.Command.SymlinkBinary { file = file }
 in
 
+let symlinkManpage =
+    types.Command.SymlinkManpage
+in
+
 let symlink =
   λ(tgt : Text) →
   λ(lnk : Text) →
@@ -199,6 +203,10 @@
   map Text types.Command symlinkBinary
 in
 
+let symlinkManpages =
+  map { file : Text, section : Natural } types.Command symlinkManpage
+in
+
 {- This is to be used on the build OS -}
 let isUnix =
   λ(os : types.OS) →
@@ -381,14 +389,14 @@
                       , mkPkgConfigVar (cfg.shareDirs # cfg.linkDirs)
                       , libPath cfg
                       , mkLDRunPath cfg.linkDirs
-                      , mkPerlLib { libDirs = cfg.linkDirs, perlVersion = [5,28,1], cfg = cfg } -- TODO: take this as a parameter
+                      , mkPerlLib { libDirs = cfg.linkDirs, perlVersion = [5,30,0], cfg = cfg } -- TODO: take this as a parameter
                       ]
 in
 
 let buildEnv =
   λ(cfg : types.BuildVars) →
     defaultPath cfg # [ mkPkgConfigVar (cfg.shareDirs # cfg.linkDirs)
-                      , mkPerlLib { libDirs = cfg.linkDirs, perlVersion = [5,28,1], cfg = cfg } -- TODO: take this as a parameter
+                      , mkPerlLib { libDirs = cfg.linkDirs, perlVersion = [5,30,0], cfg = cfg } -- TODO: take this as a parameter
                       , mkLDPath cfg.linkDirs
                       ]
 in
@@ -441,7 +449,7 @@
 
 let mkAclocalPath =
   λ(shareDirs : List Text) →
-    let flag = concatMapSep ":" Text (λ(dir : Text) → "${dir}/aclocal:${dir}/autoconf/autoconf") shareDirs
+    let flag = concatMapSep ":" Text (λ(dir : Text) → "${dir}/aclocal:${dir}/autoconf") shareDirs
     in
 
     { var = "ACLOCAL_PATH", value = flag }
@@ -500,6 +508,15 @@
             else [] : List types.Command)
 in
 
+let installWithManpages =
+  λ(mans : List { file : Text, section : Natural }) →
+  λ(installVars : types.BuildVars) →
+    defaultInstall installVars
+      # (if not installVars.isCross
+            then symlinkManpages mans
+            else [] : List types.Command)
+in
+
 let unbounded =
   λ(x : Text) →
     { name = x
@@ -537,6 +554,7 @@
       { pkgName = pkg.name
       , pkgVersion = pkg.version
       , pkgSubdir = "${pkg.name}-${showVersion pkg.version}"
+      , pkgBuildDeps = [ unbounded "make" ]
       }
 in
 
@@ -609,7 +627,7 @@
 
 let cmakeEnv =
   λ(cfg : types.BuildVars) →
-    [ mkPkgConfigVar cfg.shareDirs
+    [ mkPkgConfigVar (cfg.shareDirs # cfg.linkDirs)
     , { var = "CMAKE_INCLUDE_PATH", value = (mkIncludePath cfg.includeDirs).value }
     , { var = "CMAKE_LIBRARY_PATH", value = (libPath cfg).value }
     ]
@@ -703,7 +721,7 @@
   λ(cfg : types.BuildVars) →
     [ mkExe "autogen.sh"
     , call (defaultCall ⫽ { program = "./autogen.sh"
-                          , environment = Some ([ mkAclocalPath cfg.shareDirs ]
+                          , environment = Some ( [ mkAclocalPath cfg.shareDirs ]
                                                   # defaultPath cfg)
                           })
     ] # defaultConfigure cfg
@@ -759,6 +777,7 @@
          , mkLDRunPath cfg.linkDirs
          , mkLDFlags cfg.linkDirs
          , mkCFlags cfg
+         , mkLDPreload cfg.preloadLibs
          ]
 in
 
@@ -801,7 +820,7 @@
                                                , mkLDRunPath cfg.linkDirs
                                                , mkLDFlagsGeneral cfg.linkDirs linkLibs
                                                , mkCFlags cfg
-                                               , mkPkgConfigVar cfg.linkDirs
+                                               , mkLDPreload cfg.preloadLibs
                                                ]
                           , procDir = Some "build" }) ]
 in
@@ -949,7 +968,7 @@
                             , libPath cfg
                             , mkXdgDataDirs cfg.shareDirs
                             , mkLDPreload cfg.preloadLibs
-                            , mkPerlLib { libDirs = cfg.linkDirs, perlVersion = [5,28,1], cfg = cfg } -- TODO: take this as a parameter
+                            , mkPerlLib { libDirs = cfg.linkDirs, perlVersion = [5,30,0], cfg = cfg } -- TODO: take this as a parameter
                             ])
 in
 
@@ -1025,12 +1044,18 @@
     ]
 in
 
+let mkLDPathWrappers =
+  λ(cfg : types.BuildVars) →
+  λ(bins : List Text) →
+    concatMap Text types.Command (λ(bin : Text) → mkLDPathWrapper cfg bin) bins
+    -- TODO: add to PATH for e.g. PERL interpreter
+in
+
 let installWithWrappers =
   λ(bins : List Text) →
   λ(cfg : types.BuildVars) →
     defaultInstall cfg #
-      concatMap Text types.Command (λ(bin : Text) → mkLDPathWrapper cfg bin) bins
-      -- TODO: add to PATH for e.g. PERL interpreter
+      mkLDPathWrappers cfg bins
 in
 
 let underscoreVersion =
@@ -1067,6 +1092,18 @@
       arch
 in
 
+let configureWithPatches =
+  λ(patches : List Text) →
+  λ(cfg : types.BuildVars) →
+    map Text types.Command (λ(p : Text) → patch p) patches
+      # defaultConfigure cfg
+in
+
+let configureWithPatch =
+  λ(p : Text) →
+    configureWithPatches [p]
+in
+
 { showVersion         = showVersion
 , makeGnuLibrary      = makeGnuLibrary
 , makeGnuExe          = makeGnuExe
@@ -1099,6 +1136,7 @@
 , maybeAppend         = maybeAppend
 , mkCFlags            = mkCFlags
 , mkLDFlags           = mkLDFlags
+, mkLDFlagsGeneral    = mkLDFlagsGeneral
 , mkLDPath            = mkLDPath
 , mkLDRunPath         = mkLDRunPath
 , mkStaPath           = mkStaPath
@@ -1110,9 +1148,12 @@
 , defaultPath         = defaultPath
 , simplePackage       = simplePackage
 , symlinkBinary       = symlinkBinary
+, symlinkManpage      = symlinkManpage
 , symlink             = symlink
 , symlinkBinaries     = symlinkBinaries
+, symlinkManpages     = symlinkManpages
 , installWithBinaries = installWithBinaries
+, installWithManpages = installWithManpages
 , configureMkExes     = configureMkExes
 , generalConfigure    = generalConfigure
 , configureWithFlags  = configureWithFlags
@@ -1163,6 +1204,7 @@
 , installWithPy3Wrappers = installWithPy3Wrappers
 , cmakeConfigureNinja = cmakeConfigureNinja
 , mkLDPathWrapper     = mkLDPathWrapper
+, mkLDPathWrappers    = mkLDPathWrappers
 , installWithWrappers = installWithWrappers
 , cmakeEnv            = cmakeEnv
 , cmakeSome           = cmakeSome
@@ -1171,4 +1213,7 @@
 , configWithEnv       = configWithEnv
 , buildEnv            = buildEnv
 , patch               = patch
+, mkAclocalPath       = mkAclocalPath
+, configureWithPatches = configureWithPatches
+, configureWithPatch  = configureWithPatch
 }
diff --git a/dhall/cpkg-types.dhall b/dhall/cpkg-types.dhall
--- a/dhall/cpkg-types.dhall
+++ b/dhall/cpkg-types.dhall
@@ -104,6 +104,7 @@
               | MakeExecutable : { file : Text }
               | Call : Proc
               | SymlinkBinary : { file : Text }
+              | SymlinkManpage : { file : Text, section : Natural }
               | Symlink : { tgt : Text, linkName : Text }
               | Write : { file : Text, contents : Text }
               | CopyFile : { src : Text, dest : Text }
diff --git a/pkgs/patches/intltool.patch b/pkgs/patches/intltool.patch
new file mode 100644
--- /dev/null
+++ b/pkgs/patches/intltool.patch
@@ -0,0 +1,50 @@
+--- intltool-update.in	2015-03-08 20:39:54.000000000 -0500
++++ intltool-update.in	2019-06-19 20:58:02.349782444 -0500
+@@ -1062,13 +1062,13 @@
+ 	}
+     }
+ 
+-    if ($str =~ /^(.*)\${?([A-Z_]+)}?(.*)$/)
++    if ($str =~ /^(.*)\$\{?([A-Z_]+)}?(.*)$/)
+     {
+ 	my $rest = $3;
+ 	my $untouched = $1;
+ 	my $sub = "";
+         # Ignore recursive definitions of variables
+-        $sub = $varhash{$2} if defined $varhash{$2} and $varhash{$2} !~ /\${?$2}?/;
++        $sub = $varhash{$2} if defined $varhash{$2} and $varhash{$2} !~ /\$\{?$2}?/;
+ 
+ 	return SubstituteVariable ("$untouched$sub$rest");
+     }
+@@ -1190,10 +1190,10 @@
+ 	$name    =~ s/\(+$//g;
+ 	$version =~ s/\(+$//g;
+ 
+-	$varhash{"PACKAGE_NAME"} = $name if (not $name =~ /\${?AC_PACKAGE_NAME}?/);
+-	$varhash{"PACKAGE"} = $name if (not $name =~ /\${?PACKAGE}?/);
+-	$varhash{"PACKAGE_VERSION"} = $version if (not $name =~ /\${?AC_PACKAGE_VERSION}?/);
+-	$varhash{"VERSION"} = $version if (not $name =~ /\${?VERSION}?/);
++	$varhash{"PACKAGE_NAME"} = $name if (not $name =~ /\$\{?AC_PACKAGE_NAME}?/);
++	$varhash{"PACKAGE"} = $name if (not $name =~ /\$\{?PACKAGE}?/);
++	$varhash{"PACKAGE_VERSION"} = $version if (not $name =~ /\$\{?AC_PACKAGE_VERSION}?/);
++	$varhash{"VERSION"} = $version if (not $name =~ /\$\{?VERSION}?/);
+     }
+ 
+     if ($conf_source =~ /^AC_INIT\(([^,\)]+),([^,\)]+)[,]?([^,\)]+)?/m)
+@@ -1219,11 +1219,11 @@
+ 	$version =~ s/\(+$//g;
+         $bugurl  =~ s/\(+$//g if (defined $bugurl);
+ 
+-	$varhash{"PACKAGE_NAME"} = $name if (not $name =~ /\${?AC_PACKAGE_NAME}?/);
+-	$varhash{"PACKAGE"} = $name if (not $name =~ /\${?PACKAGE}?/);
+-	$varhash{"PACKAGE_VERSION"} = $version if (not $name =~ /\${?AC_PACKAGE_VERSION}?/);
+-	$varhash{"VERSION"} = $version if (not $name =~ /\${?VERSION}?/);
+-        $varhash{"PACKAGE_BUGREPORT"} = $bugurl if (defined $bugurl and not $bugurl =~ /\${?\w+}?/);
++	$varhash{"PACKAGE_NAME"} = $name if (not $name =~ /\$\{?AC_PACKAGE_NAME}?/);
++	$varhash{"PACKAGE"} = $name if (not $name =~ /\$\{?PACKAGE}?/);
++	$varhash{"PACKAGE_VERSION"} = $version if (not $name =~ /\$\{?AC_PACKAGE_VERSION}?/);
++	$varhash{"VERSION"} = $version if (not $name =~ /\$\{?VERSION}?/);
++        $varhash{"PACKAGE_BUGREPORT"} = $bugurl if (defined $bugurl and not $bugurl =~ /\$\{?\w+}?/);
+     }
+ 
+     # \s makes this not work, why?
diff --git a/pkgs/patches/make.patch b/pkgs/patches/make.patch
new file mode 100644
--- /dev/null
+++ b/pkgs/patches/make.patch
@@ -0,0 +1,11 @@
+--- glob/glob.c	2013-10-20 17:14:38.000000000 +0000
++++ glob/glob.c	2018-09-18 10:16:03.860886356 +0000
+@@ -208,7 +208,7 @@
+ #endif /* __GNU_LIBRARY__ || __DJGPP__ */
+ 
+ 
+-#if !defined __alloca && !defined __GNU_LIBRARY__
++#if !defined __alloca && defined __GNU_LIBRARY__
+ 
+ # ifdef	__GNUC__
+ #  undef alloca
diff --git a/pkgs/patches/pHash.patch b/pkgs/patches/pHash.patch
new file mode 100644
--- /dev/null
+++ b/pkgs/patches/pHash.patch
@@ -0,0 +1,113 @@
+--- src/cimgffmpeg.cpp	2019-06-22 20:18:05.632517868 -0500
++++ src/cimgffmpeg.cpp	2019-06-22 20:18:45.569003435 -0500
+@@ -100,12 +100,12 @@
+         AVFrame *pFrame;
+ 
+ 	// Allocate video frame
+-	pFrame=avcodec_alloc_frame();
++	pFrame=av_frame_alloc();
+ 	if (pFrame==NULL)
+ 	    return -1;
+ 
+ 	// Allocate an AVFrame structure
+-	AVFrame *pConvertedFrame = avcodec_alloc_frame();
++	AVFrame *pConvertedFrame = av_frame_alloc();
+ 	if(pConvertedFrame==NULL)
+ 	  return -1;
+ 		
+@@ -254,10 +254,10 @@
+ 	AVFrame *pFrame;
+ 
+ 	// Allocate video frame
+-	pFrame=avcodec_alloc_frame();
++	pFrame=av_frame_alloc();
+ 		
+ 	// Allocate an AVFrame structure
+-	AVFrame *pConvertedFrame = avcodec_alloc_frame();
++	AVFrame *pConvertedFrame = av_frame_alloc();
+ 	if(pConvertedFrame==NULL){
+ 	  return -1;
+ 	}
+--- configure.ac	2019-06-22 21:22:10.582842002 -0500
++++ configure.ac	2019-06-22 21:21:48.962982961 -0500
+@@ -122,7 +122,7 @@
+ AC_DEFUN([AC_CHECK_FFMPEG],
+ [
+ AC_MSG_CHECKING([whether FFmpeg is present])
+-AC_CHECK_LIB([avcodec], [avcodec_alloc_frame], [], [AC_MSG_ERROR([
++AC_CHECK_LIB([avutil], [av_frame_alloc], [], [AC_MSG_ERROR([
+ 
+ *** libavcodec not found.
+ You need FFmpeg. Get it at <http://ffmpeg.org/>])])
+--- src/pHash.h	2019-06-23 11:31:15.678771295 -0500
++++ src/pHash.h	2019-06-23 11:31:31.754816275 -0500
+@@ -47,6 +47,8 @@
+ #if defined(HAVE_IMAGE_HASH) || defined(HAVE_VIDEO_HASH)
+ #define cimg_debug 0
+ #define cimg_display 0
++#define cimg_use_png
++#define cimg_use_jpeg
+ #include "CImg.h"
+ using namespace cimg_library;
+ #endif
+--- src/cimgffmpeg.cpp	2019-06-22 21:50:15.060403190 -0500
++++ src/cimgffmpeg.cpp	2019-06-22 21:56:50.839827371 -0500
+@@ -39,11 +39,11 @@
+ int ReadFrames(VFInfo *st_info, CImgList<uint8_t> *pFrameList, unsigned int low_index, unsigned int hi_index)
+ {
+         //target pixel format
+-	PixelFormat ffmpeg_pixfmt;
++	AVPixelFormat ffmpeg_pixfmt;
+ 	if (st_info->pixelformat == 0)
+-	    ffmpeg_pixfmt = PIX_FMT_GRAY8;
++	    ffmpeg_pixfmt = AV_PIX_FMT_GRAY8;
+ 	else 
+-	    ffmpeg_pixfmt = PIX_FMT_RGB24;
++	    ffmpeg_pixfmt = AV_PIX_FMT_RGB24;
+ 
+ 	st_info->next_index = low_index;
+ 
+@@ -123,7 +123,7 @@
+ 	int size = 0;
+ 	
+ 
+-        int channels = ffmpeg_pixfmt == PIX_FMT_GRAY8 ? 1 : 3;
++        int channels = ffmpeg_pixfmt == AV_PIX_FMT_GRAY8 ? 1 : 3;
+ 
+ 	AVPacket packet;
+ 	int result = 1;
+@@ -189,11 +189,11 @@
+ 
+ int NextFrames(VFInfo *st_info, CImgList<uint8_t> *pFrameList)
+ {
+-        PixelFormat ffmpeg_pixfmt;
++        AVPixelFormat ffmpeg_pixfmt;
+ 	if (st_info->pixelformat == 0)
+-	    ffmpeg_pixfmt = PIX_FMT_GRAY8;
++	    ffmpeg_pixfmt = AV_PIX_FMT_GRAY8;
+         else 
+-	    ffmpeg_pixfmt = PIX_FMT_RGB24;
++	    ffmpeg_pixfmt = AV_PIX_FMT_RGB24;
+ 
+ 	if (st_info->pFormatCtx == NULL)
+ 	{
+@@ -287,7 +287,7 @@
+ 			break;
+ 		if(packet.stream_index == st_info->videoStream) {
+ 			
+-		int channels = ffmpeg_pixfmt == PIX_FMT_GRAY8 ? 1 : 3;
++		int channels = ffmpeg_pixfmt == AV_PIX_FMT_GRAY8 ? 1 : 3;
+  		AVPacket avpkt;
+                 av_init_packet(&avpkt);
+                 avpkt.data = packet.data;
+--- src/cimgffmpeg.h	2019-06-23 11:47:59.046307628 -0500
++++ src/cimgffmpeg.h	2019-06-23 11:32:14.754956444 -0500
+@@ -30,6 +30,8 @@
+ #define cimg_display 0
+ #define cimg_debug 0
+ 
++#define cimg_use_png
++#define cimg_use_jpeg
+ #include "CImg.h"
+ 
+ #define __STDC_CONSTANT_MACROS
diff --git a/pkgs/pkg-set.dhall b/pkgs/pkg-set.dhall
--- a/pkgs/pkg-set.dhall
+++ b/pkgs/pkg-set.dhall
@@ -108,6 +108,7 @@
     in
 
     prelude.defaultPackage ⫽
+    -- TODO: build dep on gcc/g++
       { pkgName = "cmake"
       , pkgVersion = prelude.fullVersion cfg
       , pkgUrl = "https://cmake.org/files/v${versionString}/cmake-${versionString}.${patchString}.tar.gz"
@@ -126,6 +127,7 @@
                 , prelude.copyFile wrapped wrapped
                 , prelude.symlinkBinary wrapped
                 ]
+      , pkgBuildDeps = [ prelude.unbounded "make" ]
       }
 in
 
@@ -141,7 +143,7 @@
 let dbus =
   λ(v : List Natural) →
     prelude.simplePackage { name = "dbus", version = v } ⫽
-      { pkgUrl = "https://dbus.freedesktop.org/releases/dbus/dbus-${prelude.showVersion v}.tar.gz"
+      { pkgUrl = "https://dbus.freedesktop.org/releases/dbus/dbus-${prelude.showVersion v}.tar.xz"
       , pkgDeps = [ prelude.unbounded "expat"
                   , prelude.unbounded "libselinux"
                   ]
@@ -275,9 +277,10 @@
 
   λ(v : List Natural) →
     prelude.simplePackage { name = "harfbuzz", version = v } ⫽
-      { pkgUrl = "https://www.freedesktop.org/software/harfbuzz/release/harfbuzz-${prelude.showVersion v}.tar.bz2"
+      { pkgUrl = "https://www.freedesktop.org/software/harfbuzz/release/harfbuzz-${prelude.showVersion v}.tar.xz"
       , pkgDeps = [ prelude.unbounded "freetype-prebuild"
                   , prelude.unbounded "glib"
+                  , prelude.unbounded "icu"
                   ]
       , pkgBuildDeps = [ prelude.unbounded "pkg-config" ]
       , configureCommand = prelude.configureLinkExtraLibs [ "pcre", "z" ]
@@ -336,6 +339,10 @@
       , pkgUrl = "https://dist.libuv.org/dist/v${prelude.showVersion v}/libuv-v${prelude.showVersion v}.tar.gz"
       , pkgSubdir = "libuv-v${prelude.showVersion v}"
       , configureCommand = prelude.autogenConfigure
+      , pkgBuildDeps = [ prelude.unbounded "m4"
+                       , prelude.unbounded "automake"
+                       , prelude.unbounded "libtool"
+                       ]
       }
 in
 
@@ -345,6 +352,7 @@
       { pkgUrl = "http://www.nasm.us/pub/nasm/releasebuilds/${prelude.showVersion v}.02/nasm-${prelude.showVersion v}.02.tar.xz"
       , pkgSubdir = "nasm-${prelude.showVersion v}.02"
       , installCommand = prelude.installWithBinaries [ "bin/nasm", "bin/ndisasm" ]
+      , pkgBuildDeps = [ prelude.unbounded "make" ]
       }
 in
 
@@ -362,6 +370,7 @@
 
           prelude.configureWithFlags ([ "--with-shared", "--enable-widec" ] # crossArgs) cfg
           -- enable-widec is necessary because util-linux uses libncursesw
+      , pkgBuildDeps = [ prelude.unbounded "make" ]
       }
 in
 
@@ -374,7 +383,9 @@
 let pcre =
   λ(v : List Natural) →
     prelude.simplePackage { name = "pcre", version = v } ⫽
-      { pkgUrl = "https://ftp.pcre.org/pub/pcre/pcre-${prelude.showVersion v}.tar.bz2" }
+      { pkgUrl = "https://ftp.pcre.org/pub/pcre/pcre-${prelude.showVersion v}.tar.bz2"
+      , pkgBuildDeps = [ prelude.unbounded "make" ]
+      }
 in
 
 let perl5 =
@@ -412,6 +423,7 @@
     prelude.simplePackage { name = "libpng", version = v } ⫽
       { pkgUrl = "https://download.sourceforge.net/libpng/libpng-${prelude.showVersion v}.tar.xz"
       , pkgDeps = [ prelude.unbounded "zlib" ]
+      , pkgBuildDeps = [ prelude.unbounded "make" ]
       }
 in
 
@@ -513,13 +525,17 @@
     prelude.simplePackage { name = "zlib", version = v } ⫽
       { pkgUrl = "http://www.zlib.net/zlib-${prelude.showVersion v}.tar.xz"
       , configureCommand = zlibConfigure
+      , installCommand =
+          prelude.installWithManpages [ { file = "share/man/man3/zlib.3", section = 3 } ]
       }
 in
 
 let gettext =
   λ(v : List Natural) →
     prelude.makeGnuExe { name = "gettext", version = v } ⫽
-      { installCommand = prelude.installWithBinaries [ "bin/gettext", "bin/msgfmt", "bin/autopoint" ] }
+      { installCommand = prelude.installWithBinaries [ "bin/gettext", "bin/msgfmt", "bin/autopoint" ]
+      , pkgBuildDeps = [ prelude.unbounded "make" ]
+      }
 in
 
 let gzip =
@@ -631,7 +647,8 @@
 
 let patch =
   λ(v : List Natural) →
-    prelude.makeGnuExe { name = "patch", version = v }
+    prelude.makeGnuExe { name = "patch", version = v } ⫽
+      { pkgBuildDeps = [] : List types.Dep }
 in
 
 let m4 =
@@ -641,7 +658,11 @@
           λ(cfg : types.BuildVars) →
             [ prelude.patch (./patches/m4.patch as Text) ]
               # prelude.defaultConfigure cfg
-      , pkgBuildDeps = [ prelude.unbounded "patch" ]
+      , installCommand =
+          prelude.installWithManpages [ { file = "share/man/man1/m4.1", section = 1 } ]
+      , pkgBuildDeps = [ prelude.unbounded "patch"
+                       , prelude.unbounded "make"
+                       ]
       }
 in
 
@@ -661,7 +682,7 @@
 
   λ(v : List Natural) →
     prelude.simplePackage { name = "openssl", version = v } ⫽
-      { pkgUrl = "https://www.openssl.org/source/openssl-${prelude.showVersion v}a.tar.gz"
+      { pkgUrl = "https://www.openssl.org/source/openssl-${prelude.showVersion v}c.tar.gz"
       , configureCommand =
           λ(cfg : types.BuildVars) →
             let sharedFlag =
@@ -669,13 +690,19 @@
                 then "no-shared"
                 else "shared"
             in
+            -- TODO: actually do this sensibly
+            let targetMakefile =
+              if cfg.isCross
+                then "gcc"
+                else "linux-x86_64"
+            in
             [ prelude.mkExe "Configure"
             , prelude.call (prelude.defaultCall ⫽ { program = "./Configure"
-                                                  , arguments = [ "--prefix=${cfg.installDir}", "gcc", sharedFlag ] -- FIXME: gcc platform doesn't support shared libraries
+                                                  , arguments = [ "--prefix=${cfg.installDir}", targetMakefile, sharedFlag ] -- FIXME: gcc platform doesn't support shared libraries
                                                   , environment = opensslCfgVars cfg
                                                   })
             ]
-      , pkgSubdir = "openssl-${prelude.showVersion v}a"
+      , pkgSubdir = "openssl-${prelude.showVersion v}c"
       , pkgBuildDeps = [ prelude.unbounded "perl" ]
       }
 in
@@ -689,7 +716,9 @@
 let giflib =
   λ(v : List Natural) →
     prelude.simplePackage { name = "giflib", version = v } ⫽
-      { pkgUrl = "https://downloads.sourceforge.net/giflib/giflib-${prelude.showVersion v}.tar.bz2" }
+      { pkgUrl = "https://downloads.sourceforge.net/giflib/giflib-${prelude.showVersion v}.tar.bz2"
+      , pkgBuildDeps = [ prelude.unbounded "make" ]
+      }
 in
 
 let emacs =
@@ -786,10 +815,15 @@
           [ prelude.writeFile { file = "config.site", contents = config } ]
             # prelude.generalConfigure pyEnv "configure" ([] : List Text)
                 ([ "--build=${prelude.printArch cfg.buildArch}" ] # crossArgs # staticFlag) cfg
+          -- enable-optimizations takes too long
           -- disable ipv6 for cross-compiling
-          -- "--enable-optimizations" (takes forever)
-      , pkgDeps = [ prelude.unbounded "libffi" ]
-      , installCommand = prelude.installWithBinaries [ "bin/python${major}" ]
+      , pkgDeps = [ prelude.unbounded "libffi"
+                  , prelude.unbounded "ncurses"
+                  ]
+      , installCommand =
+          λ(cfg : types.BuildVars) →
+            prelude.installWithBinaries [ "bin/python${major}" ] cfg
+              # prelude.symlinkManpages [ { file = "share/man/man1/python${major}.1", section = 1 } ]
       -- , installCommand =
           -- prelude.installWithWrappers [ "python${major}" ]
       }
@@ -875,13 +909,16 @@
       , pkgDeps = [ prelude.lowerBound { name = "libffi", lower = [3,0,0] }
                   , prelude.unbounded "libtasn1"
                   ]
+      , pkgBuildDeps = [ prelude.unbounded "pkg-config" ]
       }
 in
 
 let libffi =
   λ(v : List Natural) →
     prelude.simplePackage { name = "libffi", version = v } ⫽
-      { pkgUrl = "https://sourceware.org/ftp/libffi/libffi-${prelude.showVersion v}.tar.gz" }
+      { pkgUrl = "https://sourceware.org/ftp/libffi/libffi-${prelude.showVersion v}.tar.gz"
+      , pkgBuildDeps = [ prelude.unbounded "make" ]
+      }
 in
 
 let gdb =
@@ -890,11 +927,13 @@
       { configureCommand = prelude.configureMkExes [ "mkinstalldirs" ] }
 in
 
+-- lol the libtoolize binary is empty for some reason
 let libtool =
   λ(v : List Natural) →
     prelude.makeGnuExe { name = "libtool", version = v } ⫽
       { pkgUrl = "http://ftpmirror.gnu.org/libtool/libtool-${prelude.showVersion v}.tar.gz"
       , pkgBuildDeps = [ prelude.lowerBound { name =  "m4", lower = [1,4,16] } ]
+      , pkgStream = False
       }
 in
 
@@ -903,6 +942,7 @@
     prelude.simplePackage { name = "pkg-config", version = v } ⫽
       { pkgUrl = "https://pkg-config.freedesktop.org/releases/pkg-config-${prelude.showVersion v}.tar.gz"
       , configureCommand = prelude.configureWithFlags [ "--with-internal-glib" ]
+      , pkgBuildDeps = [ prelude.unbounded "make" ]
       }
 in
 
@@ -1050,7 +1090,9 @@
   λ(name : Text) →
   λ(v : List Natural) →
     prelude.simplePackage { name = name, version = v } ⫽
-      { pkgUrl = "https://www.x.org/releases/individual/proto/${name}-${prelude.showVersion v}.tar.bz2" }
+      { pkgUrl = "https://www.x.org/releases/individual/proto/${name}-${prelude.showVersion v}.tar.bz2"
+      , pkgBuildDeps = [ prelude.unbounded "make" ]
+      }
 in
 
 let mkXProtoWithPatch =
@@ -1058,11 +1100,10 @@
   λ(patch : Text) →
   λ(v : List Natural) →
     mkXProto name v ⫽
-      { configureCommand =
-          λ(cfg : types.BuildVars) →
-            [ prelude.patch patch ]
-              # prelude.defaultConfigure cfg
-      , pkgBuildDeps = [ prelude.unbounded "patch" ]
+      { configureCommand = prelude.configureWithPatch patch
+      , pkgBuildDeps = [ prelude.unbounded "patch"
+                       , prelude.unbounded "make"
+                       ]
       }
 in
 
@@ -1170,7 +1211,7 @@
           [ prelude.call (prelude.defaultCall ⫽ { program = prelude.makeExe cfg.buildOS
                                                 , environment = Some (prelude.defaultPath cfg # [ prelude.libPath cfg
                                                                                                 , prelude.mkLDRunPath cfg.linkDirs
-                                                                                                , prelude.mkPerlLib { libDirs = cfg.linkDirs, perlVersion = [5,28,1], cfg = cfg }
+                                                                                                , prelude.mkPerlLib { libDirs = cfg.linkDirs, perlVersion = [5,30,0], cfg = cfg }
                                                                                                 ])
                                                 })
           ]
@@ -1195,15 +1236,16 @@
       { pkgUrl = "https://launchpad.net/intltool/trunk/${versionString}/+download/intltool-${versionString}.tar.gz"
       , configureCommand =
           λ(cfg : types.BuildVars) →
-            [ prelude.mkExe "configure"
+            [ prelude.patch (./patches/intltool.patch as Text)
+            , prelude.mkExe "configure"
             , prelude.call (prelude.defaultCall ⫽ { program = "./configure"
                                                   , arguments = [ "--prefix=${cfg.installDir}" ]
                                                   , environment = Some (prelude.defaultPath cfg
-                                                      # [ prelude.mkPerlLib { libDirs = cfg.linkDirs, perlVersion = [5,28,1], cfg = cfg } ])
+                                                      # [ prelude.mkPerlLib { libDirs = cfg.linkDirs, perlVersion = [5,30,0], cfg = cfg } ])
                                                   })
             ]
     , pkgDeps = [ prelude.unbounded "XML-Parser" ]
-    , pkgBuildDeps = [ prelude.upperBound { name = "perl", upper = [5,30] } ] -- lower bound: 5.8.1
+    , pkgBuildDeps = [ prelude.lowerBound { name = "perl", lower = [5,8,1] } ]
     }
 in
 
@@ -1348,11 +1390,14 @@
     let fullVersion = versionString ++ "." ++ Natural/show x.patch
     in
 
-    prelude.simplePackage { name = "gobject-introspection", version = prelude.fullVersion x } ⫽
+    prelude.ninjaPackage { name = "gobject-introspection", version = prelude.fullVersion x } ⫽
       { pkgUrl = "https://download.gnome.org/sources/gobject-introspection/${versionString}/gobject-introspection-${fullVersion}.tar.xz"
-      , pkgBuildDeps = [ prelude.unbounded "flex" ]
-      , configureCommand = prelude.configureLinkExtraLibs [ "pcre", "gobject-2.0", "gio-2.0" ]
+      , pkgBuildDeps = [ prelude.unbounded "meson" ] -- prelude.unbounded "flex" "bison" ]
       , pkgDeps = [ prelude.lowerBound { name = "glib", lower = [2,58,0] } ]
+      , installCommand =
+          λ(cfg : types.BuildVars) →
+            [ prelude.mkExe "build/tools/g-ir-scanner" ]
+              # prelude.ninjaInstall cfg
       }
 in
 
@@ -1373,6 +1418,7 @@
                        , prelude.unbounded "bison"
                        ]
       , configureCommand = prelude.configWithEnv flexEnv
+      , installCommand = prelude.installWithBinaries [ "bin/flex" ]
       }
 in
 
@@ -1432,21 +1478,6 @@
                              ]
       , installCommand =
           λ(cfg : types.BuildVars) →
-            let libDir = "lib/${prelude.printArch cfg.buildArch}-${prelude.printOS cfg.buildOS}-gnu"
-            in
-            let noCross =
-              if not cfg.isCross
-                then
-                  [ prelude.symlink "${libDir}/libglib-2.0.so" "lib/libglib-2.0.so"
-                  , prelude.symlink "${libDir}/libglib-2.0.so.0" "lib/libglib-2.0.so.0"
-                  , prelude.symlink "${libDir}/libgio-2.0.so" "lib/libgio-2.0.so"
-                  , prelude.symlink "${libDir}/libgthread-2.0.so" "lib/libgthread-2.0.so"
-                  , prelude.symlink "${libDir}/libgobject-2.0.so" "lib/libgobject-2.0.so"
-                  , prelude.symlink "${libDir}/libgmodule-2.0.so" "lib/libgmodule-2.0.so"
-                  ]
-                else [] : List types.Command
-            in
-
             prelude.ninjaInstallWithPkgConfig (prelude.mesonMoves [ "glib-2.0.pc"
                                                                   , "gobject-2.0.pc"
                                                                   , "gio-2.0.pc"
@@ -1456,7 +1487,6 @@
                                                                   , "gmodule-2.0.pc"
                                                                   , "gthread-2.0.pc"
                                                                   ]) cfg
-              # noCross
               # [ prelude.symlink "include/glib-2.0/glib" "include/glib"
                 , prelude.symlink "include/glib-2.0/gobject" "include/gobject"
                 , prelude.symlink "include/glib-2.0/glib.h" "include/glib.h"
@@ -1650,7 +1680,7 @@
                        ] -- TODO: disable introspection?
       , pkgDeps = [ prelude.unbounded "glib" ]
       , installCommand =
-          prelude.ninjaInstallWithPkgConfig [{ src = "build/atk.pc", dest = "lib/pkgconfig/atk.pc" }]
+          prelude.ninjaInstallWithPkgConfig [{ src = "build/meson-private/atk.pc", dest = "lib/pkgconfig/atk.pc" }]
       }
 in
 
@@ -1722,7 +1752,9 @@
 let xcb-proto =
   λ(v : List Natural) →
     prelude.simplePackage { name = "xcb-proto", version = v } ⫽
-      { pkgUrl = "https://xorg.freedesktop.org/archive/individual/xcb/xcb-proto-${prelude.showVersion v}.tar.bz2" }
+      { pkgUrl = "https://xorg.freedesktop.org/archive/individual/xcb/xcb-proto-${prelude.showVersion v}.tar.bz2"
+      , pkgBuildDeps = [ prelude.unbounded "make" ]
+      }
 in
 
 let libxcb =
@@ -1740,7 +1772,9 @@
 let libpthread-stubs =
   λ(v : List Natural) →
     prelude.simplePackage { name = "libpthread-stubs", version = v } ⫽
-      { pkgUrl = "https://www.x.org/archive/individual/xcb/libpthread-stubs-${prelude.showVersion v}.tar.bz2" }
+      { pkgUrl = "https://www.x.org/archive/individual/xcb/libpthread-stubs-${prelude.showVersion v}.tar.bz2"
+      , pkgBuildDeps = [ prelude.unbounded "make" ]
+      }
 in
 
 let xorgConfigure =
@@ -1776,7 +1810,9 @@
   λ(name : Text) →
   λ(v : List Natural) →
     prelude.simplePackage { name = name, version = v } ⫽
-      { pkgUrl = "https://www.x.org/releases/individual/util/${name}-${prelude.showVersion v}.tar.bz2" }
+      { pkgUrl = "https://www.x.org/releases/individual/util/${name}-${prelude.showVersion v}.tar.bz2"
+      , pkgBuildDeps = [ prelude.unbounded "make" ]
+      }
 in
 
 let libXrender =
@@ -1884,19 +1920,31 @@
 let bzip2 =
   let cc = prelude.mkCCArg
   in
-  let bzipInstall =
+  -- TODO: use if... to switch only on static
+  λ(v : List Natural) →
+    let versionString = prelude.showVersion v
+    in
+    let bzipInstall =
+      λ(cfg : types.BuildVars) →
+        [ prelude.call (prelude.defaultCall ⫽ { program = prelude.makeExe cfg.buildOS
+                                              , arguments = cc cfg # [ "PREFIX=${cfg.installDir}", "install", "-j${Natural/show cfg.cpus}" ]
+                                              })
+        , prelude.copyFile "libbz2.so.${versionString}" "lib/libbz2.so.${versionString}"
+        , prelude.symlink "lib/libbz2.so.${versionString}" "lib/libbz2.so.1.0"
+        ]
+    in
+  let bzipShared =
     λ(cfg : types.BuildVars) →
       [ prelude.call (prelude.defaultCall ⫽ { program = prelude.makeExe cfg.buildOS
-                                            , arguments = cc cfg # [ "PREFIX=${cfg.installDir}", "install", "-j${Natural/show cfg.cpus}" ]
+                                            , arguments = [ "-f", "Makefile-libbz2_so" ]
                                             })
       ]
   in
 
-  λ(v : List Natural) →
     prelude.simplePackage { name = "bzip2", version = v } ⫽
-      { pkgUrl = "https://www.sourceware.org/pub/bzip2/bzip2-${prelude.showVersion v}.tar.gz"
+      { pkgUrl = "https://www.sourceware.org/pub/bzip2/bzip2-${versionString}.tar.gz"
       , configureCommand = prelude.doNothing
-      , buildCommand = prelude.doNothing
+      , buildCommand = bzipShared
       , installCommand = bzipInstall
       }
 in
@@ -1904,7 +1952,9 @@
 let expat =
   λ(v : List Natural) →
     prelude.simplePackage { name = "expat", version = v } ⫽
-      { pkgUrl = "https://github.com/libexpat/libexpat/releases/download/R_${prelude.underscoreVersion v}/expat-${prelude.showVersion v}.tar.bz2" }
+      { pkgUrl = "https://github.com/libexpat/libexpat/releases/download/R_${prelude.underscoreVersion v}/expat-${prelude.showVersion v}.tar.bz2"
+      , pkgBuildDeps = [ prelude.unbounded "make" ]
+      }
 in
 
 let gperf =
@@ -1990,7 +2040,9 @@
 
 let libXi =
   mkXLibDeps { name = "libXi"
-             , deps = [ prelude.unbounded "libXext" ]
+             , deps = [ prelude.unbounded "libXext"
+                      , prelude.unbounded "libXfixes"
+                      ]
              }
 in
 
@@ -2019,7 +2071,7 @@
 let at-spi-atk =
   λ(x : { version : List Natural, patch : Natural }) →
     mkGnomeNinja "at-spi2-atk" x ⫽
-      { pkgDeps = [ prelude.unbounded "at-spi2-core"
+      { pkgDeps = [ prelude.lowerBound { name = "at-spi2-core", lower = [2,32,2] }
                   , prelude.lowerBound { name = "atk", lower = [2,29,2] }
                   , prelude.unbounded "libxml2"
                   ]
@@ -2090,6 +2142,11 @@
       prelude.defaultPath cfg # [ { var = "LDFLAGS", value = (mkLDFlagsGtk cfg.linkDirs) ++ " -lpcre -lfribidi" }
                                 , prelude.mkPkgConfigVar cfg.linkDirs
                                 , prelude.mkLDPreload cfg.preloadLibs
+                                , prelude.mkXdgDataDirs cfg.shareDirs
+                                , prelude.mkCFlags cfg
+                                -- , prelude.mkLDFlags cfg.linkDirs
+                                -- , prelude.libPath cfg
+                                -- , prelude.mkLDRunPath cfg.linkDirs
                                 ]
   in
   let gtkConfig =
@@ -2115,6 +2172,7 @@
                   , prelude.lowerBound { name = "gdk-pixbuf", lower = [2,30,0] }
                   , prelude.unbounded "libXft"
                   , prelude.lowerBound { name = "libepoxy", lower = [1,4] }
+                  , prelude.unbounded "libXi"
                   ]
       }
 in
@@ -2223,6 +2281,7 @@
   λ(v : List Natural) →
     prelude.simplePackage { name = "libarchive", version = v } ⫽
       { pkgUrl = "https://www.libarchive.org/downloads/libarchive-${prelude.showVersion v}.tar.gz"
+      -- , pkgDeps = [ prelude.unbounded "libxml2" ]
       , pkgDeps = [ prelude.unbounded "xz"
                   -- , prelude.unbounded "bzip2"
                   , prelude.unbounded "zlib"
@@ -2433,7 +2492,9 @@
     prelude.simplePackage { name = "libmypaint", version = v } ⫽
       { pkgUrl = "https://github.com/mypaint/libmypaint/releases/download/v${versionString}/libmypaint-${versionString}.tar.xz"
       , pkgDeps = [ prelude.unbounded "json-c" ]
-      , pkgBuildDeps = [ prelude.unbounded "intltool" ]
+      , pkgBuildDeps = [ prelude.unbounded "intltool"
+                       , prelude.unbounded "gettext"
+                       ]
       }
 in
 
@@ -2695,7 +2756,10 @@
       { pkgDeps = [ prelude.lowerBound { name = "libxslt", lower = [1,1,8] }
                   , prelude.lowerBound { name = "libxml2", lower = [2,6,12] }
                   ]
-      , pkgBuildDeps = [ prelude.lowerBound { name = "intltool", lower = [0,35,0] } ]
+      , pkgBuildDeps = [ prelude.lowerBound { name = "intltool", lower = [0,35,0] }
+                       , prelude.unbounded "gettext"
+                       , prelude.unbounded "python2"
+                       ]
       , configureCommand = prelude.configureMkExes [ "py-compile" ]
       }
 in
@@ -3089,6 +3153,20 @@
       }
 in
 
+let pdfgrep =
+  λ(v : List Natural) →
+    prelude.simplePackage { name = "pdfgrep", version = v } ⫽
+      { pkgUrl = "https://pdfgrep.org/download/pdfgrep-${prelude.showVersion v}.tar.gz"
+      , pkgDeps = [ prelude.unbounded "poppler"
+                  , prelude.unbounded "libgcrypt"
+                  ]
+      , installCommand =
+          λ(cfg : types.BuildVars) →
+            prelude.installWithWrappers [ "pdfgrep" ] cfg
+              # prelude.symlinkManpages [ { file = "share/man/man1/pdfgrep.1", section = 1 } ]
+      }
+in
+
 let mpc =
   λ(v : List Natural) →
     prelude.simplePackage { name = "mpc", version = v } ⫽
@@ -3097,83 +3175,368 @@
       }
 in
 
--- let gcc =
-  -- λ(v : List Natural) →
-    -- let versionString = prelude.showVersion v in
-    -- prelude.simplePackage { name = "gcc", version = v } ⫽
-      -- { pkgUrl = "http://mirror.linux-ia64.org/gnu/gcc/releases/gcc-${versionString}/gcc-${versionString}.tar.xz"
-      -- , pkgDeps = [ prelude.unbounded "mpfr"
-                  -- , prelude.unbounded "mpc"
-                  -- ]
-      -- , configureCommand = prelude.configureWithFlags [ "--disable-multilib" ]
-      -- , pkgStream = False
-      -- }
--- in
+let gcc =
+  λ(v : List Natural) →
+    let versionString = prelude.showVersion v in
+    prelude.simplePackage { name = "gcc", version = v } ⫽
+      { pkgUrl = "http://mirror.linux-ia64.org/gnu/gcc/releases/gcc-${versionString}/gcc-${versionString}.tar.xz"
+      , configureCommand =
+          λ(cfg : types.BuildVars) →
+            [ prelude.call { program = "contrib/download_prerequisites"
+                           , arguments = [] : List Text
+                           , environment = None (List types.EnvVar)
+                           , procDir = None Text
+                           }
+            ] #
+              prelude.configureWithFlags [ "--disable-multilib" ] cfg
+      , installCommand = prelude.installWithBinaries [ "bin/gcc", "bin/g++", "bin/gcc-ar", "bin/gcc-nm", "bin/gfortran", "bin/gcc-ranlib" ]
+      , pkgBuildDeps = [ prelude.unbounded "curl"
+                       , prelude.unbounded "sed"
+                       ]
+      , pkgStream = False
+      }
+in
 
+let ruby =
+  λ(x : { version : List Natural, patch : Natural }) →
+    let versionString = prelude.showVersion x.version
+    in
+    let fullVersion = versionString ++ "." ++ Natural/show x.patch
+    in
+
+    prelude.simplePackage { name = "ruby", version = prelude.fullVersion x } ⫽
+      { pkgUrl = "https://cache.ruby-lang.org/pub/ruby/${versionString}/ruby-${fullVersion}.tar.gz"
+      , installCommand = prelude.installWithBinaries [ "bin/ruby", "bin/gem" ]
+      , pkgStream = False
+      , pkgDeps = [ prelude.unbounded "readline"
+                  , prelude.unbounded "openssl"
+                  ]
+      }
+in
+
+let poppler =
+  λ(v : List Natural) →
+    prelude.simplePackage { name = "poppler", version = v } ⫽ prelude.cmakePackage ⫽
+      { pkgUrl = "https://poppler.freedesktop.org/poppler-${prelude.showVersion v}.tar.xz"
+      , pkgDeps = [ prelude.unbounded "fontconfig"
+                  , prelude.unbounded "libopenjpeg"
+                  , prelude.unbounded "libjpeg-turbo"
+                  , prelude.unbounded "freetype"
+                  , prelude.unbounded "zlib"
+                  , prelude.unbounded "libpng"
+                  ]
+      , installCommand =
+          λ(cfg : types.BuildVars) →
+            prelude.cmakeInstall cfg
+              # prelude.mkLDPathWrappers cfg [ "pdfdetach"
+                                             , "pdffonts"
+                                             , "pdfimages"
+                                             , "pdfinfo"
+                                             , "pdfseparate"
+                                             , "pdfsig"
+                                             , "pdftocairo"
+                                             , "pdftohtml"
+                                             , "pdftoppm"
+                                             , "pdftops"
+                                             , "pdftotext"
+                                             , "pdfunite"
+                                             ]
+      }
+in
+
+let tesseract =
+  λ(v : List Natural) →
+    prelude.simplePackage { name = "tesseract", version = v } ⫽
+      { pkgUrl = "https://github.com/tesseract-ocr/tesseract/archive/${prelude.showVersion v}.tar.gz"
+      , pkgDeps = [ prelude.lowerBound { name = "leptonica", lower = [1,74] } ]
+      , pkgBuildDeps = [ prelude.unbounded "libtool"
+                       , prelude.unbounded "automake"
+                       , prelude.unbounded "pkg-config"
+                       ]
+      , configureCommand = prelude.autogenConfigure
+      , installCommand = prelude.installWithBinaries [ "bin/tesseract" ]
+      }
+in
+
+let leptonica =
+  λ(v : List Natural) →
+    prelude.simplePackage { name = "leptonica", version = v } ⫽
+      { pkgUrl = "http://leptonica.org/source/leptonica-${prelude.showVersion v}.tar.gz"
+      , pkgDeps = [ prelude.unbounded "zlib" ]
+      }
+in
+
+let grep =
+  λ(v : List Natural) →
+    prelude.makeGnuExe { name = "grep", version = v }
+in
+
+let phash =
+  λ(v : List Natural) →
+    prelude.simplePackage { name = "pHash", version = v } ⫽
+      { pkgUrl = "http://phash.org/releases/pHash-${prelude.showVersion v}.tar.gz"
+      , pkgDeps = [ prelude.unbounded "CImg"
+                  , prelude.unbounded "ffmpeg"
+                  , prelude.unbounded "libsndfile"
+                  , prelude.unbounded "libsamplerate"
+                  , prelude.unbounded "mpg123"
+                  , prelude.unbounded "libjpeg"
+                  , prelude.unbounded "libpng"
+                  , prelude.unbounded "fftw"
+                  ]
+      , pkgBuildDeps = [ prelude.unbounded "autoconf"
+                       , prelude.unbounded "automake"
+                       , prelude.unbounded "grep"
+                       , prelude.unbounded "coreutils"
+                       , prelude.unbounded "sed"
+                       , prelude.unbounded "libtool"
+                       ]
+      , configureCommand =
+          λ(cfg : types.BuildVars) →
+            [ prelude.patch (./patches/pHash.patch as Text)
+            , prelude.call { program = "autoreconf"
+                           , arguments = [ "-i" ]
+                           , environment = Some [ { var = "PATH", value = prelude.mkPathVar cfg.binDirs }
+                                                , prelude.mkAclocalPath cfg.shareDirs
+                                                ]
+                           , procDir = None Text
+                           }
+            ]
+              # prelude.defaultConfigure cfg
+      , pkgStream = False
+      }
+in
+
+let cimg =
+  λ(v : List Natural) →
+    let versionString = prelude.showVersion v in
+    prelude.simplePackage { name = "CImg", version = v } ⫽
+      { pkgUrl = "http://cimg.eu/files/CImg_${versionString}.zip"
+      , pkgBuildDeps = [] : List types.Dep
+      , configureCommand = prelude.doNothing
+      , buildCommand = prelude.doNothing
+      , installCommand =
+          λ(_ : types.BuildVars) →
+            [ prelude.copyFile "CImg.h" "include/CImg.h" ]
+      }
+in
+
+let ffmpeg =
+  λ(v : List Natural) →
+    prelude.simplePackage { name = "ffmpeg", version = v } ⫽
+      { pkgUrl = "https://ffmpeg.org/releases/ffmpeg-${prelude.showVersion v}.tar.bz2"
+      , pkgBuildDeps = [ prelude.unbounded "nasm" ]
+      -- TODO: cross-compile
+      , configureCommand = prelude.configureWithFlags [ "--enable-shared" ]
+      , pkgDeps = [ prelude.unbounded "bzip2" ]
+      , pkgStream = False
+      }
+in
+
+let libsndfile =
+  λ(v : List Natural) →
+    prelude.simplePackage { name = "libsndfile", version = v } ⫽
+      { pkgUrl = "http://www.mega-nerd.com/libsndfile/files/libsndfile-${prelude.showVersion v}.tar.gz" }
+in
+
+let libsamplerate =
+  λ(v : List Natural) →
+    prelude.simplePackage { name = "libsamplerate", version = v } ⫽
+      { pkgUrl = "http://www.mega-nerd.com/SRC/libsamplerate-${prelude.showVersion v}.tar.gz" }
+in
+
+let mpg123 =
+  λ(v : List Natural) →
+    prelude.simplePackage { name = "mpg123", version = v } ⫽
+      { pkgUrl = "http://www.mpg123.de/download/mpg123-${prelude.showVersion v}.tar.bz2" }
+in
+
+let time =
+  λ(v : List Natural) →
+    prelude.makeGnuExe { name = "time", version = v } ⫽
+        { pkgUrl = "https://ftp.gnu.org/gnu/time/time-${prelude.showVersion v}.tar.gz" }
+in
+
+let make =
+  λ(v : List Natural) →
+    prelude.makeGnuExe { name = "make", version = v } ⫽
+      { pkgUrl = "https://ftp.gnu.org/gnu/make/make-${prelude.showVersion v}.tar.bz2"
+      , configureCommand = prelude.configureWithPatch (./patches/make.patch as Text)
+      , buildCommand =
+          λ(cfg : types.BuildVars) →
+            [ prelude.call (prelude.defaultCall ⫽ { program = "./build.sh"
+                                                  , environment = Some (prelude.buildEnv cfg)
+                                                  })
+            ]
+      , installCommand =
+          λ(_ : types.BuildVars) →
+            [ prelude.copyFile "make" "bin/make"
+            , prelude.symlinkBinary "bin/make"
+            ]
+      , pkgBuildDeps = [ prelude.unbounded "patch" ]
+      }
+in
+
+let mercury =
+  let mercuryBuild =
+    λ(cfg : types.BuildVars) →
+      [ prelude.call (prelude.defaultCall ⫽ { program = "make"
+                                            , arguments = [ "PARALLEL=-j${Natural/show cfg.cpus}" ]
+                                            , environment = Some (prelude.buildEnv cfg)
+                                            })
+      ]
+  in
+  let mercuryCommon =
+      { pkgUrl = "http://dl.mercurylang.org/release/mercury-srcdist-14.01.1.tar.gz"
+      , pkgSubdir = "mercury-srcdist-14.01.1"
+      , buildCommand = mercuryBuild
+      }
+  in
+
+  prelude.simplePackage { name = "mercury", version = [14,1,1] } ⫽ mercuryCommon ⫽
+    { pkgBuildDeps = [ prelude.unbounded "flex" ]
+    , pkgStream = False
+    }
+in
+
+let qt =
+  λ(x : { version : List Natural, patch : Natural }) →
+    let versionString = prelude.showVersion x.version
+    in
+    let fullVersion = versionString ++ "." ++ Natural/show x.patch
+    in
+
+    prelude.simplePackage { name = "qt", version = prelude.fullVersion x } ⫽
+      { pkgUrl = "https://download.qt.io/archive/qt/${versionString}/${fullVersion}/single/qt-everywhere-src-${fullVersion}.tar.xz"
+      , pkgSubdir = "qt-everywhere-src-${fullVersion}"
+      , pkgBuildDeps = [ prelude.unbounded "flex"
+                       , prelude.unbounded "bison"
+                       , prelude.unbounded "pkg-config"
+                       , prelude.unbounded "gperf"
+                       , prelude.unbounded "perl"
+                       , prelude.unbounded "python2"
+                       , prelude.unbounded "git"
+                       ]
+      , pkgDeps = [ prelude.unbounded "fontconfig"
+                  , prelude.unbounded "mesa"
+                  , prelude.unbounded "dbus"
+                  , prelude.unbounded "freetype"
+                  , prelude.unbounded "harfbuzz"
+                  , prelude.unbounded "libjpeg-turbo"
+                  , prelude.unbounded "libpng"
+                  , prelude.unbounded "giflib"
+                  , prelude.unbounded "glib"
+                  ]
+      -- see: https://doc.qt.io/qt-5/linux-requirements.html#
+      -- TODO: -no-opengl in cross
+      , pkgStream = False
+      }
+in
+
+let lz4 =
+  λ(v : List Natural) →
+    prelude.simplePackage { name = "lz4", version = v } ⫽
+      { pkgUrl = "https://github.com/lz4/lz4/archive/v${prelude.showVersion v}.tar.gz"
+      , configureCommand = prelude.doNothing
+      , installCommand =
+        λ(cfg : types.BuildVars) →
+            [ prelude.call (prelude.defaultCall ⫽ { program = "make"
+                                                  , arguments = [ "PREFIX=${cfg.installDir}", "install" ]
+                                                  , environment = Some (prelude.buildEnv cfg)
+                                                  })
+            ]
+      }
+in
+
+let fftw =
+  λ(v : List Natural) →
+    prelude.simplePackage { name = "fftw", version = v } ⫽
+      { pkgUrl = "http://www.fftw.org/fftw-${prelude.showVersion v}.tar.gz"
+      , configureCommand = prelude.configureWithFlags [ "--enable-shared", "--enable-threads", "--with-combined-threads" ]
+      }
+in
+
+let icu =
+  λ(v : List Natural) →
+    prelude.simplePackage { name = "icu", version = v } ⫽
+      { pkgUrl = "http://download.icu-project.org/files/icu4c/${prelude.showVersion v}/icu4c-${prelude.underscoreVersion v}-src.tgz"
+      , pkgSubdir = "icu/source"
+      }
+in
+
+-- TODO: musl-ghc?
 -- https://hub.darcs.net/raichoo/hikari
 -- https://versaweb.dl.sourceforge.net/project/schilytools/schily-2019-03-29.tar.bz2
+-- https://busybox.net/downloads/busybox-1.31.0.tar.bz2
+-- https://github.com/jsoftware/jsource/archive/j807-release.tar.gz
+
 [ autoconf [2,69]
 , automake [1,16,1]
-, at-spi-atk { version = [2,33], patch = 1 }
-, at-spi-core { version = [2,33], patch = 1 }
-, atk { version = [2,33], patch = 1 }
+, at-spi-atk { version = [2,33], patch = 2 }
+, at-spi-core { version = [2,33], patch = 2 }
+, atk { version = [2,33], patch = 3 }
 , babl { version = [0,1], patch = 60 }
 , binutils [2,31]
-, bison [3,3]
+, bison [3,3,1]
 , bzip2 [1,0,6]
 , cairo [1,16,0]
 , chickenScheme [5,0,0]
+, cimg [2,6,6]
 , cmake { version = [3,13], patch = 4 }
 , compositeproto [0,4]
-, coreutils [8,30]
+, coreutils [8,31]
 , ctags [5,8]
-, curl [7,63,0]
+, curl [7,65,0]
 , damageproto [1,2,1]
-, dbus [1,12,10]
+, dbus [1,13,12]
 , diffutils [3,7]
 , dri2proto [2,8]
-, elfutils [0,175]
-, emacs [26,1]
+, elfutils [0,176]
+, emacs [26,2]
 , exiv2 [0,27,0]
 , expat [2,2,6]
 , feh [3,1,1]
+, ffmpeg [4,1,3]
+, fftw [3,3,8]
 , fixesproto [5,0]
 , fontconfig [2,13,1]
 , fossil [2,7]
-, flex [2,6,3]
+, flex [2,6,3] -- 2.6.4?
 , fltk { version = [1,3,4], patch = 2 }
 , freetype-prebuild [2,9,1] -- TODO: force both to have same version?
 , freetype [2,9,1]
 , fribidi [1,0,5]
-, gawk [4,2,1]
+, gawk [5,0,1]
 , gc [8,0,4]
--- , gcc [9,1,0]
+, gcc [9,1,0]
 , gdb [8,2]
 , gdk-pixbuf { version = [2,38], patch = 1 }
 , gegl { version = [0,4], patch = 12 }
-, gettext [0,19,8]
+, gettext [0,20,1]
 , gexiv2 { version = [0,11], patch = 0 }
 , gperf [3,1]
 , gperftools [2,7]
 , giflib [5,1,4]
 , git [2,19,2]
-, glib { version = [2,60], patch = 3 } -- TODO: bump to 2.59.0 once gobject-introspection supports it
+, glib { version = [2,60], patch = 4 }
 , glproto [1,4,17]
 , glu [9,0,0]
 , json-glib { version = [1,4], patch = 4 }
-, glibc [2,28]
+, glibc [2,29]
 , gmp [6,1,2]
-, gobject-introspection { version = [1,60], patch = 1 }
+, gobject-introspection { version = [1,60], patch = 2 }
 , gnome-doc-utils { version = [0,20], patch = 10 }
-, gnupg [2,2,15]
-, gnutls { version = [3,6], patch = 7 }
+, gnupg [2,2,16]
+, gnutls { version = [3,6], patch = 8 }
 , graphviz [2,40,1]
+, grep [3,3]
 , gsl [2,5]
 , gtk2 { version = [2,24], patch = 32 }
-, gtk3 { version = [3,24], patch = 8 }
+, gtk3 { version = [3,24], patch = 9 }
 , gzip [1,9]
-, harfbuzz [2,5,0]
+, harfbuzz [2,5,1]
 , htop [2,2,0]
+, icu [64,2]
 , imageMagick [7,0,8]
 , imlib2 [1,5,1]
 , inputproto [2,3,2]
@@ -3186,6 +3549,7 @@
 , krb5 [1,17]
 , lapack [3,8,0]
 , lcms2 [2,9]
+, leptonica [1,78,0]
 , libarchive [3,3,3]
 , libassuan [2,5,2]
 , libatomic_ops [7,6,10]
@@ -3196,7 +3560,7 @@
 , libdrm [2,4,96]
 , libepoxy [1,5,3]
 , libev [4,25]
-, libevent [2,1,8]
+, libevent [2,1,10]
 , libexif [0,6,21]
 , libffi [3,2,1]
 , libgcrypt [1,8,4]
@@ -3215,7 +3579,9 @@
 , libpthread-stubs [0,4]
 , libopenjpeg [2,3,1]
 , libotf [0,9,16]
+, libsamplerate [0,1,9]
 , libselinux [2,8]
+, libsndfile [1,0,28]
 , libsepol [2,8]
 , libsodium [1,0,17]
 , libsoup { version = [2,67], patch = 1 }
@@ -3226,46 +3592,49 @@
 , libuv [1,24,0]
 , libSM [1,2,3]
 , libthai [0,1,28]
-, libX11 [1,6,7]
-, libXau [1,0,8]
+, libX11 [1,6,8]
+, libXau [1,0,9]
 , libXaw [1,0,13]
 , libXaw3d [1,6,3]
 , libxcb [1,13]
-, libXcomposite [0,4,4]
-, libXdamage [1,1,4]
-, libXdmcp [1,1,2]
-, libXext [1,3,3]
+, libXcomposite [0,4,5]
+, libXdamage [1,1,5]
+, libXdmcp [1,1,3]
+, libXext [1,3,4]
 , libXfixes [5,0,3]
-, libXft [2,3,2]
-, libXi [1,7]
+, libXft [2,3,3]
+, libXi [1,7,10]
 , libXinerama [1,1,4]
 , libxml2 [2,9,8]
-, libXmu [1,1,2]
+, libXmu [1,1,3]
 , libXpm [3,5,12]
 , libXScrnSaver [1,2,3]
 , libxshmfence [1,3]
 , libxslt [1,1,33]
-, libXrandr [1,5,1]
+, libXrandr [1,5,2]
 , libXrender [0,9,10]
-, libXt [1,1,5]
+, libXt [1,2,0]
 , libXtst [1,2,3]
 , libXxf86vm [1,1,4]
 , llvm [8,0,0]
 , lmdb [0,9,23]
 , lua [5,3,5]
+, lz4 [1,9,1]
 , m17n [1,8,0]
 , m4 [1,4,18]
+, make [4,2,1]
 , mako [1,0,7]
 , markupSafe [1,0]
 , memcached [1,5,12]
 , mesa [19,0,5]
 , meson [0,50,1]
-, mpc [1,0,3]
-, mpfr [3,1,6] -- [4,0,2]
+, mpc [1,1,0]
+, mpfr [4,0,2]
+, mpg123 [1,25,10]
 , mosh [1,3,2]
 , motif [2,3,8]
 , musl [1,1,20]
-, nano [4,2]
+, nano [4,3]
 , nasm [2,14]
 , ncurses [6,1]
 , nginx [1,15,7]
@@ -3282,33 +3651,41 @@
 , patch [2,7]
 , pcre [8,42]
 , pcre2 [10,32]
-, perl5 [5,28,1]
-, pixman [0,36,0]
+, pdfgrep [2,1,2]
+, perl5 [5,30,0]
+, phash [0,9,6]
+, pixman [0,38,4]
 , pkg-config [0,29,2]
 , postgresql [11,1]
-, protobuf [3,7,1]
+, poppler [0,77,0]
+, mercury
+, protobuf [3,8,0]
 , pycairo [1,18,1]
 , pygobject { version = [2,28], patch = 7 }
 , pygtk { version = [2,24], patch = 0 }
 , python [2,7,16]
 , python [3,7,3]
 , qrencode [4,0,2]
+, qt { version = [5,13], patch = 0 }
 , ragel [6,10]
 , randrproto [1,5,0]
 , re2c [1,1,1]
 , readline [7,0]
 , recordproto [1,14,2]
 , renderproto [0,11,1]
+, ruby { version = [2,6], patch = 3 }
 , scour [0,37]
 , scrnsaverproto [1,2,2]
 , sdl2 [2,0,9]
-, sed [4,5]
+, sed [4,7]
 , shared-mime-info [1,10]
 , sqlite { year = 2018, version = [3,26,0] }
 , swig [3,0,12]
 , tar [1,30]
-, texinfo [6,6]
 , tcc [0,9,27]
+, texinfo [6,6]
+, tesseract [4,0,0]
+, time [1,9]
 , unistring [0,9,10]
 , util-linux { version = [2,33], patch = 1 }
 , util-macros [1,19,2]
@@ -3316,7 +3693,7 @@
 , valgrind [3,14,0]
 , vim [8,1]
 , wayland [1,16,0]
-, wget [1,20]
+, wget [1,20,3]
 , which [2,21]
 , xcb-proto [1,13]
 , xextproto [7,3,0]
@@ -3324,7 +3701,7 @@
 , xineramaproto [1,2]
 , xmlParser [2,44]
 , xproto [7,0,31]
-, xtrans [1,3,5]
+, xtrans [1,4,0]
 , xz [5,2,4]
 , zlib [1,2,11]
 ]
diff --git a/src/Package/C/Build.hs b/src/Package/C/Build.hs
--- a/src/Package/C/Build.hs
+++ b/src/Package/C/Build.hs
@@ -5,6 +5,7 @@
 
 import           Control.Concurrent          (getNumCapabilities)
 import           CPkgPrelude
+import           Data.List                   (isInfixOf)
 import           Data.Maybe                  (isJust)
 import qualified Data.Text                   as T
 import qualified Data.Text.IO                as TIO
@@ -16,6 +17,7 @@
 import           Package.C.Type
 import           System.Directory
 import           System.Directory.Executable (mkExecutable)
+import           System.Directory.Recursive  (getSubdirsRecursive)
 import           System.FilePath             (takeDirectory, takeFileName, (</>))
 import           System.FilePath.Glob
 import           System.IO.Temp              (withSystemTempDirectory)
@@ -45,6 +47,11 @@
     let actualBin = p </> file'
     liftIO $ createDirectoryIfMissing True binDir
     liftIO $ createFileLink actualBin (binDir </> takeFileName file')
+stepToProc _ p (SymlinkManpage file' sec) = do
+    manDir <- (</> ("share" </> "man" </> "man" ++ show sec)) <$> globalPkgDir
+    let actualMan = p </> file'
+    liftIO $ createDirectoryIfMissing True manDir
+    liftIO $ createFileLink actualMan (manDir </> takeFileName file')
 stepToProc _ p (Symlink tgt' lnk) = do
     let linkAbs = p </> lnk
     putDiagnostic ("Creating directory" ++ takeDirectory linkAbs ++ "...")
@@ -151,6 +158,13 @@
 -- diagnosticDirectory :: String -> (FilePath -> m a) -> m a
 -- diagnosticDirectory s f = f (s ++ "-diagnostic")
 
+getSubdirsWrap :: FilePath -> IO [FilePath]
+getSubdirsWrap fp = do
+    b <- doesDirectoryExist fp
+    if b
+        then (fp:) <$> getSubdirsRecursive fp
+        else pure []
+
 -- TODO: more complicated solver, garbage collector, and all that.
 -- Basically nix-style builds for C libraries
 forceBuildCPkg :: CPkg
@@ -172,7 +186,11 @@
 
         let p' = p </> pkgSubdir cpkg
 
-        lds <- liftIO $ getPreloads $ linkDirs buildVars
+        lds <- liftIO $ do
+            linkSubdirs <- concat <$> traverse getSubdirsWrap (linkDirs buildVars)
+            -- FIXME: this seems stupid
+            let curses = not . ("curses" `isInfixOf`)
+            getPreloads $ filter curses linkSubdirs
 
         let buildConfigured = buildVars { installDir = pkgDir, currentDir = p, preloadLibs = lds }
 
diff --git a/src/Package/C/Dhall/Type.hs b/src/Package/C/Dhall/Type.hs
--- a/src/Package/C/Dhall/Type.hs
+++ b/src/Package/C/Dhall/Type.hs
@@ -44,6 +44,7 @@
                     , procDir     :: Maybe T.Text
                     }
              | SymlinkBinary { file :: T.Text }
+             | SymlinkManpage { file :: T.Text, section :: Natural }
              | Symlink { tgt :: T.Text, linkName :: T.Text }
              | Write { contents :: T.Text, file :: T.Text }
              | CopyFile { src :: T.Text, dest :: T.Text }
diff --git a/src/Package/C/Type.hs b/src/Package/C/Type.hs
--- a/src/Package/C/Type.hs
+++ b/src/Package/C/Type.hs
@@ -36,6 +36,7 @@
                     , procDir     :: Maybe String
                     }
              | SymlinkBinary { file :: String }
+             | SymlinkManpage { file :: String, section :: Int }
              | Symlink { tgt :: String, linkName :: String }
              | Write { contents :: T.Text, file :: FilePath }
              | CopyFile { src :: FilePath, dest :: FilePath }
@@ -64,6 +65,7 @@
 commandDhallToCommand (Dhall.MakeExecutable exe)  = MakeExecutable (T.unpack exe)
 commandDhallToCommand (Dhall.Call p as env proc)  = Call (T.unpack p) (T.unpack <$> as) (fmap envVarDhallToEnvVar <$> env) (T.unpack <$> proc)
 commandDhallToCommand (Dhall.SymlinkBinary b)     = SymlinkBinary (T.unpack b)
+commandDhallToCommand (Dhall.SymlinkManpage b s)  = SymlinkManpage (T.unpack b) (fromIntegral s)
 commandDhallToCommand (Dhall.Write out fp)        = Write out (T.unpack fp)
 commandDhallToCommand (Dhall.CopyFile src' dest') = CopyFile (T.unpack src') (T.unpack dest')
 commandDhallToCommand (Dhall.Symlink t l)         = Symlink (T.unpack t) (T.unpack l)
