【问题标题】:Swift compiler error: "non-modular header inside framework module"Swift 编译器错误:“框架模块内的非模块化标头”
【发布时间】:2014-07-28 23:36:10
【问题描述】:

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

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

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

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

更新:

这是一个 Swift 编译器错误。

更新 2:

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

【问题讨论】:

标签: objective-c frameworks swift


【解决方案1】:

你的标题是公开的吗?

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

【讨论】:

  • 我接受这个答案,即使它和我说的一样。
  • 您还可以进入框架的 Headers build 阶段,快速查看哪些 headers 是 Public、Project 和 Private。
  • 我不认为这个简单的任务可能是解决方案,因为我在来到这里之前已经为此奋斗了一个多小时。瞧,这正是解决方案,并立即奏效。
  • 如果我想要这些标头是内部的怎么办?
  • 这也解决了我的问题!就我而言,由于模块化问题,我的一个依赖于另一个 pod 的 pod 无法导入它。因此,我使用公共模式制作了一些标头作为另一个 pod 的目标。它解决了这个问题!
【解决方案2】:

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

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

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

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

让我在一些典型场景中演示这一点:将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.Build Settings中,将$(SDKROOT)/usr/include/libxml2添加到Header Search Paths

4.Build Settings中,将$(SRCROOT)/SwiftLibXML2添加到Import Paths

5. 在 Project 的 General 选项卡下,将 libxml2.tbd 添加到 Linked Frameworks and Libraries

现在你在需要的地方导入这个模块:

import SwiftLibXML2

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

【讨论】:

  • 文件名module.map已弃用,应改名为module.modulemap clang.llvm.org/docs/Modules.html#attributes
  • 如何在 Objective-C 中import SwiftLibXML2?谢谢!
  • 与任何其他 obj-c 导入方式相同:#import 但请确保您执行了步骤 3-5。
  • 我们这样做了,但是构建工件不能在机器之间移动:Objective-C(子)模块显然是使用绝对路径链接的,在编译时会导致错误,例如,使用你发布的框架。
  • 错误很可能是特定于您的构建过程的,这只是一个模块定义,因此支持模块的 llvm 语言可以与其他语言互操作,我认为它本身不会影响您的构建工件,如果我错了,请社区纠正我
【解决方案3】:

这是自动应用快速修复的方法,因此您不必在每个 pod install 之后手动更改 Pods.xcodeproj

将此 sn-p 添加到 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

【讨论】:

    【解决方案4】:

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

    【讨论】:

    • 这里也使用过 Cocoapods。安装 pod 后,无需从其他答案中施展魔法
    • 我已经完成了这一步..它工作了一段时间..现在它不工作了......我也包括了 pod-install 步骤。但现在又失败了。还有什么我应该检查的吗?我没有将 GoogleMobileAds.Framework 视为将标头更改为 Public 的选项。
    • 这对我不起作用。 Parse 仍然出现错误。 Xcode 7.3.1
    • 进行此更改后,我必须重新启动 XCode 才能使其正常工作。
    • 更改此设置有什么影响?
    【解决方案5】:

    Swift 中:

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

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

    启用位码:是

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

    谷歌地图 (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 项目。

    【讨论】:

    • 这很有帮助!还与 GoogleMobilAds 框架(使用 Cocoapods)配合得很好
    • 有关如何创建标题文件的详细信息,请参阅:stackoverflow.com/a/51227304/529663
    【解决方案6】:

    我想我解决了这个问题。我有一些在框架中使用 sqlite3 的模型代码。就我而言,罪魁祸首是

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

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

    【讨论】:

    • 这完全有帮助!就我而言,它是可达性。
    • 当我尝试在我的框架模块中包含 SSZipArchive 时,我很确定这是我的问题的解决方案。公共标头正在导入 并给出相同的错误。你能把你的源代码贴在某个地方吗,因为我只理解你的部分答案,所以我很难让它工作。谢谢!
    【解决方案7】:

    不要

    #import "MyOtherFramework.h"
    

    #import <MyOtherFramework/MyOtherFramework.h>
    

    【讨论】:

      【解决方案8】:

      这个答案已经过时了。

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

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

      【讨论】:

      • 这似乎违背了拥有框架文件的目的,但它对我有用。 Chartboost 和 RevMob 最近都开始使用框架文件而不仅仅是库。将所有内容从它们的标头复制到我的应用标头即可解决问题。
      • 这是唯一的解决方案吗?我有 6 个框架,每个框架都有大约 20 个标题。它会造成混乱。有替代品吗?
      • 很有可能。这可能不再相关,因为它是 Xcode 错误中的一种解决方法。
      【解决方案9】:

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

      【讨论】:

      • 我该怎么做呢?我的 TwitterKit 头文件有问题
      【解决方案10】:

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

      【讨论】:

        【解决方案11】:

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

        在框架模块中包含非模块化标头

        在喝了几杯咖啡和一整天的研究之后,我发现根据Xcode 7.1 Beta 2 release notes的已知问题:

        • 如果您收到一条错误消息,指出“在框架模块中包含非模块化标头” 之前编译的框架,确保“始终搜索用户路径” 构建设置设置为“否”。仅出于遗留原因,默认值为“是”。 (22784786)

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

        【讨论】:

        • 这对我有帮助!切换到 NO 后,我不得不更改一些导入,但现在我能够导入我需要的框架!
        【解决方案12】:

        我也想补充一下我对这个问题的经验。

        总结一下:

        • @ambientlight 的回答很棒,它解决了大部分问题。
        • 允许非模块化标头是另一种解决方案(请参阅上面的一些答案)。
        • 将框架的标头标记为公开(仅您想要公开的标头)并将它们导入到伞形标头中。

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

        • 仔细检查项目中的导入是否有直接将框架导入其中的头文件(如果可能,不要使用前向声明)——在另一个头文件中包含一个头文件不是一个好习惯;有时这会导致问题,因为如果处理不当,可能会导致多个包含一个标头并产生链接器问题。
        • 更新:确保库的架构与您要链接它的目标的架构相匹配。
        • 最后,在完成上述所有操作后,我仍然不断遇到该错误。所以我又挖了一点,发现(在苹果开发者论坛中,但我丢失了链接:()如果你在伞形标题中包含标题不是这样&lt;framework/headerName.h&gt;,而只是像这样"headerName.h",问题消失。

        我尝试了最后一个,到目前为止我还没有遇到过这个问题,但是我怀疑这个解决方案只有在你应用了一些最重要的答案时才有效(注意:它们并不都相互兼容,例如模块方法和允许非模块头包含)。

        【讨论】:

          【解决方案13】:

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

          【讨论】:

            【解决方案14】:

            我遇到了 Facebook 4.02 sdk 和 FBSDKCoreKit 的具体问题。

            我完成了所有步骤,但关于非模块化标题仍然出错。我只从框架中拖放特定的标题来构建阶段->标题部分。

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

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

            喜欢它重置什么的。

            【讨论】:

              【解决方案15】:

              在我的情况下(Xcode 9 beta 6 - Swift 4 - 使用 Cocoapods),当我删除 Podfile.lockPods 目录并运行 pod install 时,这个问题得到了解决再次

              【讨论】:

                【解决方案16】:

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

                【讨论】:

                  【解决方案17】:

                  我尝试了在此线程设置目标上找到的所有可能的解决方案-> 构建设置->允许框架模块中的非模块化包含切换到“是”!等等等等。

                  但没有任何效果。

                  当我通过评论 use_frameworks 安装 pod 时开始收到此错误! ,因为我想拥有 pod 的静态库。

                  Swift 编译器抛出(在 Xcode 13 上)此错误的原因是我正在导入私有框架头文件 #import "TFLTensorFlowLite.h" 在公共 .h 文件中,所以我将它导入到 .m 文件中,如下面的屏幕截图所示,它停止了 Swift 编译器抛出此错误(注意我的框架同时具有 Objective c 和 swift 代码)

                  【讨论】:

                  • 对不起,我无能为力:( ...我没有再关注这个问题了
                  【解决方案18】:

                  最常见的这个错误是由选择的答案引起的,但是当我将框架文件拖到我的新项目文件夹中时,我偶然出现了一次这个错误。我单击以删除框架,但不小心按下了对框架的“删除引用”,而不是实际完全删除文件。此时,如果我在 Finder 中打开我的项目文件夹,我会在那里看到像“CoreLocation”和“AudioToolbox”这样的文件。从项目文件夹中删除这些文件并清理项目解决了该问题。

                  【讨论】:

                    【解决方案19】:

                    在允许导入非模块化包含后,您可以尝试使用 Objective-C 桥接头导入该模块:

                    #import <YandexMobileMetrica/YandexMobileMetrica.h>
                    

                    【讨论】:

                      【解决方案20】:

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

                      • 使用查找器浏览到应用程序项目中存在的框架位置

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

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

                      【讨论】:

                        【解决方案21】:

                        我在导入 Parse 框架时遇到了这个问题。我可以修复它的唯一方法是放弃自上次提交以来的所有更改(简单地删除框架并清理项目不起作用)并再次添加 Parse(在重新下载 SDK 后)及其其他所需的框架。

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 2015-06-28
                          • 2017-12-19
                          • 2015-08-07
                          • 2016-11-20
                          • 2016-05-25
                          • 2017-07-08
                          • 1970-01-01
                          • 2016-02-18
                          相关资源
                          最近更新 更多