From faf5959c1d3f18140fefa5e5fbc3b70450254158 Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Mon, 20 Jul 2026 00:49:19 +0200 Subject: [PATCH] fix: Don't recompile Flutter apps that already failed to compile The `flutter-app` directive dedupes compilation via `COMPILED`, but that list is only appended to after a successful compile, copy and assert. When `flutter build web` fails, the target is never recorded, so every page that references the same app pays for another full compile of an app that is guaranteed to fail again in exactly the same way. Failures are now recorded in `FAILED` alongside the error, and subsequent pages re-report the stored error instead of recompiling. Every referencing page still surfaces the error, so nothing is silently swallowed. --- doc/_sphinx/extensions/flutter_app.py | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/doc/_sphinx/extensions/flutter_app.py b/doc/_sphinx/extensions/flutter_app.py index dd10ff9376f..2a45dd96c2c 100644 --- a/doc/_sphinx/extensions/flutter_app.py +++ b/doc/_sphinx/extensions/flutter_app.py @@ -75,6 +75,10 @@ class FlutterAppDirective(SphinxDirective): } # Static list of targets that were already compiled during the build COMPILED = [] + # Static map of targets whose compilation failed, to the error it failed + # with. Compiling is expensive and deterministic within a single build, so + # a target that failed once is not attempted again. + FAILED = {} def __init__(self, *args, **kwds): super().__init__(*args, **kwds) @@ -172,13 +176,24 @@ def _ensure_compiled(self): ) if not need_compiling: return + # A target that already failed to compile would fail again in exactly + # the same way, so report the original error instead of paying for + # another full `flutter build web`. + previous_error = FlutterAppDirective.FAILED.get(self.source_dir) + if previous_error is not None: + raise self.error(previous_error) self.logger.info('Compiling Flutter app [%s]' % self.app_name) - self._compile_source() - self._copy_compiled() - self._create_index_html() + try: + self._compile_source() + self._copy_compiled() + self._create_index_html() + assert os.path.isfile(self.target_dir + '/main.dart.js') + assert os.path.isfile(self.target_dir + '/index.html') + except Exception as e: + error = getattr(e, 'msg', str(e)) + FlutterAppDirective.FAILED[self.source_dir] = error + raise self.logger.info(' + copied into ' + self.target_dir) - assert os.path.isfile(self.target_dir + '/main.dart.js') - assert os.path.isfile(self.target_dir + '/index.html') FlutterAppDirective.COMPILED.append(self.source_dir) def _compile_source(self):