diff --git a/Makefile.am b/Makefile.am
index cd08fd013bedf81bf02c828bc5df2f5f4a358a64..06dcf2b0efe224adb6a4538e54e0be8fa89b4ec4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -106,7 +106,11 @@ capsule_elf_dump_LDADD          = utils/libutils.la -ldl
 capsule_elf_dump_CFLAGS         = $(AM_CFLAGS)
 capsule_elf_dump_LDFLAGS        = $(AM_LDFLAGS) $(tools_ldflags)
 
-capsule_capture_libs_SOURCES = utils/capture-libs.c utils/tools.c utils/tools.h
+capsule_capture_libs_SOURCES = utils/capture-libs.c \
+                               utils/library-cmp.c  \
+                               utils/library-cmp.h  \
+                               utils/tools.c        \
+                               utils/tools.h
 capsule_capture_libs_LDADD   = utils/libld.la
 capsule_capture_libs_LDFLAGS = $(AM_LDFLAGS) $(tools_ldflags)
 
diff --git a/utils/capture-libs.c b/utils/capture-libs.c
index 7ae394f345cb5aadd7f625dbac6a468d39040d39..c2d09270924b078ebcc9aa7bd877d8eede5700e6 100644
--- a/utils/capture-libs.c
+++ b/utils/capture-libs.c
@@ -32,6 +32,7 @@
 
 #include "debug.h"
 #include "ld-libs.h"
+#include "library-cmp.h"
 #include "tools.h"
 #include "utils.h"
 
@@ -137,19 +138,6 @@ static int dest_fd = -1;
 #define strstarts(str, start) \
   (strncmp( str, start, strlen( start ) ) == 0)
 
-/* Equivalent to GNU basename(3) from string.h, but not POSIX
- * basename(3) from libgen.h. */
-static const char *my_basename (const char *path)
-{
-  const char *ret = strrchr( path, '/' );
-
-  if( ret == NULL )
-      return path;
-
-  assert( ret[0] == '/' );
-  return ret + 1;
-}
-
 static bool resolve_ld_so ( const char *prefix,
                             char path[PATH_MAX],
                             const char **within_prefix,
@@ -334,86 +322,6 @@ static bool capture_patterns( const char * const *patterns,
                               capture_flags flags,
                               int *code, char **message );
 
-/*
- * library_cmp_by_name:
- * @soname: The library we are interested in, used in debug logging
- * @left_path: The path to the "left" instance of the library
- * @left_from: Arbitrary description of the container/provider/sysroot
- *  where we found @left_path, used in debug logging
- * @right_path: The path to the "right" instance of the library
- * @right_from: Arbitrary description of the container/provider/sysroot
- *  where we found @right_path, used in debug logging
- *
- * Attempt to determine whether @left_path is older than, newer than or
- * the same as than @right_path by inspecting their filenames.
- *
- * Return a strcmp-style result: negative if left < right,
- * positive if left > right, zero if left == right or if left and right
- * are non-comparable.
- */
-static int
-library_cmp_by_name( const char *soname,
-                     const char *left_path,
-                     const char *left_from,
-                     const char *right_path,
-                     const char *right_from )
-{
-  _capsule_autofree char *left_realpath = NULL;
-  _capsule_autofree char *right_realpath = NULL;
-  const char *left_basename;
-  const char *right_basename;
-
-  // This might look redundant when our arguments come from the ld_libs,
-  // but resolve_symlink_prefixed() doesn't chase symlinks if the
-  // prefix is '/' or empty.
-  left_realpath = realpath( left_path, NULL );
-  right_realpath = realpath( right_path, NULL );
-  left_basename = my_basename( left_realpath );
-  right_basename = my_basename( right_realpath );
-
-  DEBUG( DEBUG_TOOL,
-         "Comparing %s \"%s\" from \"%s\" with "
-         "\"%s\" from \"%s\"",
-         soname, left_basename, left_from, right_basename, right_from );
-
-  if( strcmp( left_basename, right_basename ) == 0 )
-  {
-    DEBUG( DEBUG_TOOL,
-           "Name of %s \"%s\" from \"%s\" compares the same as "
-           "\"%s\" from \"%s\"",
-           soname, left_basename, left_from, right_basename, right_from );
-    return 0;
-  }
-
-  if( strcmp( soname, left_basename ) == 0 )
-  {
-    /* In some distributions (Debian, Ubuntu, Manjaro)
-     * libgcc_s.so.1 is a plain file, not a symlink to a
-     * version-suffixed version. We cannot know just from the name
-     * whether that's older or newer, so assume equal. The caller is
-     * responsible for figuring out which one to prefer. */
-    DEBUG( DEBUG_TOOL,
-           "Unversioned %s \"%s\" from \"%s\" cannot be compared with "
-           "\"%s\" from \"%s\"",
-           soname, left_basename, left_from,
-           right_basename, right_from );
-    return 0;
-  }
-
-  if( strcmp( soname, right_basename ) == 0 )
-  {
-    /* The same, but the other way round */
-    DEBUG( DEBUG_TOOL,
-           "%s \"%s\" from \"%s\" cannot be compared with "
-           "unversioned \"%s\" from \"%s\"",
-           soname, left_basename, left_from,
-           right_basename, right_from );
-    return 0;
-  }
-
-  return ( strverscmp( left_basename, right_basename ) );
-}
-
 static bool
 capture_one( const char *soname, capture_flags flags,
              int *code, char **message )
@@ -478,7 +386,7 @@ capture_one( const char *soname, capture_flags flags,
             break;
         }
 
-        needed_basename = my_basename( needed_name );
+        needed_basename = _capsule_basename( needed_name );
 
         if( !option_glibc )
         {
diff --git a/utils/library-cmp.c b/utils/library-cmp.c
new file mode 100644
index 0000000000000000000000000000000000000000..d7644525bb1cb6edcdd4d16da3ad2be7b912d7c4
--- /dev/null
+++ b/utils/library-cmp.c
@@ -0,0 +1,104 @@
+// Copyright © 2020 Collabora Ltd
+
+// This file is part of libcapsule.
+
+// libcapsule is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 2.1 of the
+// License, or (at your option) any later version.
+
+// libcapsule is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Lesser General Public License for more details.
+
+// You should have received a copy of the GNU Lesser General Public
+// License along with libcapsule.  If not, see <http://www.gnu.org/licenses/>.
+
+#include "library-cmp.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "debug.h"
+#include "utils.h"
+
+/*
+ * library_cmp_by_name:
+ * @soname: The library we are interested in, used in debug logging
+ * @left_path: The path to the "left" instance of the library
+ * @left_from: Arbitrary description of the container/provider/sysroot
+ *  where we found @left_path, used in debug logging
+ * @right_path: The path to the "right" instance of the library
+ * @right_from: Arbitrary description of the container/provider/sysroot
+ *  where we found @right_path, used in debug logging
+ *
+ * Attempt to determine whether @left_path is older than, newer than or
+ * the same as than @right_path by inspecting their filenames.
+ *
+ * Return a strcmp-style result: negative if left < right,
+ * positive if left > right, zero if left == right or if left and right
+ * are non-comparable.
+ */
+int
+library_cmp_by_name( const char *soname,
+                     const char *left_path,
+                     const char *left_from,
+                     const char *right_path,
+                     const char *right_from )
+{
+    _capsule_autofree char *left_realpath = NULL;
+    _capsule_autofree char *right_realpath = NULL;
+    const char *left_basename;
+    const char *right_basename;
+
+    // This might look redundant when our arguments come from the ld_libs,
+    // but resolve_symlink_prefixed() doesn't chase symlinks if the
+    // prefix is '/' or empty.
+    left_realpath = realpath( left_path, NULL );
+    right_realpath = realpath( right_path, NULL );
+    left_basename = _capsule_basename( left_realpath );
+    right_basename = _capsule_basename( right_realpath );
+
+    DEBUG( DEBUG_TOOL,
+           "Comparing %s \"%s\" from \"%s\" with "
+           "\"%s\" from \"%s\"",
+           soname, left_basename, left_from, right_basename, right_from );
+
+    if( strcmp( left_basename, right_basename ) == 0 )
+    {
+        DEBUG( DEBUG_TOOL,
+               "Name of %s \"%s\" from \"%s\" compares the same as "
+               "\"%s\" from \"%s\"",
+               soname, left_basename, left_from, right_basename, right_from );
+        return 0;
+    }
+
+    if( strcmp( soname, left_basename ) == 0 )
+    {
+        /* In some distributions (Debian, Ubuntu, Manjaro)
+         * libgcc_s.so.1 is a plain file, not a symlink to a
+         * version-suffixed version. We cannot know just from the name
+         * whether that's older or newer, so assume equal. The caller is
+         * responsible for figuring out which one to prefer. */
+        DEBUG( DEBUG_TOOL,
+               "Unversioned %s \"%s\" from \"%s\" cannot be compared with "
+               "\"%s\" from \"%s\"",
+               soname, left_basename, left_from,
+               right_basename, right_from );
+        return 0;
+    }
+
+    if( strcmp( soname, right_basename ) == 0 )
+    {
+        /* The same, but the other way round */
+        DEBUG( DEBUG_TOOL,
+               "%s \"%s\" from \"%s\" cannot be compared with "
+               "unversioned \"%s\" from \"%s\"",
+               soname, left_basename, left_from,
+               right_basename, right_from );
+        return 0;
+    }
+
+    return ( strverscmp( left_basename, right_basename ) );
+}
diff --git a/utils/library-cmp.h b/utils/library-cmp.h
new file mode 100644
index 0000000000000000000000000000000000000000..4233a85be69a111780bc5537d608e1982c1868bc
--- /dev/null
+++ b/utils/library-cmp.h
@@ -0,0 +1,24 @@
+// Copyright © 2020 Collabora Ltd
+
+// This file is part of libcapsule.
+
+// libcapsule is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation; either version 2.1 of the
+// License, or (at your option) any later version.
+
+// libcapsule is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Lesser General Public License for more details.
+
+// You should have received a copy of the GNU Lesser General Public
+// License along with libcapsule.  If not, see <http://www.gnu.org/licenses/>.
+
+#pragma once
+
+int library_cmp_by_name( const char *soname,
+                         const char *container_path,
+                         const char *container_root,
+                         const char *provider_path,
+                         const char *provider_root );
diff --git a/utils/utils.c b/utils/utils.c
index 7da3b69be3252b4d38065f5d9189e7a1f475afe2..267f4a19aa8736ea537e6d568bff781ccbc07c05 100644
--- a/utils/utils.c
+++ b/utils/utils.c
@@ -680,3 +680,28 @@ _capsule_set_error( int *code_dest, char **message_dest,
         va_end( ap );
     }
 }
+
+/*
+ * _capsule_basename:
+ * @path: A path
+ *
+ * Return the part of @path after the last directory separator, or @path
+ * if there is no directory separator at all, or an empty string if @path
+ * ends with a directory separator.
+ *
+ * Equivalent to GNU basename(3) from string.h, but not POSIX
+ * basename(3) from libgen.h.
+ *
+ * Returns: (transfer none): A pointer into @path
+ */
+const char *
+_capsule_basename (const char *path)
+{
+  const char *ret = strrchr( path, '/' );
+
+  if( ret == NULL )
+      return path;
+
+  assert( ret[0] == '/' );
+  return ret + 1;
+}
diff --git a/utils/utils.h b/utils/utils.h
index e14af8665efef8c66dc3f551655e69ed7bbb94ad..34a533f6e22d5f0ecc24ce1804772d390339e7a4 100644
--- a/utils/utils.h
+++ b/utils/utils.h
@@ -230,3 +230,5 @@ _capsule_clear( void *pp )
 #ifndef static_assert
 # define static_assert(expr, message) _Static_assert(expr, message)
 #endif
+
+const char *_capsule_basename (const char *path);