no umbrella header found for target, module map will not be generated
Asked Answered
S

5

40

When I trying build CKCountdownButton as a framework in Xcode 6.3, it complains with

warning: no umbrella header found for target 'CKCountdownButton', module map will not be generated

Then when I import this framework in other project, it failed with No such module 'CKCountdownButton'

Sikko answered 8/6, 2015 at 8:21 Comment(0)
S
29

Add a CKCountdownButton.h in framework fixed this issue.

I think the umbrella header means the header file with same name like Framework

Sikko answered 13/6, 2015 at 5:39 Comment(1)
In other words, make sure the framework header matches the module name. In my case I had created a new framework target named "MyFramework macOS" (which generated MyFramework_macOS.h). I then changed the module name to "MyFramework", but I didn't change the header. I fixed the umbrella header issue by renaming the header to MyFramework.h and updating the exports within it to match the new module name (MyFramework_macOSVersionNumber to MyFrameworkVersionNumber, etc.).Dempster
S
34

I found another solution, Xcode provides a way to specify umbrella header through Module Map File configuration.

snapshot

The contents of module.modulemap should be:

framework module Foo {
    umbrella header "Bar.h"

    header "other-header.h"

    export *
    module * { export * }
}
Sikko answered 13/7, 2015 at 10:13 Comment(1)
Complete reference for the modulemap syntax here: clang.llvm.org/docs/Modules.html#module-map-languageQuarterback
S
29

Add a CKCountdownButton.h in framework fixed this issue.

I think the umbrella header means the header file with same name like Framework

Sikko answered 13/6, 2015 at 5:39 Comment(1)
In other words, make sure the framework header matches the module name. In my case I had created a new framework target named "MyFramework macOS" (which generated MyFramework_macOS.h). I then changed the module name to "MyFramework", but I didn't change the header. I fixed the umbrella header issue by renaming the header to MyFramework.h and updating the exports within it to match the new module name (MyFramework_macOSVersionNumber to MyFrameworkVersionNumber, etc.).Dempster
H
8

That target needs to have at least 1 Swift file. Check that you have Swift files added to the target

Hyperspace answered 2/6, 2017 at 8:45 Comment(0)
M
6

Custom framework module map(.modulemap) and Defines Module(DEFINES_MODULE)

[Module and .modulemap]

Public file structure:

header_1
  header_1_1
header_2

Mark all headers which should be exposed for consumer as public(header_1.h, header_2.h, header1_1.h). Headers public section[About] or you get next error.

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

modular headers - .h files which included into .modulemap:

  • .modulemap umbrella keyword from umbrella.h
  • .modulemap header keyword.

Modular headers can import only modular headers

Create an umbrella file - any .h file (or autogenerated <product_name>.h for Framework target). Let's call it Umbrella.h

Add root .h files into umbrella file(Umbrella.h). All imports from this files will be added automatically

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

Use or create a custom .modulemap file. You can call the .modulemap file as you wish, after compiling it will be called module.modulemap. Also I would not recommend you to call it as module.modulemap because it can cause unpredictable changes of this file

module.modulemap which is generated by default:

//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
}

umbrella header

Expose all module headers recursively. Generates next code

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

multiple modules

.modulemap can contain multiple modules. One of them must have the same name as PRODUCT_MODULE_NAME

//.modulemap
framework module SomeModule
framework module SomeModule2

//using
import SomeModule
import SomeModule2

Submodule module

When you import Outer module you are able to use headers from sub module

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

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

//availability
header_1

explicit submodule explicit module

You are not able to use module name for submodule header(as you can do by default as shown in previous example)

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

Dependencies between explicit submodules 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

Work with Umbrella

module * works only with umbrella, if not you get

Inferred submodules require a module with an umbrella
//.modulemap
framework module SomeModule {
  umbrella header "Umbrella.h"

  module * { export * }
  export *

next code is generated

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

When some file can not be found next error is occurred

Error: Cannot find 'header_name' in scope

To see the effect use explicit module

module * - creates submodule for every modular header inside umbrella

export * - export all submodule into current sub/module

If we use module * { } instead of module * { export * } and import SomeModule.header_1 nothing changed we steal can use all modular headers when import a single submodule. It is safety because parent module SomeModule has an access to all submodules

import SomeModule.header_1

header_1
header_2
header_1_1

If we use explicit module * { } instead of explicit module * { export * } and import SomeModule.header_1 we get error

import SomeModule.header_1

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

Producer:

Defines Module(DEFINES_MODULE)

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

Module Map File(MODULEMAP_FILE)

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

Consumer:

Import Paths(SWIFT_INCLUDE_PATHS)

Build Settings -> Import Paths
Path to custom `.modulemap` file
Morbidity answered 26/8, 2019 at 22:15 Comment(1)
should this import SomeModuleObjC.Submodule1 change to import SomeModule.Submodule1Locomotion
E
1

I had the same problem with 'GoogleToolbox'. It happened when I tried to update my pod repo and some error happened. Just did 'pod install' from terminal on the project folder and everything got ok.

Endostosis answered 10/5, 2018 at 6:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.