objective-c Swift 编译器错误:“框架模块内的非模块化头文件”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24103169/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 21:18:47  来源:igfitidea点击:

Swift compiler error: "non-modular header inside framework module"

objective-cframeworksswift

提问by Stephan

Now I would like to migrate my ObjC framework to Swift and I got the following error:

现在我想将我的 ObjC 框架迁移到 Swift,但出现以下错误:

include of non-modular header inside framework module 'SOGraphDB'

The references is to a header file which just define a protocol and I use this header file in some classes to use this protocol.

引用的是一个头文件,它只定义了一个协议,我在某些类中使用这个头文件来使用这个协议。

Is seems related to the module feature but it is at the moment not quite clear how to fix, do you know a solution?

似乎与模块功能有关,但目前尚不清楚如何修复,您知道解决方案吗?

UPDATE:

更新:

This is a Swift compiler error.

这是一个 Swift 编译器错误。

UPDATE 2:

更新 2:

A quick fix (but not solving the root cause) is to set the following setting to yes: CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES

快速修复(但不能解决根本原因)是将以下设置设置为 yes:CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES

回答by kgreenek

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.

在项目资源管理器中选择头文件。然后在 xcode 右侧的部分中,您会注意到目标旁边有一个下拉列表。将其从“项目”更改为“公共”。这对我有用。

public header

公共标题

回答by ambientlight

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 Targetto Framework Targetand start adding C and Objective C headers into framework's umbrella headerexpecting 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.

我认为大多数遇到这个问题的人是在他们切换Application TargetFramework Target并开始将 C 和 Objective C 标头添加到框架的伞头标头后导致的,期望它具有与应用程序的桥接标头相同的行为,后者的行为不同。伞头实际上是为混合的 swift 和 obj-c 框架指定的,它的目的是将 API 暴露给你的框架在objective-c 或c 中的外部世界。这意味着我们放在那里的标题应该在公共范围内。

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 Modulesdefaults to NO)

它不应该用作将不属于框架一部分的 Objective-C/C 头文件暴露给框架的 swift 代码的地方。因为在那种情况下,这些头文件也将作为我们框架模块的一部分暴露给外部世界,这通常不是我们想要做的,因为它破坏了模块化。(这正是Allows Non-modular Includes in Framework Modules默认为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 YourLegacyLibrarycan be used.

为了将 Objective-C/C 库暴露给你的框架 swift 代码,我们应该为这样的库定义一个单独的 swift 模块。然后import YourLegacyLibrary可以使用标准的swift 。

Let me demonstrate this on some typical scenario: embedding libxml2into our framework.

让我在一些典型场景中演示这一点:嵌入libxml2到我们的框架中。

1.You first need to create a module.modulemapfile which would look in this way:

1.您首先需要创建一个module.modulemap看起来像这样的文件:

For OSX framework:

对于 OSX 框架:

module SwiftLibXML2 [system] {
  header "/usr/include/libxml2/libxml/xpath.h"
  export *
}

For iOS framework:

对于 iOS 框架:

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.

它所做的只是将标头和它在 swift 模块中引用的任何其他标头包装起来,这样 swift 就能够为这些 C 接口生成 swift 绑定。

2.Then in your xcode project directory create a folder SwiftLibXML2and put this module.modulemap there

2.然后在你的xcode项目目录中创建一个文件夹SwiftLibXML2并将这个module.modulemap放在那里

3.In Build Settings, add $(SDKROOT)/usr/include/libxml2to Header Search Paths

3.Build Settings 中,添加$(SDKROOT)/usr/include/libxml2Header Search Paths

4.In Build Settings, add $(SRCROOT)/SwiftLibXML2to Import Paths

4.Build Settings 中,添加$(SRCROOT)/SwiftLibXML2Import Paths

5.Under Project's Generaltab, add libxml2.tbdto Linked Frameworks and Libraries.

5.在 Project 的General选项卡下,添加libxml2.tbdLinked 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)

(如果您想查看更完整的 module.map 示例,我建议您参考 Darwin 的 module.modulemap at /usr/include/module.modulemap,您需要安装 Xcode 命令行工具才能到达那里,请参考OS X El Capitan 中的 Missing /usr/include)

回答by funroll

Here's how to automatically apply the quick fix so you don't have to change Pods.xcodeprojmanually after each pod install.

以下是自动应用快速修复的方法,这样您就不必Pods.xcodeproj在每个pod install.

Add this snippet to the end of your Podfile:

将此代码段添加到 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

回答by Vlad Burlaciuc

Solution for me was to go on target-> build settings->Allow non-modular includesin Framework Modules switch to YES!

我的解决方案是继续目标- > 构建设置-> 允许框架模块中的非模块化包含切换到是!

回答by Jimmy Dee

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>.

我想我解决了这个问题。我有一些在框架中使用 sqlite3 的模型代码。就我而言,罪魁祸首是 <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.

问题是在我的 Module/Module.h 标头中,我导入了一个导入 <sqlite3.h> 的公共标头。解决方案是隐藏所有 sqlite3_xxx 类型并确保它们在任何公共 .h 中不可见。对 sqlite3 的所有直接引用都设为私有或项目可见性。例如,我有一个公共单例,上面挂着一些 sqlite3_stmt 指针。我将它们移到一个单独的类中,该类现在只是该公共标头中的前向声明。现在我可以建造了。

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.

顺便说一句, CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES 设置不起作用。我尝试在框架和依赖项目中设置它。这种解决方法是必要的,但我不确定为什么。

回答by King-Wizard

In Swift:

斯威夫特

1. Modify your Xcode project and targets' Build Settings as mentioned below:

1. 修改您的 Xcode 项目和目标的构建设置,如下所述:

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):

2. 使用 GoogleMaps iOS SDK 可用的当前最新版本(使用 CocoaPods 获取):

GoogleMaps (1.10.4)

谷歌地图 (1.10.4)

3. Comment the problematic import:

3. 评论有问题的导入:

//import GoogleMaps

4. Create or modify your bridging header file, adding the problematic import:

4. 创建或修改您的桥接头文件,添加有问题的导入:

[Your Xcode Project Name]-Bridging-Header.h

[您的 Xcode 项目名称]-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.

5. 清理并重新构建您的 Xcode 项目。

回答by hfossli

Don't

#import "MyOtherFramework.h"

Do

#import <MyOtherFramework/MyOtherFramework.h>

回答by seo

This answer is out-dated.

这个答案已经过时了。

When importing frameworks, you must import all header filesthat share dependencies with the root header. The easiest way to ensure this always works is to import all headers in the framework's "Headers" folder into your public headers path.

导入框架时,必须导入与根头文件共享依赖项的所有头文件。确保这始终有效的最简单方法是将框架的“Headers”文件夹中的所有标头导入您的公共标头路径。

enter image description here

在此处输入图片说明

The Swift compiler uses this information to generate a map of non-mangled symbols along with their associated type information.

Swift 编译器使用此信息来生成未损坏符号及其关联类型信息的映射。

回答by Stephan

The header file was allocated to the target but was only marked as project visible, just a change to public lead to the resolution of this error.

头文件已分配给目标,但仅标记为项目可见,只需更改为 public 即可解决此错误。

回答by Mohamed TAIEB

SwitchingBuild settings > Allow non-modular includes in Framework Modules to YES!solved the same issue for me.

构建设置 > 允许框架模块中的非模块化包含设置为YES!为我解决了同样的问题。