diff --git a/src/briefcase/platforms/macOS/__init__.py b/src/briefcase/platforms/macOS/__init__.py index a6c4b48df..c075c04d0 100644 --- a/src/briefcase/platforms/macOS/__init__.py +++ b/src/briefcase/platforms/macOS/__init__.py @@ -54,12 +54,26 @@ def run_app(self, app: BaseConfig, **kwargs): print() print("[{app.app_name}] Following system log output (type CTRL-C to stop log)...".format(app=app)) print("=" * 75) + # Streaming the system log is... a mess. The system log contains a + # *lot* of noise from other processes; even if you filter by + # process, there's a lot of macOS-generated noise. It's very + # difficult to extract just the "user generated" stdout/err log + # messages. + # + # The following sets up a log stream filter that looks for: + # 1. a log sender that matches that app binary; or, + # 2. a log sender of libffi, and a process that matches the app binary. + # Case (1) works for pre-Python 3.9 static linked binaries. + # Case (2) works for Python 3.9+ dynamic linked binaries. self.subprocess.run( [ "log", "stream", "--style", "compact", - "--predicate", 'senderImagePath=="{sender}"'.format( + "--predicate", + 'senderImagePath=="{sender}"' + ' OR (processImagePath=="{sender}"' + ' AND senderImagePath=="/usr/lib/libffi.dylib")'.format( sender=str(self.binary_path(app) / "Contents" / "MacOS" / app.formal_name) ) ], diff --git a/tests/platforms/macOS/app/test_run.py b/tests/platforms/macOS/app/test_run.py index 649d2dcd9..bd82ab872 100644 --- a/tests/platforms/macOS/app/test_run.py +++ b/tests/platforms/macOS/app/test_run.py @@ -25,7 +25,10 @@ def test_run_app(first_app_config, tmp_path): [ 'log', 'stream', '--style', 'compact', - '--predicate', 'senderImagePath=="{bin_path}/Contents/MacOS/First App"'.format(bin_path=bin_path) + '--predicate', + 'senderImagePath=="{bin_path}/Contents/MacOS/First App"' + ' OR (processImagePath=="{bin_path}/Contents/MacOS/First App"' + ' AND senderImagePath=="/usr/lib/libffi.dylib")'.format(bin_path=bin_path) ], check=True, ) @@ -78,7 +81,10 @@ def test_run_app_log_stream_failed(first_app_config, tmp_path): [ 'log', 'stream', '--style', 'compact', - '--predicate', 'senderImagePath=="{bin_path}/Contents/MacOS/First App"'.format(bin_path=bin_path) + '--predicate', + 'senderImagePath=="{bin_path}/Contents/MacOS/First App"' + ' OR (processImagePath=="{bin_path}/Contents/MacOS/First App"' + ' AND senderImagePath=="/usr/lib/libffi.dylib")'.format(bin_path=bin_path) ], check=True, )