Skip to content

fix(flutter): name the iOS podspec after the pub package (pulsar_haptics) - #141

Draft
ilya-clicapin wants to merge 1 commit into
software-mansion:mainfrom
ilya-clicapin:fix/flutter-cocoapods-podspec-name
Draft

fix(flutter): name the iOS podspec after the pub package (pulsar_haptics)#141
ilya-clicapin wants to merge 1 commit into
software-mansion:mainfrom
ilya-clicapin:fix/flutter-cocoapods-podspec-name

Conversation

@ilya-clicapin

Copy link
Copy Markdown

Fixes #140.

What was broken

Flutter derives the expected podspec filename from the pub package name, so it looked for flutter/pulsar/ios/pulsar_haptics.podspec. The file was named pulsar.podspec, and because ios/pulsar_haptics/Package.swift is present the tooling concluded the plugin is Swift Package Manager only. In an app that uses CocoaPods, flutter pub get ends with:

Plugin pulsar_haptics is only compatible with Swift Package Manager. Try enabling Swift Package Manager by running "flutter config --enable-swift-package-manager" or remove the plugin as a dependency.

The pub name also drives the module GeneratedPluginRegistrant imports (@import pulsar_haptics;), so even forcing the pod in by hand would have built it under the wrong module name.

Changes

  • Rename flutter/pulsar/ios/pulsar.podspec to ios/pulsar_haptics.podspec and set s.name = 'pulsar_haptics'.
  • Tag s.version with a pulsar-sync:flutter-version marker so scripts/sync-sdk-versions.mjs keeps it in step with the pub version — it was stuck at 0.0.1 while the package is at 0.0.3.
  • Point scripts/sync-sdk-versions.mjs at the new filename (it would otherwise throw on the old path).
  • Drop the stale references to a podspec named pulsar from CONTRIBUTING.md and from the SPM comment in _build-ios-flutter.yml (that workflow's symlink dance is unchanged — the mirror is now pulsar_haptics, but routing through a uniquely-named symlink still costs nothing).
  • Example app: regenerate ios/Podfile.lock, and drop use_frameworks! — see below.

The use_frameworks! caveat

CocoaPods' target validator compares product module names case-insensitively, so the plugin pod pulsar_haptics collides with the module CocoaPods derives for the native pod Pulsar-haptics (Pulsar_haptics):

[!] The 'Pods-Runner' target has frameworks with conflicting names: pulsar_haptics.

This only triggers when the app opts into frameworks; with the default static linkage pod install is fine. That's why the example app's Podfile drops use_frameworks!, with a comment pointing here.

The real fix is s.module_name = 'Pulsar' on iOS/Pulsar/Pulsar-haptics.podspec — that is the module name the Swift Package already exposes, and the Flutter bridge's #if canImport(Pulsar_haptics) / #elseif canImport(Pulsar) shim already accepts both — but it only takes effect once a native pod carrying it is published, so I left it out. Happy to fold it in if you'd rather ship both together.

Verification

Flutter 3.44.0, Xcode 26.5, CocoaPods 1.16.2, on flutter/PulsarApp.

With SPM disabled (flutter config --no-enable-swift-package-manager), which is the configuration from the issue:

  • flutter pub get — succeeds (fails on main with the error above)
  • pod install — installs Flutter, Pulsar-haptics (1.1.2), pulsar_haptics (0.0.3)
  • flutter build ios --debug --no-codesign --simulator — builds

With SPM enabled, flutter build ios --debug --no-codesign --simulator still builds, so the CI path in _build-ios-flutter.yml is unaffected. node scripts/sync-sdk-versions.mjs runs clean and leaves the tree unchanged.

Not included

The CI guard suggested in the issue. The Flutter iOS job in test-build-apps.yml is workflow_dispatch-only and goes through SPM, so adding a CocoaPods cell (SPM off, pub get + pod install) is a dispatcher-shape decision I'd rather leave to you — say the word and I'll add it here.

Unrelated drift I noticed while in here: the Flutter plugin pins Pulsar-haptics at 1.1.2 while sdk-versions.json lists iOS 1.2.0. Left untouched.

Flutter derives the expected podspec path from the pub package name, so it looked for `ios/pulsar_haptics.podspec`, did not find it, and — because `ios/pulsar_haptics/Package.swift` is present — concluded the plugin is Swift Package Manager only. In an app that uses CocoaPods, `flutter pub get` then failed with "Plugin pulsar_haptics is only compatible with Swift Package Manager" and the plugin could not be adopted at all. The same name drives the module `GeneratedPluginRegistrant` imports (`@import pulsar_haptics;`), so even with SPM disabled by hand the pod built under the wrong module name.

Rename `ios/pulsar.podspec` to `ios/pulsar_haptics.podspec`, set `s.name` to match, and tag `s.version` with a `pulsar-sync:flutter-version` marker so `scripts/sync-sdk-versions.mjs` keeps it in step with the pub version instead of leaving it stuck at 0.0.1.

CocoaPods compares product module names case-insensitively, so the plugin pod `pulsar_haptics` now collides with the native pod's derived module `Pulsar_haptics` (from `Pulsar-haptics`) whenever the app opts into frameworks. The example app's Podfile drops `use_frameworks!` for that reason; declaring `s.module_name = 'Pulsar'` on the native podspec — matching the module name its Swift Package already exposes — would lift the restriction for apps that need frameworks, but that needs a native release and is left out here.

Verified on the example app with Flutter 3.44.0: with SPM disabled, `flutter pub get` and `pod install` succeed and `flutter build ios --debug --simulator` builds; with SPM enabled, the build still succeeds.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@ilya-clicapin
ilya-clicapin force-pushed the fix/flutter-cocoapods-podspec-name branch from 9d2b015 to a488f54 Compare July 29, 2026 15:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Flutter plugin unusable with CocoaPods: iOS podspec is named pulsar.podspec but the pub package is pulsar_haptics

1 participant