Ошибка компилятора 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

Stephan
источник
3
Кажется, есть новая настройка сборки для "CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES"
Стефан,
1
Кто-нибудь видел это на включениях, которые являются общедоступными и модульными? Я вижу это с помощью проекта vanilla (cocoapods): github.com/CocoaPods/CocoaPods/issues/3092 и dropbox.com/s/trhe5vwhzoa9bf5/…
Крис Коновер
Кто-нибудь сделал быстрый скрипт, который включает это автоматически?
фатухоку
@fatuhoku да
funroll
Ни одно из этих решений не помогло мне, похоже, в моем случае это было столкновение с болтами. Удаление его решило проблему: stackoverflow.com/a/33114309/3324388
Aggressor

Ответы:

316

Ваш заголовок публичный?

Выберите файл заголовка в проводнике проекта. Затем в разделе справа в xcode вы увидите выпадающий список рядом с целью. Измените это от "проекта" до "общественности". Это сработало для меня.

публичный заголовок

kgreenek
источник
Я принимаю этот ответ, даже если он такой же, как я сказал.
Стефан
Вы также можете перейти к этапу сборки заголовков вашей инфраструктуры и быстро увидеть, какие заголовки являются общедоступными, проектными и частными.
Хосе Ибаньес
Я не думал, что эта простая задача могла бы быть решением, так как я боролся с этим более часа, прежде чем приехать сюда в SO. И вот, это было именно то решение и сразу сработало.
TMc
1
А что если я хочу, чтобы эти заголовки были внутренними?
Рафаэль
2
Это также решает мою проблему! В моем случае мой один модуль, который зависит от другого модуля, не может импортировать его из-за модульной проблемы. Поэтому я сделал несколько заголовков включенными в качестве цели для другого модуля, используя публичный режим. И это решает проблему!
Чен Ли Ён
135

Это ожидаемое поведение компилятора и по очень веской причине.

Я думаю , что большинство людей , работающих в этом проблемы вызываются после того, как они переходят от Application Targetк Framework Targetи начать добавлять C и Objective C заголовки в фреймворка заголовок зонтика ожидая его , чтобы иметь такое же поведение , как Bridging заголовок приложения , который ведет себя по- разному. Заголовок зонтика фактически предназначен для смешанной быстрой среды obj-c, и его цель - представить API-интерфейсы внешнему миру, который есть у вашей платформы в target-c или c. Это означает, что заголовки, которые мы помещаем туда, должны быть в открытом доступе.

Он не должен использоваться как место, которое предоставляет заголовки Objective-C / C, которые не являются частью вашей платформы, быстрому коду вашей платформы. Потому что в этом случае эти заголовки также будут представлены внешнему миру как часть нашего каркасного модуля, что часто не то, что мы хотим сделать, поскольку это нарушает модульность. (И именно поэтому параметр « Разрешает немодульные включения в модуле фреймворка» по умолчанию равен NO )

Чтобы представить библиотеку 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 сможет генерировать привязки swift для этих интерфейсов Си.

2. Затем в каталоге вашего проекта xcode создайте папку SwiftLibXML2и поместите туда этот модуль.modulemap

3. В настройках сборки добавьте $(SDKROOT)/usr/include/libxml2в пути поиска заголовка

4. В настройках сборки добавьте $(SRCROOT)/SwiftLibXML2в пути импорта

5. В рамках проекта в Общие Вкладка, добавьте libxml2.tbdв Linked рамочные и библиотек .

Теперь вы импортируете этот модуль, где это необходимо, с помощью:

import SwiftLibXML2

(если вы хотите посмотреть более полный пример module.map, я бы посоветовал сослаться на модуль module.modulemap Дарвина, для его установки /usr/include/module.modulemapвам понадобятся инструменты командной строки Xcode, ссылка отсутствует / usr / include в OS X El Capitan )

окружающий свет
источник
1
Имя файла module.mapустарело, его следует переименовать в module.modulemap clang.llvm.org/docs/Modules.html#attributes
Hyperbole
Как import SwiftLibXML2в Objective-C? Спасибо!
Итачи
так же, как и любой другой импорт obj-c: #import <libxml / xpath.h>, но убедитесь, что вы выполнили шаги 3-5.
окружающий свет
Мы сделали это, но затем артефакт сборки нельзя перемещать между машинами: модуль Objective-C (sub), по-видимому, связан с использованием абсолютных путей, что приводит к ошибкам при компиляции, скажем, приложения, которое использует поставленную вами инфраструктуру.
Рафаэль
ошибка, скорее всего, связана с вашим процессом сборки, это всего лишь определение модуля, так что языки llvm, которые поддерживают модули, могут взаимодействовать с другими, я не думаю, что это само по себе может повлиять на ваши артефакты сборки, может ли сообщество исправить меня, если я я неправ
ambientlight
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
funroll
источник
29

Решением для меня было перейти на цель-> настройки сборки-> Разрешить немодульные включения в Framework Modules и переключиться на YES!

Влад Бурлачук
источник
Также работал с Cocoapods здесь. Не нужно делать магию из другого ответа после установки модуля
brainray
3
Я сделал этот шаг ... он работал некоторое время ... и теперь он не работает ... Я также включил шаг pod-install. Но теперь это снова терпит неудачу. Что-нибудь еще, что я должен проверить? Я не вижу GoogleMobileAds.Framework в качестве опции для изменения заголовков на Public.
Майкл Роу
Это не сработало для меня. Все еще получаю ошибку с разбора. Xcode 7.3.1
C0D3
Мне пришлось перезапустить XCode после внесения этого изменения, чтобы он заработал.
Джон Фаулер
1
Как влияет изменение этого параметра?
№5
15

Я думаю, я справился с этим. У меня есть некоторый код модели, который использует sqlite3 в рамках. В моем случае виновником был <sqlite3.h>.

Проблема заключалась в том, что в моем заголовке Module / Module.h я импортировал публичный заголовок, который импортировал <sqlite3.h>. Решением было скрыть все типы sqlite3_xxx и убедиться, что они не видны ни в одном публичном .h. Все прямые ссылки на sqlite3 были сделаны частными или видимыми для проекта. Например, у меня был публичный синглтон, на котором висели некоторые указатели sqlite3_stmt. Я переместил их в отдельный класс, который теперь является только предварительным объявлением в этом публичном заголовке. Теперь я могу строить.

Кстати, настройка CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES не работает. Я попытался установить его как в рамках, так и в зависимом проекте. Этот обходной путь был необходим, хотя я не уверен, почему.

Джимми Ди
источник
Это полностью помогло! В моем случае это была достижимость.
Даниэль Брим
4
Я почти уверен, что это решение моей проблемы, когда я пытаюсь включить SSZipArchive в модуль фреймворка. Открытый заголовок импортирует <zlib.h> и выдает ту же ошибку. Можете ли вы опубликовать свой исходный код где-нибудь, потому что я изо всех сил пытаюсь заставить его работать, так как я понимаю только часть вашего ответа ... спасибо!
Брюс
15

В Свифте :

1. Измените ваш проект Xcode и настройки сборки целей, как указано ниже:

Разрешить немодульные включения в каркасные модули: нет

Включить битовый код: да

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
для получения более подробной информации о том, как создать файл заголовка, см .: stackoverflow.com/a/51227304/529663
lenooh
6

Этот ответ устарел.

При импорте фреймворков вы должны импортировать все файлы заголовков, которые имеют общие зависимости с корневым заголовком. Самый простой способ убедиться, что это всегда работает, - импортировать все заголовки в папке «Заголовки» фреймворка в общий путь к заголовкам.

введите описание изображения здесь

Компилятор Swift использует эту информацию для генерации карты не искаженных символов вместе с информацией об их связанном типе.

поисковая оптимизация
источник
Похоже, это лишает цели наличия файлов Framework, но у меня это сработало. Chartboost и RevMob недавно начали использовать файлы Framework вместо просто библиотек. Копирование всего из их заголовков в заголовки моего приложения решает проблему.
Джейсон Шорт,
Это единственное решение? У меня есть 6 фреймворков, и у каждого есть около 20 заголовков. Это создает беспорядок. Любая альтернатива?
Вивин
1
Более чем вероятно. Это, вероятно, больше не актуально, так как это был обходной путь в ошибке XCode.
SEO
6

не

#import "MyOtherFramework.h"

Делать

#import <MyOtherFramework/MyOtherFramework.h>
hfossli
источник
3

Заголовочный файл был выделен для цели, но помечен только как видимый проект, просто изменение общедоступного приведет к устранению этой ошибки.

Stephan
источник
Как именно я могу это сделать? У меня проблемы с заголовочными файлами
TwitterKit
2

Я знаю, что это старый вопрос, но у меня была та же самая проблема, и ничто сверху не помогло мне. Поэтому я надеюсь, что мой ответ будет полезен для кого-то. В моем случае проблема была в настройке ALWAYS_SEARCH_USER_PATHS. Когда он был установлен на NO, проект строился и работал нормально. Но поскольку один из модулей требовал, чтобы он был установлен в ДА, я получал ошибку

Включение немодульного заголовка внутри модуля фреймворка

После пары чашек кофе и целого дня исследований я обнаружил, что в соответствии с известными проблемами Xcode 7.1 Beta 2 заметки о выпуске :

• Если вы получили сообщение об ошибке «Включение немодульного заголовка в модуле платформы» для ранее скомпилированной платформы, убедитесь, что для параметра сборки «Всегда искать пути пользователя» установлено значение «Нет». По умолчанию «Да» только по старым причинам. (22784786)

Я использовал XCode 7.3, но, похоже, эта ошибка еще не исправлена.

iyuna
источник
Это то, что помогло мне! Мне пришлось изменить некоторые импорта после перехода на НЕТ, но теперь я смог импортировать необходимую структуру!
Павел Гуров
2

Переключение параметров сборки> Разрешить немодульные включения в Framework Modules в YES! решил ту же проблему для меня.

Мохамед ТАИЕБ
источник
2

Я хотел бы добавить свой опыт с этой проблемой.

Просто подведу итог:

  • Ответ @ ambientlight отличный, и он решает большинство проблем.
  • разрешение немодульных заголовков - другое решение (см. некоторые ответы выше).
  • помечая заголовки фреймворка как общедоступные (только те, которые вы хотите предоставить) и импортируя их в зонтичный заголовок.

Вот мои 2 дополнения к вышеупомянутому ответу (ответам):

  • тщательно проверяйте импорт в вашем проекте для заголовков, которые импортируют ваши фреймворки непосредственно в них (вместо использования предварительного объявления, если это возможно) - не рекомендуется включать файл заголовка в другой файл заголовка; иногда это вызывает проблемы, потому что, если не сделано должным образом, это может привести к множественному включению одного заголовка и создать проблемы компоновщика.
  • ОБНОВЛЕНИЕ: убедитесь, что архитектуры библиотеки и цели, с которой вы хотите связать ее, совпадают.
  • и, наконец, после всего вышеперечисленного, я все еще продолжал сталкиваться с этой ошибкой. Поэтому я покопался еще немного и обнаружил (на форумах разработчиков Apple, но потерял ссылку :(), что если вы включите заголовки в заголовок зонтика не так <framework/headerName.h>, а только так "headerName.h", проблема исчезнет.

Я попробовал этот последний, и до сих пор у меня больше не возникало этой проблемы, однако я подозреваю, что это решение действительно, только если вы применили некоторые из лучших ответов (примечание: они не все совместимы, например, , модульный подход и разрешение немодульного заголовка включает).

Георгий Бояджиев
источник
1

У меня была именно эта проблема при включении моей собственной структуры в проект. Исправлена ​​ошибка, при которой все импорта sqlite3.h помещались в файлы .m, а не в публичные .h. Я предполагаю, что другие библиотеки могут отмечать аналогичные проблемы с Xcode.

Роб Сандерс
источник
1

У меня была конкретная проблема с Facebook 4.02 SDK и FBSDKCoreKit.

Я сделал все шаги, но все еще ошибка о немодульном заголовке. я перетаскиваю только определенный заголовок из фреймворка, чтобы построить фазы-> раздел заголовка.

Затем автоматически создается копия заголовка в навигаторе проекта вверху.

Я удалил его из фаз сборки -> заголовок и удалил новый файл и работал нормально.

Как это сброшено или что-то.

Харис
источник
1

В моем случае (Xcode 9 бета - 6 - Swift 4 - с помощью Cocoapods) это была решена , когда я удалил Podfile.lock и Бобы каталог и побежал pod installснова

m_katsifarakis
источник
1

Я получил эту проблему после обновления проекта с swift2 на swift3. Я использовал XCode 8.3.2 для обновления кода и не смог избавиться от ошибки «немодульный заголовок внутри модуля фреймворка». Когда я открыл этот же проект в другой версии XCode (версия 9.0.1), ошибка не появилась.

DevB2F
источник
0

Чаще всего эта ошибка вызвана выбранным ответом, но у меня эта ошибка появлялась однажды случайно при перетаскивании файлов фреймворка в папку моего нового проекта. Я щелкнул, чтобы удалить рамки, но случайно нажал только «Удалить ссылку» на рамки, а не фактически полностью удалить файлы. В этот момент, если я открыл папку своего проекта в Finder, я увидел там файлы типа «CoreLocation» и «AudioToolbox». Удаление этих файлов из папки проекта и очистка проекта устранили проблему.

ColossalChris
источник
0

После разрешения импорта немодульных включений вы можете попробовать импортировать этот модуль, используя заголовок Objective-C Bridging:

#import <YandexMobileMetrica/YandexMobileMetrica.h>
Юрий Коршев
источник
0

Я решил это, удалив Modulesпапку из рамок.

  • Перейдите к расположению вашего фреймворка, которое присутствует в проекте приложения с помощью поиска

  • Перейти в Test.frameworkпапку (в приведенном выше случае это будет SOGraphDB.framework) & Удалить Modulesпапку.

  • Очистите и перестройте приложение, оно решит проблему.

Витталь Пай
источник
-1

У меня была эта проблема при импорте фреймворка Parse. Единственный способ исправить это - отменить все мои изменения, так как мой последний коммит (простое удаление фреймворка и очистка проекта не сработали) и снова добавить Parse (после новой загрузки SDK) с другими необходимыми фреймворками.

amurray4
источник