Swift编译器错误:“框架模块内的非模块化标头”


204

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

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

引用指向仅定义协议的头文件,我在某些类中使用此头文件来使用此协议。

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

更新:

这是Swift编译器错误。

更新2:

一种快速的解决方法(但不能解决根本原因)是将以下设置设置为yes:CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES


3
似乎有一个新的构建设置“ CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES”
Stephan

1
有没有人看到过包含公共和模块化的内容?我认为这与香草(的CocoaPods)项目:github.com/CocoaPods/CocoaPods/issues/3092dropbox.com/s/trhe5vwhzoa9bf5/...
克里斯·康诺弗

是否有人制作了自动启用此功能的快速脚本?
fatuhoku

@fatuhoku yeah
funroll

这些解决方案都不适合我,在我看来,这似乎是一个bolts.framework冲突。删除它可以解决问题:stackoverflow.com/a/33114309/3324388
Aggressor 2015年

Answers:


316

您的标头公开吗?

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

公共头


我接受这个答案,即使它与我所说的相同。
Stephan

您还可以进入框架的Headers构建阶段,并快速查看哪些Header是Public,Project和Private。
Jose Ibanez 2014年

我不认为这个简单的任务可能是解决方案,因为我在来到这里之前已经花了一个多小时与之抗争。瞧,这完全是解决方案,可以立即工作。
TMc

1
如果我希望这些标头位于内部,该怎么办?
拉斐尔

2
这也解决了我的问题!就我而言,由于模块化问题,依赖于另一个容器的一个容器无法导入它。因此,我使用了公共模式,将一些标头作为另一个pod的目标。它解决了这个问题!
陈李甬

135

这是预期的编译器行为,并且有很好的理由。

我认为大多数遇到此问题的人是从他们切换Application TargetFramework Target并开始将C和Objective C标头添加到框架的伞形标头之后引起的,他们期望它具有与应用程序的Bridging标头相同的行为,但行为不同。伞头实际上是为混合快速obj-c框架指定的,其目的是将API暴露给您的框架在Objective-c或c中拥有的外部世界。这意味着我们放在其中的标题应该在公共范围内。

它不应用作将不属于框架的Objective-C / C标头暴露给框架的快速代码的地方。因为在这种情况下,这些标头也将作为框架模块的一部分公开给外界,这通常不是我们想要做的,因为它破坏了模块性。(这就是为什么在框架模块中允许非模块化包含默认为NO的原因

为了向您的框架swift代码公开Objective-C / C库,我们应该为该库定义一个单独的swift模块。然后import YourLegacyLibrary可以使用标准的swift 。

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

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

对于OSX框架:

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

对于iOS框架:

module SwiftLibXML2 [system] {
  header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/libxml2/libxml/xpath.h"
  export *
}

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

2.然后在xcode项目目录中创建一个文件夹SwiftLibXML2,并将此module.modulemap放在此处

3.在“ 构建设置”中,添加$(SDKROOT)/usr/include/libxml2标题搜索路径

4.在“ 构建设置”中,添加$(SRCROOT)/SwiftLibXML2到“ 导入路径”

5.在Project的General选项卡下,添加libxml2.tbdLinked Frameworks and Libraries

现在,您需要通过以下方式导入此模块:

import SwiftLibXML2

(如果您想看一个更完整的module.map示例,我建议您参考处的Darwin的module.modulemap /usr/include/module.modulemap,您需要在此安装Xcode命令行工具,并参考OS X El Capitan中的Missing / usr / include


1
该文件名module.map已弃用,应重命名为module.modulemap clang.llvm.org/docs/Modules.html#attributes
Hyperbole

如何import SwiftLibXML2在Objective-C中?谢谢!
Itachi 2016年

与其他obj-c导入方法相同:#import <libxml / xpath.h>,但请确保已执行步骤3-5。
光'16

我们这样做了,但是构建工件无法在机器之间移动:Objective-C(子)模块显然是使用绝对路径链接的,因此在编译(例如使用您附带的框架的应用程序)时会导致错误。
拉斐尔

该错误很可能是特定于您的构建过程的,这只是一个模块定义,因此支持模块的llvm语言可以与其他语言互操作,我认为它本身不会影响您的构建工件,如果我愿意,社区是否可以纠正我是错的

55

这是自动应用快速修复的方法,因此您无需Pods.xcodeproj在每次之后都进行手动更改pod install

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

29

对我来说,解决方案是继续目标- >构建设置->允许将 Framework Modules中的非模块化包含项切换为YES!


在这里也与Cocoapods合作。吊舱安装后,无需从其他答案中
解脱出来

3
我已经完成了此步骤..它工作了一段时间..现在却不起作用...我也包括了pod-install步骤。但是现在又失败了。我还有什么要检查的吗?我没有看到GoogleMobileAds.Framework作为将标头更改为Public的选项。
Michael Rowe 2015年

这对我不起作用。解析仍然出现错误。Xcode 7.3.1
C0D3 '16

进行此更改后,我必须重新启动XCode才能起作用。
约翰·福勒

1
更改此设置会有什么影响?
nr5

15

我想我已经解决了。我有一些在框架中使用sqlite3的模型代码。就我而言,罪魁祸首是<sqlite3.h>。

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

顺便说一句,CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES设置无效。我尝试同时在框架和相关项目中进行设置。尽管我不确定为什么,但这种解决方法是必要的。


这完全有帮助!就我而言,就是可达性。
Daniel Brim 2014年

4
当我尝试在框架模块中包含SSZipArchive时,我很确定这是解决我问题的方法。公共标头正在改进<zlib.h>并给出相同的错误。您能将源代码发布到某个地方吗,因为我一直无法使它正常工作,因为我只了解您的答案的一部分..谢谢!
2015年

15

Swift中

1.如下所述修改您的Xcode项目和目标的Build Settings:

允许非模块化模块包含在框架模块中:否

启用位码:是

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

GoogleMaps(1.10.4)

3.评论有问题的导入:

//import GoogleMaps

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

[您的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.清理并重新构建Xcode项目。


1
这很有帮助!也可以很好地与GoogleMobilAds框架(与Cocoapods一起使用)
bluenowhere 2015年

有关如何创建标题文件的更多详细信息,请参见:stackoverflow.com/a/51227304/529663
lenooh

6

这个答案已经过时了。

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

在此处输入图片说明

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


这似乎破坏了拥有Framework文件的目的,但是对我有用。Chartboost和RevMob最近都开始使用Framework文件,而不仅仅是库文件。将所有内容从其标头复制到我的应用程序标头即可解决此问题。
杰森·肖特

这是唯一的解决方案吗?我有6个框架,每个框架都有大约20个标头。它造成混乱。还有其他选择吗?
vivin

1
更有可能。这可能不再相关,因为它是Xcode错误中的解决方法。
seo 2015年

6

#import "MyOtherFramework.h"

#import <MyOtherFramework/MyOtherFramework.h>

3

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


我到底该怎么做?我的TwitterKit头文件遇到了麻烦
Vinod Sobale

2

我知道这是一个古老的问题,但是我遇到了同样的问题,但上面没有任何帮助。因此,我希望我的回答对某人有所帮助。就我而言,问题出在ALWAYS_SEARCH_USER_PATHS设置中。当它设置为NO时,没有项目可以正常工作。但是就其中一个Pod要求将其设置为YES,我收到了一个错误

在框架模块内包含非模块化头

经过几杯咖啡和整天的研究,我发现根据Xcode 7.1 Beta 2的已知问题发行说明

•如果对于先前编译的框架出现错误,指出“在框架模块中包含非模块头”,请确保将“始终搜索用户路径”构建设置设置为“否”。仅出于传统原因,默认值为“是”。(22784786)

虽然我使用的是XCode 7.3,但似乎此错误尚未修复。


这就是帮助我的原因!切换到NO后,我不得不更改一些导入,但是现在我可以导入所需的框架了!
帕维尔·古洛夫

2

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


2

我也想补充我的经验。

总结一下:

  • @ambientlight的答案很好,它可以解决大多数问题。
  • 允许使用非模块化标头是另一种解决方案(请参见上面的一些答案)。
  • 将框架的标头标记为公共(仅是要公开的标头),并将其导入到伞形标头中。

这是我对上述答案的2个补充:

  • 仔细检查项目中的导入是否包含将框架直接导入框架中的标头(如果可能,请不要使用前向声明)–在另一个标头文件中包含标头文件不是一个好习惯;有时这会引起问题,因为如果处理不当,可能会导致一个标头的多个包含,并导致链接程序问题。
  • 更新:确保库的结构与要链接它的目标的结构相匹配。
  • 最后,完成上述所有操作后,我仍然不断遇到该错误。因此,我进行了更多研究,发现(在苹果开发人员论坛中,但我丢失了链接:(),如果您在伞形标头中包含标头不是这样<framework/headerName.h>,而是仅这样"headerName.h",问题就消失了。

我尝试了最后一个,到目前为止,我再也没有遇到过这个问题,但是,我怀疑只有当您应用了一些最佳答案后,该解决方案才有效(请注意:例如,它们并不完全兼容。 ,模块方法和允许非模块化标头包括)。


1

在项目中包含自己的框架时,我遇到了这个确切的问题。通过将所有导入的sqlite3.h放在.m文件中而不是在公共.h文件中来解决此问题。我假设其他库可能会用Xcode标记类似的问题。


1

我在使用Facebook 4.02 SDK和FBSDKCoreKit时遇到了特定问题。

我做了所有步骤,但仍然出现关于非模块化标头的错误。我只将特定的标头从框架中拖放到构建阶段->标头部分。

然后在顶部的项目导航器上自动创建标题的副本。

我从构建阶段->标头中删除了它,并删除了新文件,并且工作正常。

喜欢它重置或什么。


1

就我而言(Xcode 9 beta 6-Swift 4-使用Cocoapods),当我删除Podfile.lockPods目录并pod install再次运行时,此问题已解决。


1

将项目从swift2更新到swift3后,出现了这个问题。我使用XCode 8.3.2更新代码,无法摆脱错误“框架模块内部的非模块化标头”。当我在另一个版本的XCode(版本9.0.1)中打开相同的项目时,未出现错误。


0

通常,此错误是由选择的答案引起的,但是当我将框架文件拖到新的项目文件夹中时,我曾经偶然出现此错误。我单击以删除框架,但无意间只按了“删除对框架的引用”,而不是真正地完全删除了文件。此时,如果我在Finder中打开项目文件夹,则会在其中看到“ CoreLocation”和“ AudioToolbox”之类的文件。从项目文件夹删除这些文件并清理项目解决了该问题。



0

我解决了Modules从框架中删除文件夹的问题。

  • 使用查找器浏览到App Project中存在的框架位置

  • 进入Test.framework文件夹(在上述情况下为SOGraphDB.framework)并删除Modules文件夹。

  • 清理并重新构建应用程序,它将解决问题。


-1

我在导入Parse框架时遇到了这个问题。我可以解决的唯一方法是放弃自上次提交以来的所有更改(仅删除框架并清理项目无法正常工作),然后再次(在重新下载SDK之后)将Parse与其他必需的框架一起添加。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.