目标中未找到Umbrella头文件,因此不会生成模块映射。

40

当我尝试在Xcode 6.3中将CKCountdownButton构建为框架时,它提示:

警告:未找到目标“CKCountdownButton”的伞头文件,模块映射将不会生成

然后当我在其他项目中导入此框架时,它失败了,显示 No such module 'CKCountdownButton'

5个回答

34

我找到了另一种解决方法,Xcode 提供了一种通过模块映射文件配置指定 Umbrella Header 的方式。

snapshot

module.modulemap 文件的内容应为:

framework module Foo {
    umbrella header "Bar.h"

    header "other-header.h"

    export *
    module * { export * }
}

2
模块映射语法的完整参考资料在此处:http://clang.llvm.org/docs/Modules.html#module-map-language - Patrick Pijnappel

29
在框架中添加一个名为 CKCountdownButton.h 的文件可以解决这个问题。
我认为“伞头文件”指的是与框架同名的头文件。

4
换句话说,请确保框架标题与模块名称匹配。在我的情况下,我创建了一个名为“ MyFramework macOS”的新框架目标(生成了MyFramework_macOS.h)。然后,我更改了模块名称为“ MyFramework”,但我没有更改标题。通过将标题重命名为MyFramework.h并更新其中的导出以匹配新的模块名称(从MyFramework_macOSVersionNumberMyFrameworkVersionNumber等),我解决了伞头文件的问题。 - Adam Preble

8

该目标至少需要有一个Swift文件。请检查您是否已向目标添加了Swift文件。


5

自定义框架模块映射(.modulemap)和定义模块(DEFINES_MODULE)

[模块和.modulemap]

公共文件结构:

header_1
  header_1_1
header_2

将所有应该向消费者公开的标头标记为public(header_1.h、header_2.h、header1_1.h)。 Headers 必须放在public部分[关于],否则会出现下一个错误。

//For example in umbrella.h
Include of non-modular header inside framework module '<module_name>'

//or in upper .h file
'PBURLConnectionStub.h' file not found

模块化头文件 - 包含在.modulemap中的.h文件:

  • umbrella关键字来自于umbrella.h的.modulemap
  • header关键字来自于.modulemap。

模块化头文件只能导入仅为模块化头文件。

创建一个Umbrella.h的遮盖文件 - 任何.h文件(或针对框架目标的自动生成的<product_name>.h)。在此我们称其为Umbrella.h

将根.h文件添加到umbrella file(Umbrella.h)中。所有从这些文件中导入的内容将自动添加进去。

//Umbrella.h file
#import "header_1.h"
#import "header_2.h"

使用或创建自定义的 .modulemap 文件。您可以随意命名 .modulemap 文件,在编译后它会被称为 module.modulemap。不建议您将其命名为 module.modulemap,因为这可能会导致此文件发生不可预测的更改。

module.modulemap是默认生成的文件:

//the same for Objective-C and Swift framework
framework module SomeModule {

    //umbrella header "<umbrella_name>.h"
    umbrella header "Umbrella.h"
  
    export *
    module * { export * }
}

//unique for Swift framework
module SomeModule.Swift {
    header "SomeModule-Swift.h"
    requires objc
}

伞形头

递归地公开所有模块头,生成下一个代码。

//.modulemap
framework module SomeModule {
    //explicitly define all modular header
    header "header_1.h"
    header "header_2.h"
    header "header_1_1.h"
}

//using
import SomeModule

header_1
header_2
header_1_1

多个模块

.modulemap 可以包含多个模块,其中一个必须与 PRODUCT_MODULE_NAME 相同。

//.modulemap
framework module SomeModule
framework module SomeModule2

//using
import SomeModule
import SomeModule2

子模块module

当您导入外部模块时,您可以使用来自子模块的标题。

//.modulemap
framework module SomeModule {
    module Submodule1 {
        header "header_1.h"
    }
}

//using
import SomeModuleSwift.Submodule1
//or even
import SomeModuleSwift

//availability
header_1

显式子模块 显式模块

您无法像默认情况下所示的那样使用模块名称作为子模块头。

//.modulemap
framework module SomeModule {
    explicit module Submodule1 {
        header "header_1.h"
    }
}

//using
//import SomeModuleSwift //Error: Cannot find 'header_1' in scope
import SomeModuleSwift.Submodule1

//availability
header_1

显式子模块间的依赖关系 export

//.modulemap
framework module SomeModule {
  explicit module Submodule1 {
      header "header_1.h"
      export Submodule2
  }
  explicit module Submodule2 {
      header "header_2.h"
  }
}

//using
import SomeModuleObjC.Submodule1

//availability
header_1
header_2

与Umbrella合作

module * 只能与 umbrella 一起使用,否则会出现问题。

Inferred submodules require a module with an umbrella

//.modulemap
framework module SomeModule {
  umbrella header "Umbrella.h"

  module * { export * }
  export *

下一个代码是生成的

framework module SomeModule {

  //module * { export * }
  module header_1 {
    header "header_1.h"

    export header_2 
    export header_1_1 
  }

  module header_2 {
    header "header_2.h"
    
    export header_1 
    export header_1_1 
  }

  module header_1_1 {
    header "header_1_1.h"
    
    export header_1 
    export header_2 
  }

  //export *
  export header_1 
  export header_2 
  export header_1_1 
}

//using one of them
import SomeModule.header_1 
//or 
import SomeModule.header_2
//or
import SomeModule.header_1_1 
//or
SomeModule

//availability
header_1
header_2
header_1_1

当找不到某个文件时,就会出现下面的错误。
Error: Cannot find 'header_name' in scope

要查看效果,请使用显式模块

module * - 为伞兵内的每个模块化头创建子模块

export * - 将所有子模块导出到当前子/模块

如果我们使用module * { }而不是module * { export * }import SomeModule.header_1,则没有任何变化,我们仍然可以在导入单个子模块时使用所有模块化头。这是安全的,因为父模块SomeModule可以访问所有子模块。

import SomeModule.header_1

header_1
header_2
header_1_1

如果我们使用explicit module * { }而不是explicit module * { export * }import SomeModule.header_1,我们会得到错误。
import SomeModule.header_1

header_1
//header_2 //Error: Cannot find 'header_2' in scope

生产者:

定义模块(DEFINES_MODULE)

Build Settings -> Defines Module
If YES - Xcode generates .modulemap. If `MODULEMAP_FILE` is not specified Xcode try to generate it automatically

模块映射文件(MODULEMAP_FILE)

Build Settings -> Module Map File
Path to custom `.modulemap` file
The result file `module.modulemap` will be generated and embedded into .framework

消费者:

导入路径(SWIFT_INCLUDE_PATHS)

Build Settings -> Import Paths
Path to custom `.modulemap` file

这个 import SomeModuleObjC.Submodule1 应该改为 import SomeModule.Submodule1 - Clement Prem

1

我遇到了与“GoogleToolbox”相同的问题。当我尝试更新我的pod repo时发生了一些错误。只需在终端上从项目文件夹中运行“pod install”,一切都变得正常了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接