28

Porting apps to mac is finally possible thanks to Catalyst, problem is, numerous pods don't support AppKit. Most common one would be Crashlytics / Firebase.

In [...]/Pods/Crashlytics/iOS/Crashlytics.framework/Crashlytics(CLSInternalReport.o), building for Mac Catalyst, but linking in object file built for iOS Simulator, file '[...]/Pods/Crashlytics/iOS/Crashlytics.framework/Crashlytics' for architecture x86_64

Since it's a recent topic, I couldn't find doc on how to remove a pod from my build for macOS but keep it for iOS and iPadOS.

It is possible to use in code:

#if !targetEnvironment(macCatalyst) 
// Code to exclude for your macOS app
#endif

But that one part of the problem, the other part is to link the pod only for iOS...

What would be the easiest/best course of action when the library is not vital for macOS but still wanted on iOS?

1
  • Hey op! It would be great to know if my answer helped you! if it does, please mark the answer as the right answer Commented Aug 25, 2020 at 10:13

6 Answers 6

26

For the best approach of handling unsupported framweorks for Catalyst, you guys should read the solution of Fernando Moya de Rivas, he has a github with a solution here with more up to date information.

He basically said you just need to define an array of all of the libs you don't want to install on mac osx, like this: ['Fabric', 'Crashlytics', 'Firebase/Core', ...].

Then, your pod file can look simple as this:

# Podfile
load 'remove_unsupported_libraries.rb'

target 'My target' do
   use_frameworks!
   # Install your pods
   pod ...
end

# define unsupported pods
def catalyst_unsupported_pods
    ['Fabric', 'Crashlytics', 'Firebase/Core', ...]
end

# Remove unsupported pods from your project
post_install do |installer|   
    installer.configure_support_catalyst
end
Sign up to request clarification or add additional context in comments.

2 Comments

I think this should be the accepted answer now. Just note that I think it requires Ruby 2.6.3 to avoid an error when it calls filter
I switched this to the accepted answer now, as it seems the consensus :)
19

Following @ajgryc answer, I was able to make a sleek solution:

In your podfile add

post_install do |installer|
    installer.pods_project.targets.each do |target|
        if target.name == "Pods-[Name of Project]"
            puts "Updating #{target.name} OTHER_LDFLAGS to OTHER_LDFLAGS[sdk=iphone*]"
            target.build_configurations.each do |config|
                xcconfig_path = config.base_configuration_reference.real_path
                xcconfig = File.read(xcconfig_path)
                new_xcconfig = xcconfig.sub('OTHER_LDFLAGS =', 'OTHER_LDFLAGS[sdk=iphone*] =')
                File.open(xcconfig_path, "w") { |file| file << new_xcconfig }
            end
        end
    end
end

Since Cocoapods 1.8.4

post_install do |installer|
  installer.pods_project.targets.each do |target|
    if target.name == "Pods-[Name of Project]"
      puts "Updating #{target.name} to exclude Crashlytics/Fabric"
      target.build_configurations.each do |config|
        xcconfig_path = config.base_configuration_reference.real_path
        xcconfig = File.read(xcconfig_path)
        xcconfig.sub!('-framework "Crashlytics"', '')
        xcconfig.sub!('-framework "Fabric"', '')
        new_xcconfig = xcconfig + 'OTHER_LDFLAGS[sdk=iphone*] = -framework "Crashlytics" -framework "Fabric"'
        File.open(xcconfig_path, "w") { |file| file << new_xcconfig }
      end
    end
  end
end

And then in run script build phase for Fabric:

if [[$ARCHS != "x86_64"]]; then
  "${PODS_ROOT}/Fabric/run" [your usual key]
fi

6 Comments

This works well to disable all CocoaPods from being linked in MacCatalyst. Change the third line to if target.name.start_with?("Pods") to catch all Pod targets.
This doesn't seem to work anymore with cocoapods 1.8.4
I tried both way "if target.name.start_with?("Pods")" does not work for me also with cocoapods 1.8.4, I got below error, anybody can guide me. in /Users/ios/Desktop/xxxxxx/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/FIRAnalyticsConnector(FIRConnectorUtils_d79571aba36a7d46e5c6ca87a6fec1c1.o), building for Mac Catalyst, but linking in object file built for iOS Simulator, file '/Users/ios/Desktop/xxxxxx/Pods/FirebaseAnalytics/Frameworks/FIRAnalyticsConnector.framework/FIRAnalyticsConnector' for architecture x86_64
For the run script, you can also use: if [[ ${IS_MACCATALYST} != "YES" ]]; then "${PODS_ROOT}/Fabric/run" fi
Can you update an answer to include a link to an issue in cocoa pods so that people reading an answer can upvote it? This should be supported out of the box in my opinion. github.com/CocoaPods/CocoaPods/issues/9364
|
13
+50

Open your Pods-$projectname.release.xcconfig file in your project's Pods directory, and locate the OTHER_LDFLAGS line. Add [sdk=iphone*] immediately after the variable name (as an example, mine now looks like this):

OTHER_LDFLAGS[sdk=iphone*] = $(inherited) -ObjC -l"MailCore-ios" -l"c++" -l"iconv" -l"resolv" -l"xml2" -l"z"

That conditionally sets the link options only when building iphone variants, preventing the pod from being linked on OSX. Of course as you mention, this needs to be combined with #if !targetEnvironment(macCatalyst) and #endif surrounding the code calling the pod or you'll get linker errors.

This allowed me to get past the same problem. (And in case you're wondering what other cool things besides conditional variables you can add to your .xcconfig files, here's a reference I found: https://pewpewthespells.com/blog/xcconfig_guide.html )

4 Comments

I have given you the bounty, but accepted my own answer as I give a solution out of the box which will make people's life easier, thank you very much!
sorry, but where is a Pods-$projectname.release.xcconfig file. I am not able to find it.
In my config it is in <Project Directory>/Pods/Target Support Files/Pods-<Project Name>
this solution isn't recommended as the xcconfig always build itself in every pod install. I would recommend to read this Fernando Moya de Rivas's answer for the best alternative
10

I have an updated solution that works for me with the following Google pods:

  pod 'FirebaseUI/Auth'
  pod 'FirebaseUI/Phone'
  pod 'FirebaseUI/Email'
  pod 'Firebase/Auth'
  pod 'Firebase/Analytics'
  pod 'Fabric', '~> 1.10.2'
  pod 'Firebase/Crashlytics'
  pod 'Firebase/AdMob'
post_install do |installer|
  installer.pods_project.targets.each do |target|
    if target.name.start_with?("Pods")
        puts "Updating #{target.name} to exclude Crashlytics/Fabric"
      target.build_configurations.each do |config|
        xcconfig_path = config.base_configuration_reference.real_path
        xcconfig = File.read(xcconfig_path)
        xcconfig.sub!('-framework "FirebaseAnalytics"', '')
        xcconfig.sub!('-framework "FIRAnalyticsConnector"', '')
        xcconfig.sub!('-framework "GoogleMobileAds"', '')
        xcconfig.sub!('-framework "Google-Mobile-Ads-SDK"', '')
        xcconfig.sub!('-framework "GoogleAppMeasurement"', '')
        xcconfig.sub!('-framework "Fabric"', '')
        new_xcconfig = xcconfig + 'OTHER_LDFLAGS[sdk=iphone*] = $(inherited) -framework "FirebaseAnalytics"  -framework "FIRAnalyticsConnector"  -framework "GoogleMobileAds" -framework "GoogleAppMeasurement" -framework "GoogleUtilities" "-AppMeasurement" -framework "Fabric"'
        File.open(xcconfig_path, "w") { |file| file << new_xcconfig }
      end
    end
  end
end

5 Comments

I'm trying to use this solution as it looks the most clean, but I get this error: ld: in /Users/<name>/source/<app>/Pods/Fabric/iOS/Fabric.framework/Fabric(Fabric.o), building for Mac Catalyst, but linking in object file built for iOS Simulator, for architecture x86_64 I use exactly what you have above minus the GoogleMobileAds and Google-Mobile-Ads-SDK. Why am I getting this?
I’m not sure. At this point it’s time to remove Fabric isn’t it? I don’t agree that Google had the right to buy them, but they did and are shutting it down so...
Sadly using 'pod Crashlytics' automatically installs Fabric (1.10.2). Not sure why that happens and am cautious about using the 'Firebase/Crashlytics' pod because Google says that that's still in the beta stage :(
Does anyone get a build failure with error "unsealed contents present in the bundle root" when doing this?
@user13138159 I m trying the above solution but it gives me the error ld: in /Users/<name>/Desktop/<app>/Pods/GoogleAnalytics/Libraries/libGoogleAnalytics.a(GAITrackerImpl.o), building for Mac Catalyst, but linking in object file built for iOS Simulator, file '/Users/<name>/Desktop/<app>/Pods/GoogleAnalytics/Libraries/libGoogleAnalytics.a' for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation) what ekzactly you did?
7

With cocoapods 1.8.4, I had to adapt @AncAinu's excellent answer as follows:

post_install do |installer|
  installer.pods_project.targets.each do |target|
    if target.name == "Pods-[Name of Project]"
      puts "Updating #{target.name} to exclude Crashlytics/Fabric"
      target.build_configurations.each do |config|
        xcconfig_path = config.base_configuration_reference.real_path
        xcconfig = File.read(xcconfig_path)
        xcconfig.sub!('-framework "Crashlytics"', '')
        xcconfig.sub!('-framework "Fabric"', '')
        new_xcconfig = xcconfig + 'OTHER_LDFLAGS[sdk=iphone*] = -framework "Crashlytics" -framework "Fabric"'
        File.open(xcconfig_path, "w") { |file| file << new_xcconfig }
      end
    end
  end
end

5 Comments

FYI, the latest release of Crashlytics is now open-source and thus compiles directly for Catalyst when needed. This hack is no longer required in the case of Crashlytics, but can be useful with other legacy pods.
in above Name of the Project part, we have to write name of the project file ? if target.name == "Pods-[MyProjectExample]". something like that or just paste the answer ? because it doest work for me
Yes you have to replace with your project name.
I done everything right. if target.name == "Pods-[VPNoid]" clean and build my project again. but still error is complaining. Do u have any idea ?
Remove the []
3

Based on what has already been discussed here... here is my solution for projects with multiple targets. It basically is validating the usage of the libs on each target instead of following the target name.

post_install do |installer|
    
    installer.pods_project.targets.each do |target|
        
        # handle non catalyst libs
        libs = ["FirebaseAnalytics", "Google-Mobile-Ads-SDK"]
        
        target.build_configurations.each do |config|
            xcconfig_path = config.base_configuration_reference.real_path
            xcconfig = File.read(xcconfig_path)
            values = ""
            
            libs.each { |lib|
                if xcconfig["-framework \"#{lib}\""]
                    puts "Found '#{lib}' on target '#{target.name}'"
                    xcconfig.sub!(" -framework \"#{lib}\"", '')
                    values += " -framework \"#{lib}\""
                end
            }
            
            if values.length > 0
                puts "Preparing '#{target.name}' for Catalyst\n\n"
                new_xcconfig = xcconfig + 'OTHER_LDFLAGS[sdk=iphone*] = $(inherited)' + values
                File.open(xcconfig_path, "w") { |file| file << new_xcconfig }
            end
        end
    end
end


It outputs something like this

Generating Pods project

Found 'Google-Mobile-Ads-SDK' on target 'Pods-TheApp'
Found 'FirebaseAnalytics' on target 'Pods-TheApp'
Preparing 'Pods-TheApp' for Catalyst

Found 'Google-Mobile-Ads-SDK' on target 'Pods-TheApp-TheAppTests'
Found 'FirebaseAnalytics' on target 'Pods-TheApp-TheAppTests'
Preparing 'Pods-TheApp-TheAppTests' for Catalyst

Found 'Google-Mobile-Ads-SDK' on target 'Pods-TheApp-TheApp_iOS_UI_Tests'
Found 'FirebaseAnalytics' on target 'Pods-TheApp-TheApp_iOS_UI_Tests'
Preparing 'Pods-TheApp-TheApp_iOS_UI_Tests' for Catalyst

Found 'Google-Mobile-Ads-SDK' on target 'Pods-TheAppIntentsExtension'
Found 'FirebaseAnalytics' on target 'Pods-TheAppIntentsExtension'
Preparing 'Pods-TheAppIntentsExtension' for Catalyst

Found 'Google-Mobile-Ads-SDK' on target 'Pods-TheAppTodayExtension'
Found 'FirebaseAnalytics' on target 'Pods-TheAppTodayExtension'
Preparing 'Pods-TheAppTodayExtension' for Catalyst

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.