Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot Build In Xcode 7.1 #466

Closed
shushutochako opened this issue Oct 25, 2015 · 49 comments
Closed

Cannot Build In Xcode 7.1 #466

shushutochako opened this issue Oct 25, 2015 · 49 comments

Comments

@shushutochako
Copy link

I upgraded to XCode 7.1 yesterday.
When using Cocoapods, the module will no longer build for me with the error

include of non-modular header inside framework module 'Parse.Parse'
#import <Parse/PFACL.h>

include of non-modular header inside framework module 'Parse.Parse'
#import <Parse/PFAnalytics.h>
・
・
more

Is there a workaround?

@nlutsenko
Copy link
Contributor

Sounds super strange, since we have tests passing on every commit running Xcode 7.1, which explicitly test CocoaPods linter. I would suggest tyin to clean your derived data and/or reinstalling all your pods.

@nlutsenko nlutsenko self-assigned this Oct 25, 2015
@shushutochako
Copy link
Author

Thank you for answering. I tried clean and reinstalling but it was the same result.
The image below is the capture of the error.

capture

Incidentally version of cocoapod is 0.39.0 and Parse is 1.9.1.

@BellAppLab
Copy link

Same thing here...

@shushutochako
Copy link
Author

Hi @nlutsenko.
This issue has been resolved by add description of the following to Podfile.

post_install do |installer|
    `find Pods -regex 'Pods/Parse.*\\.h' -print0 | xargs -0 sed -i '' 's/\\(<\\)Parse\\/\\(.*\\)\\(>\\)/\\"\\2\\"/'`
end

I'm sorry for the inconvenience.

@fluidsonic
Copy link
Contributor

@shushutochako adding code to the Podfile is a workaround, not a solution.

Same problem here with CocoaPods 0.39.0, Xcode 7.1 & Parse 1.9.1.

@nlutsenko why is the style #import <Parse/XYZ.h> used instead of the typical #import "XYZ.h"?
Changing all imports fixes the problem like @shushutochako's workaround does.

@BellAppLab
Copy link

One million times THIS.

Same goes for Bolts. Also, referencing Bolts with @import Bolts; rather than #import <Bolts/BFTask.h>.

I've been doing the refactoring here, @nlutsenko and will be glad to push them through.

@fluidsonic
Copy link
Contributor

Looks like Bolts imports are also affected.
Fixing just the #import <Parse/…> leads to the next error:

Pods/Parse/Parse/PFUser.h:12:9: error: include of non-modular header inside framework module 'Parse.PFUser'
#import <Bolts/BFTask.h>

Bolts is broken too:

Pods/Bolts/Bolts/Common/BFCancellationToken.h:13:9: error: include of non-modular header inside framework module 'Bolts.BFCancellationToken' [-Werror,-Wnon-modular-include-in-framework-module]
#import <Bolts/BFCancellationTokenRegistration.h>

@BellAppLab I don't think that @import is an option here since Bolts supports iOS 6+ while @import for non-system modules requires iOS 8+ afaik.
#import <Bolts/Bolts.h> should be sufficient since that's converted to @import Bolts automatically if possible.

@BellAppLab
Copy link

You're right, @fluidsonic.

@fluidsonic
Copy link
Contributor

@BellAppLab just tested it.

#import <Bolts/Bolts.h> does not work :(

Pods/Parse/Parse/PFAnalytics.h:12:9: error: include of non-modular header inside framework module 'Parse.PFAnalytics'
#import <Bolts/Bolts.h>

@BellAppLab
Copy link

Yes, @fluidsonic. I did the same test here, which is why I suggested the @import directive.

@fluidsonic
Copy link
Contributor

The correct import directive is actually #import <Bolts/Bolts-umbrella.h> when using CocoaPods with frameworks enabled. @import will most likely not work for pre-iOS 8 apps and any other apps not using CocoaPod's use_frameworks!.

@BellAppLab
Copy link

Another good call. I'll be refactoring based on these findings. If you come across anything else, please let us know, @fluidsonic.

@fluidsonic
Copy link
Contributor

Although still a workaround I think the best trick is to use a proxy header:

Bolts.h

#if __has_include(<Bolts/Bolts-umbrella.h>)
#   import <Bolts/Bolts-umbrella.h>
#else
#   import <Bolts/Bolts.h>
#endif

And then instead of #import <Bolts/…> simply use #import "Bolts.h".

This should work with and without CocoaPods & with and without modules.

@BellAppLab
Copy link

Feel free to submit those if you like.

@fluidsonic
Copy link
Contributor

Bolts: BoltsFramework/Bolts-ObjC#179
Parse: #469

Facebook SDK is also affected: https://developers.facebook.com/bugs/1512425999080858/

@nlutsenko nlutsenko reopened this Oct 26, 2015
@nlutsenko
Copy link
Contributor

Replacing angular with quoted imports is not the best thing to do (will expand more on this).
Can someone share their pod file here? I am wondering if static libraries via CocoaPods or frameworks are affected.

@fluidsonic
Copy link
Contributor

This issue only affects modules, not static libraries.
We do use use_frameworks! and thus modules.

Bolts, Parse and Facebook SDK are all broken for us due to angular imports.

After a lot of compiling and fixing we can finally build our project again using the pull requests #469, BoltsFramework/Bolts-ObjC#179 and facebook/facebook-ios-sdk#801.

@BellAppLab
Copy link

I've been keeping a bridging library between Parse and Swift, with a couple of helper methods that encapsulate common patterns in implementing Parse enabled apps: https://github.com/BellAppLab/Parsable.git

Since Xcode 7.1, there has been red warnings all over the place. The situation is dire and some locals say we are not going to recover from this ever. Back to you at the studio.

P.S.: AFAIK, when building Swift apps with Obj-C dependencies, one has to use the use_frameworks! directive, which is my case.

@BellAppLab
Copy link

Thanks, @fluidsonic. Were you able to build FB's SDK? I'm having issues with FBSDKLoginKit cross-importing internal files from FBSDKCoreKit.

@fluidsonic
Copy link
Contributor

@BellAppLab yes, we addressed the Facebook SDK issues in this pull request.

So many libraries (including Parse and Facebook SDKs) are cross-referencing headers from other frameworks. I'm happy to see that Xcode 7.1 requires the library authors to clean up their mess :)

@BellAppLab
Copy link

👆

Man, you saved my day.

@fluidsonic
Copy link
Contributor

@BellAppLab use_frameworks! is only mandatory when having Swift dependencies in CocoaPods. It's not necessary when having a Swift project with non-Swift dependencies.

@BellAppLab
Copy link

@fluidsonic Unfortunately, though: [!] Pods written in Swift can only be integrated as frameworks; add 'use_frameworks!' to your Podfile or target to opt into using it.

So if you mix and match Obj-C and Swift dependencies, you're stuck with use_frameworks!.

@fluidsonic
Copy link
Contributor

@BellAppLab yep, like I said :)

Using modules/frameworks is a good step forward towards cleaner libraries so this is good anyway.
The only real downside at the moment is a significantly increased app launch time.
But we're drifting off-topic.

@nlutsenko angular imports should be used when importing other framework's headers, not the headers of the own frameworks. Local imports should use quotes.
Also the framework could be renamed. Hard-coding the name of the framework in the import is not a good idea. Framework imports are local to the framework anyway so no need to add the name there.

@nlutsenko
Copy link
Contributor

@fluidsonic The style should explicitly be #import <Parse/....h>.
Can you post a link on why you think angular imports are wrong?

This syntax is 1:1 mappable to @import Parse.PFUser;, since both of them are using clang modulemaps. If you use the quoted import - you get 0 to no benefit from using modular imports.
Can someone please share their podfile so we at least have a repro case?

I've tested this right now with http://cl.ly/dd6C
New project, using frameworks and Xcode 7.1 + Cocoapods 0.39.
This works great!

@fluidsonic
Copy link
Contributor

@nlutsenko I agree that you use #import <Parse/XYZ.h> or @import Parse.XYZ; from OUTSIDE of the framework. But a framework doesn't import itself.

@BellAppLab
Copy link

@fluidsonic You're right. Misread it! ;)

Here's a podfile:

platform :ios, '8.0'
use_frameworks!

link_with 'SBeta', 'SBetaTests'
pod 'Parsable'
pod 'UILoader'

@fluidsonic
Copy link
Contributor

@nlutsenko
Copy link
Contributor

@fluidsonic Aha! Finally, someone got us a repro project. Thank you, let me look into it.
The problem is purely with pods that depend on Parse and integrated into the end application.
Quoted imports - still not a valid solution, there should be something else here.

angular imports should be used when importing other framework's headers, not the headers of the own frameworks. Local imports should use quotes.

Please take a look at Foundation.framework, say NSObject.h - there are imports all over the place for the same Foundation.framework.

Also the framework could be renamed. Hard-coding the name of the framework in the import is not a good idea. Framework imports are local to the framework anyway so no need to add the name there.

Framework - renamed? I don't think this is valid because first - we aren't going to rename the framework, second - as long as you are using modulemaps everything will be great.

The only reason why quoted imports work for you here, is due to custom Header Search Paths that CocoaPods sets, where headers could be found as they were local for everything!

@fluidsonic
Copy link
Contributor

System frameworks seem to be special. For example I can #import <UIKit/UIApplication.h> (so a single specific header) without issues but I cannot #import <Bolts/BFTask.h>.

Anyway quoted imports are local i.e. relative to the file which contains the import. Since all headers are in the Framework's Headers directory this will work fine.

Here's an example project with both frameworks pre-built for iPhone 4s simulator.
No CocoaPods.
No custom header search paths.
Still works.

https://www.dropbox.com/s/dicskwko04e0523/YoloTest12.zip?dl=0

@BellAppLab
Copy link

Besides, FB's SDKs weren't always called FBSDKCoreKit, FBSDKLoginKit and so forth...

@nlutsenko
Copy link
Contributor

@fluidsonic Why can't you #import <Bolts/BFTask.h> again?
I am going to try few more thing here (custom modulemap in CocoaPods).
Please note - not all pods have this error.
Example: ParseTwitterUtils is not generating any of these errors, though it depends on Parse.

@nlutsenko
Copy link
Contributor

@fluidsonic This has much wider impact than just Parse and Bolts.
CocoaPods/CocoaPods#4420 is tracking for everything else.

@fluidsonic
Copy link
Contributor

@nlutsenko ParseTwitterUtils is broken the same way.

Pods/ParseTwitterUtils/ParseTwitterUtils/ParseTwitterUtils.h:10:9: error: include of non-modular header inside framework module 'ParseTwitterUtils.ParseTwitterUtils'
#import <ParseTwitterUtils/PFTwitterUtils.h>

Good catch with the CocoaPods issue. I didn't notice the generated *-umbrella.h headers use quoted imports. Maybe the imports used in the frameworks and the imports used in the umbrella header must match starting with Xcode 7.1?
Yet there doesn't seem to be a solution yet.

A custom module map could indeed solve the problem. I'll test this too.

@nlutsenko
Copy link
Contributor

Custom module map - not a solution. Tested it right now, doesn't seem to work.
Super strange, since ParseTwitterUtils works great for me (import that pod in the project, not cross-dependant pods).

Even if you change the umbrella header to angular imports - that still doesn't work.
I think all of it comes down to Header Search Paths inside Pods/Headers/Private and that directory contains all headers, not only private ones (removing that folder from build settings solves the problem).

@fluidsonic Feel free to close those PRs, as it feels this is a wider problem that just imports in our SDK.
We can reopen that if that turns out to be the only solution.

Note on system frameworks: I think simply due to the fact, that headers there couldn't be found without angular imports - it works. Those frameworks are not special in any way when it comes down to imports.

@fluidsonic
Copy link
Contributor

@nlutsenko indeed, CocoaPods messes with the Header Search Path only for Pods, not for the project itself (at least when using frameworks) and unsetting the search path also fixes the issue.
So I think the easier way to solve this issue globally is to wait for CocoaPods to take care of it and use the pull requests as workarounds until then.

Thanks!

@nlutsenko
Copy link
Contributor

Glad I could help!
Will keep an eye out for CocoaPods issue, and will close this one out when it's fixed.

@cbot
Copy link

cbot commented Oct 27, 2015

As a temporary workaround, I added the following lines to my podfile:

post_install do |installer|
    `find Pods -regex 'Pods/Parse.*\\.h' -print0 | xargs -0 sed -i '' 's/\\(<\\)Parse\\/\\(.*\\)\\(>\\)/\\"\\2\\"/'`
    `find Pods -regex 'Pods/Bolts.*\\.h' -print0 | xargs -0 sed -i '' 's/\\(<\\)Bolts\\/\\(.*\\)\\(>\\)/\\"\\2\\"/'`
    `find Pods -regex 'Pods/Parse.*\\.h' -print0 | xargs -0 sed -i '' 's/#import <Bolts\\/BFTask.h>/#import <Bolts\\/Bolts-umbrella.h>/'`
end

@fluidsonic
Copy link
Contributor

We unset all Pod's Header Search Path as a workaround.
This might break some Pods but in our case all Pods work without problems.

Podfile:

post_install do |installer|
    installer.pods_project.targets.each do |target|
        target.build_configuration_list.set_setting('HEADER_SEARCH_PATHS', '')
    end
end

@thecritic
Copy link

@cbot +1

@chlebta
Copy link

chlebta commented Nov 9, 2015

@fluidsonic @cbot @nlutsenko
I got same issue at #import <Bolts/Bolts-umbrella.h> in Parse.PFAnalitycs.h line how to fix it please ?
The cbot & fluidsonic workaround didn't work

@chlebta
Copy link

chlebta commented Nov 10, 2015

@fluidsonic trying to use your pull request for both parse and bolts I get that annoying issue at

#if __has_include(<Bolts/Bolts-umbrella.h>)
#   import <Bolts/Bolts-umbrella.h>
#else
#   import <Bolts/Bolts.h>
#endif

The same issue at line 2 of Parse+Bolts.h file

@fluidsonic
Copy link
Contributor

@chlebta What is the issue?
I would use the Podfile workaround for now as it is more reliable.

@chlebta
Copy link

chlebta commented Nov 10, 2015

@fluidsonic I've tried the workaround but I get this issue `include of non-modular header inside framework module 'Parse.FileName'

@fluidsonic
Copy link
Contributor

When you use this workaround and run pod update then the non-modular header error should no longer occur. If it still occurs it's possible that the post_install hook in your Podfile is replaced by another post_install hook.

@hiteshvadlamudi
Copy link

Is there a solution yet. I am on Parse 1.10, ParseFacebookUtilsV4 1.9.1 and FBSDKCoreKit 4.8, FBLoginKit 4.8 and FBShareKit 4.8

I tried downgrading to Parse 1.8, Import FB 4.7 and all the above work arounds, All of them fail.

Please advice.

@cbot
Copy link

cbot commented Nov 27, 2015

Looks like the issues has been fixed in Cocoapods on the master branch, see CocoaPods/CocoaPods#4420

@nlutsenko
Copy link
Contributor

Closing this issue out, since it's been fixed in CocoaPods master.
Once again, for reference, this issue was inside how CocoaPods places headers and updates in Xcode 7.1, 7.2 regarding strict enforcement of Header Search Paths and Framework Search Paths.
There is more information available in CocoaPods/CocoaPods#4420

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

No branches or pull requests

7 participants