funroll
funroll

Reputation: 37093

How to detect use_frameworks! at compile time

I'm developing a cocoapod. Someone who uses my pod can choose whether or not to include this line in their Podfile:

use_frameworks!

If they include it, my code will be compiled into a .framework file. If not, it will be compiled into a .a file.

I'd like to use preprocessor macros to include different code in my cocoa pod, based on whether use_frameworks! is present.

For example, something like this:

#if PODFILE_CONTAINS_USE_FRAMEWORKS
@import My_Library;
#else
#import <My-Library/MyLibrary.h>
#end

This situation comes up when you have a pod name that's not c99extidentifier compliant.

I already tried checking for #if defined COCOAPODS, but that's defined in both these cases.

Upvotes: 5

Views: 270

Answers (2)

Enricoza
Enricoza

Reputation: 1142

I've had a similar issue as you had here. I wanted to import Swift generated Header from Objective C within the same cocoapod, but the header is in different locations depending on the type of library (and therefore the presence or absence of use_frameworks!). I've managed to import the correct file in both cases without having to change the Podfile.


What i did

In order to have the header imported in both static library (without use_frameworks!) and dynamic framework (with use_frameworks!) i used something i found out here:

There basically is a compiler preprocessor macro __has_include ( header-name ) to find out if it actually has an import file in that specific location.

So, in case the file is there, I use that import, otherwise I use the other one (assuming there is no third options).

So in my case the import look like this:

#if defined __has_include && __has_include(<MyLibrary-Swift.h>)
#import <MyLibrary-Swift.h>
#else
#import <MyLibrary/MyLibrary-Swift.h>
#endif

To run custom code according to the presence of use_frameworks!

In your case you can use the __has_include(<MyLibrary-Swift.h>) as a podfile DOESN'T contain use_frameworks! like this:

#if defined __has_include && __has_include(<MyLibrary-Swift.h>)
// use_frameworks! is NOT present
#else
// use_frameworks! is present
#endif

Assuming that the generated header will look like this:

  • MyLibrary-Swift.h -> if use_frameworks! is NOT present in the podfile
  • MyLibrary/MyLibrary-Swift.h -> if use_frameworks! is present in the podfile

Upvotes: 0

funroll
funroll

Reputation: 37093

Got it working.

This snippet needs to go in the Podfile:

post_install do |pi|
    pi.pods_project.targets.each do |target|
        target.build_configurations.each do |config|
            unless pi.podfile.defined_in_file.read().include? "\nuse_frameworks!\n"
              config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= ['$(inherited)']
              config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] << 'NO_USE_FRAMEWORKS=1'
            end
        end
    end
end

Then in the source file, the code looks like this:

#if defined NO_USE_FRAMEWORKS
#import <My-Library/MyLibrary.h>
#else
@import My_Library;
#endif

It defaults to @import syntax if the symbol is not present.

So the Podfile snippet only really needs to be added if use_frameworks! is not present. But it will work either way.

Upvotes: 3

Related Questions