Что такое экспорт * в файле module.modulemap внутри каждого фреймворка?
Я создал один фреймворк с именем Communication
Внутри рамочного контейнера есть один module.modulemap
файл.
module.modulemap
framework module Communication {
umbrella header "Communication.h"
export *
module * { export * }
}
Я могу понять, что модуль требовал зонтичного заголовка, чтобы выставить его содержащему приложение / цель.
Но в чем смысл двух других строк кода?
export *
module * { export * }
Если у кого есть идеи, что эти строки экспортируют?
3 ответа
Modular Framework
содержит .modulemap
файл по следующему пути
module_name.framework/Modules/module_name.modulemap
Что касается именования, мое правило
ProductName -> Product Module Name -> <name>.modulemap -> framework module <name>
Когда вы создаете библиотеку, вы должны создать и настроить ее вручную [Custom modulemap], когда вы создаете фреймворк, Xcode генерирует его автоматически, еслиBuild Settings -> Defines Module -> YES
.
Когда вы создаете свой .modulemap
файл вы должны обновить путь в Build Settings -> Module Map File
Давайте посмотрим на пример:
Примечание: я используюexplicit module
чтобы показать, что Xcode будет генерировать ошибки
//ClassA.h
#import "ClassAA.h"
//ClassB.h
//ClassAA.h
//Module.h
#import "ClassA.h"
#import "ClassB.h"
//Module.modulemap
framework module Module {
//Expose all imports from Module.h for Module module recursively
// import Module - you can use ClassA, ClassB, ClassAA
umbrella header "Module.h"
//explicit module * { }
// 1. `module` works only with `umbrella`
// 2. Generates a submodule for every header inside Module.h recursively
// import Module.ClassA, import Module.ClassB, import Module.ClassC
//explicit module * { export * }
//export all imports from <submodule_name>.h for <submodule_name> module
// import Module.ClassA - you can use ClassA, ClassAA (ClassAA was added)
explicit module * { export * }
//export all imports from Module.h for Module module
// import Module.ClassA - you can use ClassA, ClassAA, ClassB(ClassB was added)
export *
}
Что помогло мне разобраться в ключевых словах и в файлах, так это поиграть с ними. Я нашел документацию Clang &gt; Modules сложной для понимания. Я суммирую некоторые эксперименты, которые я проводил 1 , чтобы дать вам представление о том, чтоmodule
ключевые слова означают на практике. Я обнаружил, что поведение файла в коде Objective-C и Swift отличается, поэтому я рассмотрю оба варианта отдельно.
Предположим, ваш заголовочный файл состоит из следующих двух импортов:
#import <Communication/Class1.h>
#import <Communication/Class2.h>
Предположим также, чтоClass1.h
определяет один класс с именем иClass2.h
определяет один класс с именем .
Импорт модулей в классы Objective-C
Предположим, для начала, что ваш файл определен минимально следующим образом:
В классах Objective-C ваших целей, которые связаны с платформой, вы можете импортировать модуль и вызывать классы, импортированные через зонтичный заголовочный файл, следующим образом:
@import Communication;
+ (void)someMethodThatDependsOnTheCommunicationModule {
[Class1 someOperation];
[Class2 someOperation];
}
Чего вы сейчас не можете сделать, так это импортировать подмодуль. Чтобы это стало возможным, вам нужно изменить файл на следующее:
framework module Communication {
umbrella header "Communication.h"
module Class1 {
header "Class1.h"
}
}
Теперь вы можете импортировать подмодуль и вызвать его следующим образом:
@import Communication.Class1;
+ (void)someMethodThatDependsOnTheCommunicationModule {
[Class1 someOperation];
}
Конечно, вы по-прежнему не можете импортировать подмодуль. Чтобы сделать это возможным, вы можете либо добавить объявление модуля в файл, как мы это сделали, либо использовать подстановочный знак 2. Вот как это можно сделать с помощью подстановочного знака:
Благодаря этому изменению вы теперь можете импортировать подмодули и и вызывать их классы следующим образом:
@import Communication.Class1;
@import Communication.Class2;
+ (void)someMethodThatDependsOnTheCommunicationModule {
[Class1 someOperation];
[Class2 someOperation];
}
Я изо всех сил старался найти применение этому ключевому слову в контексте модулей, которые будут импортированы в код Objective-C, но мне это не удалось.
Импорт модулей в классы Swift
Предположим, для начала, что ваш файл определен минимально следующим образом:
framework module Communication {
umbrella header "Communication.h"
}
В классах Swift ваших целей, которые связаны с фреймворком, вы можете импортироватьCommunication
модуль, и вы можете вызывать классы, импортированные черезCommunication.h
заголовочный файл зонтика, например:
import Communication
func someFunctionThatDependsOnTheCommunicationModule {
Class1.someOperation()
Class2.someOperation()
}
Чего вы сейчас не можете сделать, так это импортировать подмодуль. Чтобы это стало возможным, вам нужно изменить файл на следующее:
framework module Communication {
umbrella header "Communication.h"
module Class1 {}
}
Теперь вы можете импортировать подмодуль и вызвать его следующим образом:
import Communication.Class1
func someFunctionThatDependsOnTheCommunicationModule {
Class1.someOperation()
}
В отличие от того, что я испытал при использовании Objective-C3 , я обнаружил, что все еще могу звонить, несмотря на импортCommunication.Class1
только.
Если вы все еще хотите импортироватьCommunication.Class2
изолированно 4 , вы можете либо добавитьClass2
объявление модуля вmodulemap
файл, как мы это сделали дляClass1
или используйте подстановочный знак 2. Вот как это можно сделать с помощью подстановочного знака:
framework module Communication {
umbrella header "Communication.h"
module * {}
}
Я изо всех сил старался найти применение этомуexport
ключевое слово в контексте модулей, которые будут импортированы в код Swift, но мне это не удалось.
2 Подстановочный знак будет определять модуль для каждого класса, определенного заголовками, импортированными в зонтичный заголовочный файл.
3 И вопреки моим ожиданиям.
4 Несмотря на то, что это совершенно бессмысленно, как объяснено в предыдущем абзаце.
framework module Communication { // Define a module with framework semantics
umbrella header "Communication.h" // Use the imported headers in the umbrella header to define the module
export * // Re-export all symbols from submodules into the main module
module * { export * } // Create a submodule for every header in the umbrella header
}
module *
указывает, что все заголовочные файлы, импортированные в зонтик Communication.h, сами являются подмодулями.
export *
внутри module *
объявляет, что любой файл заголовка, импортированный из этих файлов заголовка - которые импортированы в зонтике - также является субмодулями.