The use_modular_headers option generates module maps for Swift and Objective-C pods instead of generating frameworks. See http://blog.cocoapods.org/CocoaPods-1.5.0/ Attached is an example project (AppCode 2018.1, Xcode 9.3, Swift 4.1)
Is your header public?
Select the header file in the project explorer. Then in the section on the right in xcode, you'll notice there is a dropdown next to the target. Change that from "project" to "public". This worked for me.
This is an expected compiler behaviour and for a very good reason.
I think the majority of people running into this issues is caused after they switch from Application Target
to Framework Target
and start adding C and Objective C headers into framework's umbrella header expecting it to have a same behaviour as application's Bridging Header, which behaves differently. The umbrella header is actually designated for mixed swift, obj-c framework and its purpose is exposing the APIs to the outer world that your framework has in objective-c or c. That means the headers we put there should be in the public scope.
It should not be used as a place that exposes Objective-C/C headers that are not a part of your framework to your framework's swift code. Because in that case these headers will be also exposed as the part of our framework module to the outer world, which is often not what we want to do since it breaks the modularity. (And that is exactly why Allows Non-modular Includes in Framework Modules defaults to NO)
In order to expose Objective-C/C library to your framework swift code, we should define a separate swift module for such library. Then a standard swift import YourLegacyLibrary
can be used.
Let me demonstrate this on some typical scenario: embedding libxml2
into our framework.
1. You first need to create a module.modulemap
file which would look in this way:
For OSX framework:
module SwiftLibXML2 [system] {
header "/usr/include/libxml2/libxml/xpath.h"
export *
}
For iOS framework:
module SwiftLibXML2 [system] {
header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/libxml2/libxml/xpath.h"
export *
}
All it does is that it wrap ups the header and any other headers it references inside swift module, so that swift will then be able to generate the swift bindings for these C interfaces.
2. Then in your xcode project directory create a folder SwiftLibXML2
and put this module.modulemap there
3. In Build Settings, add $(SDKROOT)/usr/include/libxml2
to Header Search Paths
4. In Build Settings, add $(SRCROOT)/SwiftLibXML2
to Import Paths
5. Under Project's General tab, add libxml2.tbd
to Linked Frameworks and Libraries.
Now you import this module where needed with:
import SwiftLibXML2
(if you want to look a more complete module.map example, I would suggest referencing Darwin's module.modulemap at /usr/include/module.modulemap
, you would need to have Xcode command-line tools installed to go there, reference Missing /usr/include in OS X El Capitan)
Here's how to automatically apply the quick fix so you don't have to change Pods.xcodeproj
manually after each pod install
.
Add this snippet to the end of your Podfile:
post_install do |installer|
installer.pods_project.build_configuration_list.build_configurations.each do |configuration|
configuration.build_settings['CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES'] = 'YES'
end
end
Solution for me was to go on target-> build settings->Allow non-modular includes in Framework Modules switch to YES!
In Swift:
1. Modify your Xcode project and targets' Build Settings as mentioned below:
Allow Non-modular Includes In Framework Modules: No
Enable Bitcode: Yes
2. Use the current latest version available for GoogleMaps iOS SDK (use CocoaPods for getting it):
GoogleMaps (1.10.4)
3. Comment the problematic import:
//import GoogleMaps
4. Create or modify your bridging header file, adding the problematic import:
[Your Xcode Project Name]-Bridging-Header.h
// Use this file to import your target's public headers
// that you would like to expose to Swift.
#import <GoogleMaps/GoogleMaps.h>
5. Clean and re-build your Xcode project.
I think I got around this. I have some model code that uses sqlite3 in a framework. In my case, the culprit was <sqlite3.h>.
The problem was that in my Module/Module.h header, I imported a public header that imported <sqlite3.h>. The solution was to hide all the sqlite3_xxx types and make sure they were not visible in any public .h. All direct references to sqlite3 were made private or project visibility. For example, I had a public singleton that had some sqlite3_stmt pointers hanging off it. I moved those to a separate class that is now only a forward declaration in that public header. Now I can build.
Incidentally, the CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES setting didn't work. I tried setting it both in the framework and the dependent project. This workaround was necessary, though I'm not sure why.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With