diff --git a/scripts/lib/checklayer/cases/bsp.py b/scripts/lib/checklayer/cases/bsp.py
index b76163fb56..e9472fd512 100644
--- a/scripts/lib/checklayer/cases/bsp.py
+++ b/scripts/lib/checklayer/cases/bsp.py
@@ -5,7 +5,7 @@
 
 import unittest
 
-from checklayer import LayerType, get_signatures, check_command, get_depgraph
+from checklayer import LayerType, check_command, get_depgraph
 from checklayer.case import OECheckLayerTestCase
 
 class BSPCheckLayer(OECheckLayerTestCase):
@@ -45,10 +45,9 @@ class BSPCheckLayer(OECheckLayerTestCase):
         msg = []
         for machine in self.td['machines']:
             # In contrast to test_machine_signatures() below, errors are fatal here.
-            try:
-                get_signatures(self.td['builddir'], failsafe=False, machine=machine)
-            except RuntimeError as ex:
-                msg.append(str(ex))
+            error = self.tc.world_error(machine)
+            if error is not None:
+                msg.append(str(error))
         if msg:
             msg.insert(0, 'The following machines broke a world build:')
             self.fail('\n'.join(msg))
@@ -80,7 +79,7 @@ class BSPCheckLayer(OECheckLayerTestCase):
         tunes = {}
         # Preserve ordering of machines as chosen by the user.
         for machine in self.td['machines']:
-            curr_sigs, tune2tasks = get_signatures(self.td['builddir'], failsafe=True, machine=machine)
+            curr_sigs, tune2tasks = self.tc.world_signatures(machine)
             # Invert the tune -> [tasks] mapping.
             tasks2tune = {}
             for tune, tasks in tune2tasks.items():
diff --git a/scripts/lib/checklayer/context.py b/scripts/lib/checklayer/context.py
index 4de8f668fd..19bd59a709 100644
--- a/scripts/lib/checklayer/context.py
+++ b/scripts/lib/checklayer/context.py
@@ -9,9 +9,44 @@ import glob
 import re
 
 from oeqa.core.context import OETestContext
+from checklayer import get_signatures
 
 class CheckLayerTestContext(OETestContext):
     def __init__(self, td=None, logger=None, layer=None, test_software_layer_signatures=True):
         super(CheckLayerTestContext, self).__init__(td, logger)
         self.layer = layer
         self.test_software_layer_signatures = test_software_layer_signatures
+        self._world_runs = {}
+
+    def _world_run(self, machine):
+        '''
+        Calls get_signatures(failsafe=False) once per machine and remembers
+        the outcome: the signatures, or the RuntimeError raised instead.
+        '''
+        if machine not in self._world_runs:
+            try:
+                self._world_runs[machine] = get_signatures(self.td['builddir'], failsafe=False, machine=machine)
+            except RuntimeError as ex:
+                self._world_runs[machine] = ex
+        return self._world_runs[machine]
+
+    def world_error(self, machine):
+        '''
+        Returns the RuntimeError that get_signatures(failsafe=False) raises
+        for the given machine, or None if world can be built.
+        '''
+        result = self._world_run(machine)
+        if isinstance(result, RuntimeError):
+            return result
+        return None
+
+    def world_signatures(self, machine):
+        '''
+        Returns (sigs, tune2tasks) like get_signatures(failsafe=True). When
+        world can be built, -k makes no difference, so the signatures of the
+        run without it are reused; otherwise bitbake runs again with -k.
+        '''
+        result = self._world_run(machine)
+        if isinstance(result, RuntimeError):
+            return get_signatures(self.td['builddir'], failsafe=True, machine=machine)
+        return result
