diff --git a/tests/CapsuleTest.pm b/tests/CapsuleTest.pm
index 1097239fe5c685e125c7be0fb43e3f54b4d51f36..0e3fb4435cedf20ff4b93bfea02480fbbbde7ff6 100644
--- a/tests/CapsuleTest.pm
+++ b/tests/CapsuleTest.pm
@@ -34,6 +34,7 @@ our @EXPORT = qw(
     run_ok
     run_verbose
     skip_all_unless_bwrap
+    skip_all_unless_nm
     $CAPSULE_INIT_PROJECT_TOOL
     $CAPSULE_SYMBOLS_TOOL
     $CAPSULE_VERSION_TOOL
@@ -208,6 +209,23 @@ sub skip_all_unless_bwrap {
     }
 }
 
+=item skip_all_unless_nm()
+
+If we cannot run B<nm>(1) to implement B<get_symbols_with_nm>, log a
+TAP report that all tests have been skipped (as if via
+C<plan skip_all =E<gt> ...>), and exit.
+
+=cut
+
+sub skip_all_unless_nm {
+    if (! run([split(' ', $NM),
+                qw(--dynamic --extern-only --defined-only
+                --with-symbol-versions /bin/true)], '>/dev/null')) {
+        plan(skip_all =>
+            'Cannot run nm (no support for --with-symbol-versions?)');
+    }
+}
+
 =item get_symbols_with_nm(I<LIBRARY>)
 
 Return a list of symbols found in I<LIBRARY>, in the same format
diff --git a/tests/gl-shim.pl b/tests/gl-shim.pl
index 8db5fc17f85599ab3e9024a37998b5ecf088478b..857b18d7d0f6705e28b4b40549e0c2d59f88ce0e 100755
--- a/tests/gl-shim.pl
+++ b/tests/gl-shim.pl
@@ -30,6 +30,8 @@ use lib $FindBin::Bin;
 
 use CapsuleTest;
 
+skip_all_unless_nm;
+
 my $test_tempdir = File::Temp->newdir();
 diag "Working directory: $test_tempdir";
 chdir $test_tempdir;
diff --git a/tests/init-project.pl b/tests/init-project.pl
index 36b6a75a75cf830db94668ec36eecfc8ef9d8f60..f424afbe6b8bfe4f9afcc7131d8cea6a6516c94d 100755
--- a/tests/init-project.pl
+++ b/tests/init-project.pl
@@ -30,6 +30,8 @@ use lib $FindBin::Bin;
 
 use CapsuleTest;
 
+skip_all_unless_nm;
+
 my $test_tempdir = File::Temp->newdir();
 diag "Working directory: $test_tempdir";
 chdir $test_tempdir;