diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4e3a676c..b2f85668 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -82,6 +82,7 @@ jobs: build_system: ['cocoapods', 'spm'] env: SERIOUS_PYTHON_VERSION: ${{ matrix.python_version }} + BRIDGE_EXAMPLE_TEST_PYDANTIC: "1" steps: - name: Checkout repository uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 @@ -124,7 +125,7 @@ jobs: if [ "${{ matrix.build_system }}" = "cocoapods" ]; then export SERIOUS_PYTHON_DARWIN_SPM=false fi - dart run serious_python:main package app/src --platform Darwin --python-version ${{ matrix.python_version }} + dart run serious_python:main package app/src --platform Darwin --python-version ${{ matrix.python_version }} --requirements "pydantic>=2,<3" if [ "${{ matrix.build_system }}" = "spm" ]; then export SP_NATIVE_SET="$(cat build/.serious_python_spm_key)" fi @@ -370,6 +371,7 @@ jobs: python_version: ['3.12', '3.13', '3.14'] env: SERIOUS_PYTHON_VERSION: ${{ matrix.python_version }} + BRIDGE_EXAMPLE_TEST_PYDANTIC: "1" steps: - name: Checkout repository uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 @@ -397,7 +399,7 @@ jobs: working-directory: "src/serious_python/example/bridge_example" shell: bash run: | - dart run serious_python:main package app/src --platform Windows --python-version ${{ matrix.python_version }} + dart run serious_python:main package app/src --platform Windows --python-version ${{ matrix.python_version }} --requirements "pydantic>=2,<3" # bash + pipefail so the test step actually fails when flutter fails # (default PowerShell shell on windows runners eats the failure when # piping into tail). @@ -446,6 +448,7 @@ jobs: title: ARM64 env: SERIOUS_PYTHON_VERSION: ${{ matrix.python_version }} + BRIDGE_EXAMPLE_TEST_PYDANTIC: "1" steps: - name: Checkout repository uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 @@ -498,7 +501,8 @@ jobs: flutter pub get dart run serious_python:main package app/src \ --platform Linux \ - --python-version ${{ matrix.python_version }} + --python-version ${{ matrix.python_version }} \ + --requirements "pydantic>=2,<3" set -o pipefail # Three back-to-back `xvfb-run` invocations race for display diff --git a/src/serious_python/CHANGELOG.md b/src/serious_python/CHANGELOG.md index 99556fd5..1bef7fd3 100644 --- a/src/serious_python/CHANGELOG.md +++ b/src/serious_python/CHANGELOG.md @@ -1,3 +1,8 @@ +## 6.1.2 + +* Windows Debug builds (`flutter test`, `flutter run`) use the release CPython, so compiled packages such as `pydantic-core` or `numpy` import there ([#261](https://github.com/flet-dev/serious-python/pull/261), [flet-dev/flet#7020](https://github.com/flet-dev/flet/discussions/7020)). +* Fix native Python extension imports on Linux, including `pydantic-core`, which failed with unresolved CPython symbols such as `PyExc_RecursionError` ([#261](https://github.com/flet-dev/serious-python/pull/261)). + ## 6.1.1 * Release Windows apps no longer ship Python's debug modules (`*_d.pyd`), about 10 MB each ([#260](https://github.com/flet-dev/serious-python/pull/260)). diff --git a/src/serious_python/example/bridge_example/app/src/main.py b/src/serious_python/example/bridge_example/app/src/main.py index 1b10d4fb..c0068719 100644 --- a/src/serious_python/example/bridge_example/app/src/main.py +++ b/src/serious_python/example/bridge_example/app/src/main.py @@ -85,6 +85,25 @@ def _emit(event: dict) -> None: dart_bridge.send_bytes(control_port, json.dumps(event).encode("utf-8")) +# Desktop CI packages Pydantic v2 to exercise its native pydantic-core wheel. +# Validate before registering handlers so a failure prevents test readiness. +if os.environ.get("BRIDGE_EXAMPLE_TEST_PYDANTIC") == "1": + try: + from pydantic import BaseModel + + class DependencyProbe(BaseModel): + value: int + + assert DependencyProbe.model_validate({"value": "42"}).value == 42 + print("[bridge_example] Pydantic native extension validation passed", flush=True) + except Exception: + import traceback + + # Native stderr is not forwarded by every integration-test runner. + _emit({"event": "startup_error", "message": traceback.format_exc()}) + raise + + def on_control(payload: bytes) -> None: global counter if not payload: diff --git a/src/serious_python/example/bridge_example/integration_test/_helpers.dart b/src/serious_python/example/bridge_example/integration_test/_helpers.dart index a0dc7f5e..2c5bc2b5 100644 --- a/src/serious_python/example/bridge_example/integration_test/_helpers.dart +++ b/src/serious_python/example/bridge_example/integration_test/_helpers.dart @@ -23,6 +23,9 @@ Future bootAndAwaitReady(WidgetTester tester) async { // readiness signal for the control channel. final deadline = DateTime.now().add(const Duration(seconds: 30)); while (handle.pythonVersion.value == null) { + if (handle.startupError != null) { + throw StateError('Python startup failed:\n${handle.startupError}'); + } if (DateTime.now().isAfter(deadline)) { throw TimeoutException( 'Python control handler never responded with version event'); diff --git a/src/serious_python/example/bridge_example/lib/main.dart b/src/serious_python/example/bridge_example/lib/main.dart index 5db835f3..a9849725 100644 --- a/src/serious_python/example/bridge_example/lib/main.dart +++ b/src/serious_python/example/bridge_example/lib/main.dart @@ -38,6 +38,9 @@ class BridgeExampleHandle { /// event arrives. final ValueNotifier pythonVersion = ValueNotifier(null); + /// Startup traceback sent over the bridge when a dependency check fails. + String? startupError; + /// Send a JSON control op (Dart → Python) on the control channel. void sendControl(Map op) { final bytes = Uint8List.fromList(utf8.encode(jsonEncode(op))); @@ -72,15 +75,6 @@ void main() { BridgeExampleHandle._instance = BridgeExampleHandle._(control, echo); - // Fire-and-forget: Python's main.py blocks forever waiting for messages. - // Awaiting SeriousPython.run() would deadlock the UI. - unawaited(SeriousPython.run( - environmentVariables: { - _controlPortEnv: '${control.port}', - _echoPortEnv: '${echo.port}', - }, - )); - runApp(const BridgeExampleApp()); } @@ -101,6 +95,15 @@ class _BridgeExampleAppState extends State { final handle = BridgeExampleHandle.instance; _controlSub = handle.controlBridge.messages.listen(_onControl); + // Subscribe before starting Python so even an immediate startup failure + // reaches the test harness. main.py blocks forever, so don't await it. + unawaited(SeriousPython.run( + environmentVariables: { + _controlPortEnv: '${handle.controlBridge.port}', + _echoPortEnv: '${handle.echoBridge.port}', + }, + )); + // Request the Python version once Python has had a moment to register // its handler. sendControl() retries internally if the handler isn't // ready yet, so we can fire immediately. @@ -123,6 +126,8 @@ class _BridgeExampleAppState extends State { handle.counter.value = msg['value'] as int; } else if (event == 'version') { handle.pythonVersion.value = msg['value'] as String; + } else if (event == 'startup_error') { + handle.startupError = msg['message'] as String; } // 'mem' events are consumed by the memory test directly via its own // listener — no widget-visible state for them. diff --git a/src/serious_python/example/flask_example/pubspec.lock b/src/serious_python/example/flask_example/pubspec.lock index ee2c371a..fa02eea7 100644 --- a/src/serious_python/example/flask_example/pubspec.lock +++ b/src/serious_python/example/flask_example/pubspec.lock @@ -361,42 +361,42 @@ packages: path: "../.." relative: true source: path - version: "6.1.1" + version: "6.1.2" serious_python_android: dependency: transitive description: path: "../../../serious_python_android" relative: true source: path - version: "6.1.1" + version: "6.1.2" serious_python_darwin: dependency: transitive description: path: "../../../serious_python_darwin" relative: true source: path - version: "6.1.1" + version: "6.1.2" serious_python_linux: dependency: transitive description: path: "../../../serious_python_linux" relative: true source: path - version: "6.1.1" + version: "6.1.2" serious_python_platform_interface: dependency: transitive description: path: "../../../serious_python_platform_interface" relative: true source: path - version: "6.1.1" + version: "6.1.2" serious_python_windows: dependency: transitive description: path: "../../../serious_python_windows" relative: true source: path - version: "6.1.1" + version: "6.1.2" shelf: dependency: transitive description: diff --git a/src/serious_python/example/run_example/pubspec.lock b/src/serious_python/example/run_example/pubspec.lock index bf721fe5..08f3bae4 100644 --- a/src/serious_python/example/run_example/pubspec.lock +++ b/src/serious_python/example/run_example/pubspec.lock @@ -384,42 +384,42 @@ packages: path: "../.." relative: true source: path - version: "6.1.1" + version: "6.1.2" serious_python_android: dependency: transitive description: path: "../../../serious_python_android" relative: true source: path - version: "6.1.1" + version: "6.1.2" serious_python_darwin: dependency: transitive description: path: "../../../serious_python_darwin" relative: true source: path - version: "6.1.1" + version: "6.1.2" serious_python_linux: dependency: transitive description: path: "../../../serious_python_linux" relative: true source: path - version: "6.1.1" + version: "6.1.2" serious_python_platform_interface: dependency: transitive description: path: "../../../serious_python_platform_interface" relative: true source: path - version: "6.1.1" + version: "6.1.2" serious_python_windows: dependency: transitive description: path: "../../../serious_python_windows" relative: true source: path - version: "6.1.1" + version: "6.1.2" shelf: dependency: transitive description: diff --git a/src/serious_python/pubspec.yaml b/src/serious_python/pubspec.yaml index 32ac0699..42695975 100644 --- a/src/serious_python/pubspec.yaml +++ b/src/serious_python/pubspec.yaml @@ -2,7 +2,7 @@ name: serious_python description: A cross-platform plugin for adding embedded Python runtime to your Flutter apps. homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python -version: 6.1.1 +version: 6.1.2 platforms: ios: diff --git a/src/serious_python_android/CHANGELOG.md b/src/serious_python_android/CHANGELOG.md index 8007f5c8..d0409168 100644 --- a/src/serious_python_android/CHANGELOG.md +++ b/src/serious_python_android/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.1.2 + +* Align with the serious_python **6.1.2** release ([#261](https://github.com/flet-dev/serious-python/pull/261)). + ## 6.1.1 * Align with the serious_python **6.1.1** release ([#260](https://github.com/flet-dev/serious-python/pull/260)). diff --git a/src/serious_python_android/android/build.gradle.kts b/src/serious_python_android/android/build.gradle.kts index b6c3d48e..2dd352bf 100644 --- a/src/serious_python_android/android/build.gradle.kts +++ b/src/serious_python_android/android/build.gradle.kts @@ -21,7 +21,7 @@ buildscript { } group = "com.flet.serious_python_android" -version = "6.1.1" +version = "6.1.2" rootProject.allprojects { repositories { diff --git a/src/serious_python_android/pubspec.yaml b/src/serious_python_android/pubspec.yaml index 52bfbbf7..d53fcd00 100644 --- a/src/serious_python_android/pubspec.yaml +++ b/src/serious_python_android/pubspec.yaml @@ -2,7 +2,7 @@ name: serious_python_android description: Android implementation of the serious_python plugin homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python -version: 6.1.1 +version: 6.1.2 environment: sdk: ">=3.0.0 <4.0.0" diff --git a/src/serious_python_darwin/CHANGELOG.md b/src/serious_python_darwin/CHANGELOG.md index 3cffc859..4c1a2889 100644 --- a/src/serious_python_darwin/CHANGELOG.md +++ b/src/serious_python_darwin/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.1.2 + +* Align with the serious_python **6.1.2** release ([#261](https://github.com/flet-dev/serious-python/pull/261)). + ## 6.1.1 * Align with the serious_python **6.1.1** release ([#260](https://github.com/flet-dev/serious-python/pull/260)). diff --git a/src/serious_python_darwin/darwin/serious_python_darwin.podspec b/src/serious_python_darwin/darwin/serious_python_darwin.podspec index 732cf5ec..bd4b0861 100644 --- a/src/serious_python_darwin/darwin/serious_python_darwin.podspec +++ b/src/serious_python_darwin/darwin/serious_python_darwin.podspec @@ -4,7 +4,7 @@ # Pod::Spec.new do |s| s.name = 'serious_python_darwin' - s.version = '6.1.1' + s.version = '6.1.2' s.summary = 'A cross-platform plugin for adding embedded Python runtime to your Flutter apps.' s.description = <<-DESC A cross-platform plugin for adding embedded Python runtime to your Flutter apps. diff --git a/src/serious_python_darwin/pubspec.yaml b/src/serious_python_darwin/pubspec.yaml index 779bd10c..ffd0b2e9 100644 --- a/src/serious_python_darwin/pubspec.yaml +++ b/src/serious_python_darwin/pubspec.yaml @@ -2,7 +2,7 @@ name: serious_python_darwin description: iOS and macOS implementations of the serious_python plugin homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python -version: 6.1.1 +version: 6.1.2 environment: # The Swift Package Manager build path needs Flutter 3.44 / Dart 3.11 (the diff --git a/src/serious_python_linux/CHANGELOG.md b/src/serious_python_linux/CHANGELOG.md index 6427ce9e..c71fe8c1 100644 --- a/src/serious_python_linux/CHANGELOG.md +++ b/src/serious_python_linux/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.1.2 + +* Fix native Python extension imports, including `pydantic-core`, which failed with unresolved CPython symbols such as `PyExc_RecursionError` ([#261](https://github.com/flet-dev/serious-python/pull/261)). + ## 6.1.1 * Align with the serious_python **6.1.1** release ([#260](https://github.com/flet-dev/serious-python/pull/260)). diff --git a/src/serious_python_linux/pubspec.yaml b/src/serious_python_linux/pubspec.yaml index fad83f0e..d1797f8e 100644 --- a/src/serious_python_linux/pubspec.yaml +++ b/src/serious_python_linux/pubspec.yaml @@ -2,7 +2,7 @@ name: serious_python_linux description: Linux implementations of the serious_python plugin homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python -version: 6.1.1 +version: 6.1.2 environment: sdk: '>=3.1.3 <4.0.0' diff --git a/src/serious_python_platform_interface/CHANGELOG.md b/src/serious_python_platform_interface/CHANGELOG.md index aea44fd8..45269547 100644 --- a/src/serious_python_platform_interface/CHANGELOG.md +++ b/src/serious_python_platform_interface/CHANGELOG.md @@ -1,3 +1,8 @@ +## 6.1.2 + +* On Windows, open `dart_bridge.dll` in Debug builds too, instead of `dart_bridge_d.dll` ([#261](https://github.com/flet-dev/serious-python/pull/261), [flet-dev/flet#7020](https://github.com/flet-dev/flet/discussions/7020)). +* On Linux, load the bridge and its CPython dependencies with global symbol visibility so native Python extension wheels can resolve the CPython API ([#261](https://github.com/flet-dev/serious-python/pull/261)). + ## 6.1.1 * Align with the serious_python **6.1.1** release ([#260](https://github.com/flet-dev/serious-python/pull/260)). diff --git a/src/serious_python_platform_interface/lib/src/dart_bridge_ffi.dart b/src/serious_python_platform_interface/lib/src/dart_bridge_ffi.dart index d4d99a5c..1b3aad46 100644 --- a/src/serious_python_platform_interface/lib/src/dart_bridge_ffi.dart +++ b/src/serious_python_platform_interface/lib/src/dart_bridge_ffi.dart @@ -14,9 +14,9 @@ import 'package:flutter/foundation.dart' show kDebugMode; /// - Apple (macOS/iOS): statically linked into the host app via /// `dart_bridge.xcframework` — looked up through [DynamicLibrary.process]. /// - Android: bundled as `libdart_bridge.so` in jniLibs — opened by name. -/// - Linux: bundled next to the executable — opened by name. -/// - Windows: bundled next to the .exe, with a separate Debug-CRT variant -/// `dart_bridge_d.dll` for `fvm flutter run`. +/// - Linux: bundled next to the executable — opened with global symbols so +/// Python extension wheels can resolve the CPython API. +/// - Windows: bundled next to the .exe as `dart_bridge.dll`, in Debug builds too. /// /// Mirrors the C surface declared in /// [dart-bridge/src/dart_bridge.c](https://github.com/flet-dev/dart-bridge/blob/main/src/dart_bridge.c) @@ -144,23 +144,61 @@ class DartBridge { /// Test/override entry point: open a specific library path. Replaces the /// cached instance. static DartBridge open(String path) => - _instance = DartBridge._(DynamicLibrary.open(path)); + _instance = DartBridge._(_openLibrary(path)); /// Test/override entry point: resolve from the host process (Apple). /// Replaces the cached instance. static DartBridge process() => _instance = DartBridge._(DynamicLibrary.process()); + static DynamicLibrary _openLibrary(String path) { + if (!Platform.isLinux) return DynamicLibrary.open(path); + + // dart:ffi uses RTLD_LOCAL on Linux. Extension wheels generally leave + // their CPython symbols unresolved, expecting the embedding interpreter + // to provide them globally. RTLD_GLOBAL also exposes the bridge's + // libpython dependencies, including the version-specific CPython library. + final process = DynamicLibrary.process(); + final dlopen = process.lookupFunction< + Pointer Function(Pointer, Int32), + Pointer Function(Pointer, int)>('dlopen'); + final dlclose = process.lookupFunction), + int Function(Pointer)>('dlclose'); + const rtldLazy = 0x1; + const rtldGlobal = 0x100; + final handle = using((arena) => dlopen( + path.toNativeUtf8(allocator: arena), rtldLazy | rtldGlobal)); + if (handle == nullptr) { + final dlerror = process.lookupFunction Function(), + Pointer Function()>('dlerror'); + final error = dlerror(); + throw ArgumentError('Failed to load $path: ' + '${error == nullptr ? "unknown dlopen error" : error.toDartString()}'); + } + try { + return DynamicLibrary.open(path); + } finally { + // DynamicLibrary.open retains its own reference to the global library. + dlclose(handle); + } + } + static DynamicLibrary _loadDefault() { if (Platform.isMacOS || Platform.isIOS) { return DynamicLibrary.process(); } if (Platform.isAndroid || Platform.isLinux) { - return DynamicLibrary.open('libdart_bridge.so'); + return _openLibrary('libdart_bridge.so'); } if (Platform.isWindows) { - return DynamicLibrary.open( - kDebugMode ? 'dart_bridge_d.dll' : 'dart_bridge.dll'); + try { + return DynamicLibrary.open('dart_bridge.dll'); + } on ArgumentError { + // Older serious_python_windows 6.x versions only bundle the debug + // DLL in Debug builds, and allow newer platform-interface versions. + if (!kDebugMode) rethrow; + return DynamicLibrary.open('dart_bridge_d.dll'); + } } throw UnsupportedError( 'serious_python: dart_bridge has no binary for this platform'); diff --git a/src/serious_python_platform_interface/pubspec.yaml b/src/serious_python_platform_interface/pubspec.yaml index 383e555f..002556c8 100644 --- a/src/serious_python_platform_interface/pubspec.yaml +++ b/src/serious_python_platform_interface/pubspec.yaml @@ -2,7 +2,7 @@ name: serious_python_platform_interface description: A common platform interface for the serious_python plugin. homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python -version: 6.1.1 +version: 6.1.2 environment: sdk: ">=3.0.0 <4.0.0" diff --git a/src/serious_python_windows/CHANGELOG.md b/src/serious_python_windows/CHANGELOG.md index f3ad5b96..1873b665 100644 --- a/src/serious_python_windows/CHANGELOG.md +++ b/src/serious_python_windows/CHANGELOG.md @@ -1,3 +1,7 @@ +## 6.1.2 + +* **Compiled Python packages import in Debug Windows builds.** Debug builds, such as `flutter test`, `flutter run` and Flet's `flet test`, bundled a debug build of CPython (`python3XY_d.dll` with `dart_bridge_d.dll`), which only imports extension modules named `*_d.pyd`. Wheels from PyPI don't ship those, so packages like `pydantic-core` or `numpy` failed with `ModuleNotFoundError` (e.g. `No module named 'pydantic_core._pydantic_core'`). Every build configuration now bundles the release CPython and `dart_bridge.dll`, and no build ships CPython's `*_d` modules ([#261](https://github.com/flet-dev/serious-python/pull/261), [flet-dev/flet#7020](https://github.com/flet-dev/flet/discussions/7020)). + ## 6.1.1 * **Release Windows apps no longer ship Python's debug modules.** The 3.0.0 rewrite of the `DLLs` copy step lost the removal of `*_d.*` from Release builds, so every app carried each extension module twice (`_ctypes.pyd` and `_ctypes_d.pyd`, …): about 10 MB and two dozen files more than needed, and as many extra signatures when the app is code-signed. Release and Profile builds now drop them again; Debug builds keep them ([#260](https://github.com/flet-dev/serious-python/pull/260)). diff --git a/src/serious_python_windows/lib/serious_python_windows.dart b/src/serious_python_windows/lib/serious_python_windows.dart index 5c6861ba..dcce7ebd 100644 --- a/src/serious_python_windows/lib/serious_python_windows.dart +++ b/src/serious_python_windows/lib/serious_python_windows.dart @@ -6,10 +6,9 @@ import 'package:serious_python_platform_interface/serious_python_platform_interf /// Windows implementation of [SeriousPythonPlatform]. /// /// Python lifecycle (env, sys.path, Py_Initialize, run, finalize, sync/async) -/// lives in `serious_python_run`, packaged as `dart_bridge.dll` (Release CRT) -/// or `dart_bridge_d.dll` (Debug CRT) and bundled next to the .exe by this -/// plugin's CMakeLists.txt. The correct DLL is picked at runtime based on -/// [kDebugMode]. +/// lives in `serious_python_run`, packaged as `dart_bridge.dll` and bundled +/// next to the .exe by this plugin's CMakeLists.txt, with the release CPython +/// in every build configuration. /// /// This class derives PYTHONHOME from `Platform.resolvedExecutable` (the /// runner .exe directory, where the bundled CPython lives) and dispatches a diff --git a/src/serious_python_windows/pubspec.yaml b/src/serious_python_windows/pubspec.yaml index ceb2221a..2479c26b 100644 --- a/src/serious_python_windows/pubspec.yaml +++ b/src/serious_python_windows/pubspec.yaml @@ -2,7 +2,7 @@ name: serious_python_windows description: Windows implementations of the serious_python plugin homepage: https://flet.dev repository: https://github.com/flet-dev/serious-python -version: 6.1.1 +version: 6.1.2 environment: sdk: '>=3.1.3 <4.0.0' diff --git a/src/serious_python_windows/windows/CMakeLists.txt b/src/serious_python_windows/windows/CMakeLists.txt index 97eb4eeb..68062718 100644 --- a/src/serious_python_windows/windows/CMakeLists.txt +++ b/src/serious_python_windows/windows/CMakeLists.txt @@ -124,33 +124,30 @@ if(_py_extract) file(WRITE "${_py_marker}" "${_py_build_id}") endif() -# ---- dart_bridge prebuilt DLLs -------------------------------------------- -# Release CRT (.dll) is what Release Flutter builds consume; Debug CRT -# (_d.dll) is what `fvm flutter run` / Debug builds consume. Both ship in -# every release of flet-dev/dart-bridge; we bundle both and let Flutter's -# CONFIG-aware copy machinery pick the right one at app launch time. +# ---- dart_bridge prebuilt DLL --------------------------------------------- +# Every build configuration, Debug included, bundles the release +# `dart_bridge.dll` and the release CPython it links (python3.dll -> +# python3XY.dll). A Debug CPython would only import extension modules named +# `*_d.pyd`, which PyPI wheels don't ship, so no compiled package +# (pydantic-core, numpy, ...) could be imported in Debug builds such as +# `flutter test` and `flutter run`. Nothing in the plugin links Python, so a +# Debug runner loads the release DLLs as they are. # -# Cached under the upstream arch-qualified filenames so multiple flet-dev/ -# dart-bridge versions can coexist in $FLET_CACHE_DIR. Copied to stable -# unqualified names in the build tree because Flutter's bundled_libraries +# Cached under the upstream arch-qualified filename so multiple flet-dev/ +# dart-bridge versions can coexist in $FLET_CACHE_DIR. Copied to a stable +# unqualified name in the build tree because Flutter's bundled_libraries # machinery preserves filenames as-is, and the Dart side opens the DLL by -# `dart_bridge[_d].dll` (no arch suffix). +# `dart_bridge.dll` (no arch suffix). set(DART_BRIDGE_RELEASE_CACHED "${DB_CACHE}/dart_bridge-windows-x86_64.dll") -set(DART_BRIDGE_DEBUG_CACHED "${DB_CACHE}/dart_bridge_d-windows-x86_64.dll") _sp_download( "https://github.com/flet-dev/dart-bridge/releases/download/v${DART_BRIDGE_VERSION}/dart_bridge-windows-x86_64.dll" "${DART_BRIDGE_RELEASE_CACHED}") -_sp_download( - "https://github.com/flet-dev/dart-bridge/releases/download/v${DART_BRIDGE_VERSION}/dart_bridge_d-windows-x86_64.dll" - "${DART_BRIDGE_DEBUG_CACHED}") set(DART_BRIDGE_DIR "${CMAKE_BINARY_DIR}/dart_bridge") set(DART_BRIDGE_RELEASE_DLL "${DART_BRIDGE_DIR}/dart_bridge.dll") -set(DART_BRIDGE_DEBUG_DLL "${DART_BRIDGE_DIR}/dart_bridge_d.dll") file(MAKE_DIRECTORY "${DART_BRIDGE_DIR}") configure_file("${DART_BRIDGE_RELEASE_CACHED}" "${DART_BRIDGE_RELEASE_DLL}" COPYONLY) -configure_file("${DART_BRIDGE_DEBUG_CACHED}" "${DART_BRIDGE_DEBUG_DLL}" COPYONLY) # Any new source files that you add to the plugin should be added here. list(APPEND PLUGIN_SOURCES @@ -217,9 +214,9 @@ if(EXISTS "${SERIOUS_PYTHON_WINDIR}/Sysnative") endif() set(serious_python_windows_bundled_libraries - "${PYTHON_PACKAGE}/python${PYTHON_VERSION_NODOT}$<$:_d>.dll" - "${PYTHON_PACKAGE}/python3$<$:_d>.dll" - "$,${DART_BRIDGE_DEBUG_DLL},${DART_BRIDGE_RELEASE_DLL}>" + "${PYTHON_PACKAGE}/python${PYTHON_VERSION_NODOT}.dll" + "${PYTHON_PACKAGE}/python3.dll" + "${DART_BRIDGE_RELEASE_DLL}" "${_sp_crt_dir}/msvcp140.dll" "${_sp_crt_dir}/vcruntime140.dll" "${_sp_crt_dir}/vcruntime140_1.dll" @@ -245,12 +242,9 @@ add_custom_command(TARGET CopyPythonDLLs POST_BUILD "${SP_RUNNER_OUT}/DLLs/tk86t.dll" COMMAND ${CMAKE_COMMAND} -DDIR=${SP_RUNNER_OUT}/DLLs -DGLOBS=*.ico\;*.cat -P "${CMAKE_CURRENT_SOURCE_DIR}/rm_globs.cmake" - # Debug-only modules (*_d.pyd, *_d.dll, *_d.pdb) ship in Debug builds only: - # Release and Profile builds load the release ones. (The 3.0.0 move from - # cmd.exe DEL to rm_globs.cmake dropped this, so Release apps carried - # every module twice.) "__none__" matches nothing in Debug builds. - COMMAND ${CMAKE_COMMAND} -DDIR=${SP_RUNNER_OUT}/DLLs - -DGLOBS=$,__none__,*_d.*> + # Debug CPython's modules (*_d.pyd, *_d.dll, *_d.pdb): every build loads + # the release CPython, so nothing imports them. + COMMAND ${CMAKE_COMMAND} -DDIR=${SP_RUNNER_OUT}/DLLs -DGLOBS=*_d.* -P "${CMAKE_CURRENT_SOURCE_DIR}/rm_globs.cmake" )