Помилка компілятора Swift: "немодульний заголовок всередині модуля рамки"


204

Тепер я хотів би перенести мою рамку ObjC на Swift, і я отримав таку помилку:

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

Посилання на файл заголовка, який просто визначає протокол, і я використовую цей файл заголовка в деяких класах, щоб використовувати цей протокол.

Здається, пов'язане з функцією модуля, але наразі не зовсім зрозуміло, як виправити, чи знаєте ви рішення?

ОНОВЛЕННЯ:

Це помилка компілятора Swift.

ОНОВЛЕННЯ 2:

Швидке виправлення (але не вирішення першопричини) полягає у встановленні наступного параметра так: CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = ТАК


3
Здається, є новий параметр збірки для "CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES"
Стефан

1
Хтось бачив це на включеннях, які є публічними та модульними? Я бачу це у проекті з ваніллю (какаоподи): github.com/CocoaPods/CocoaPods/isissue/3092 та dropbox.com/s/trhe5vwhzoa9bf5/…
Кріс Коновер,

Хтось зробив швидкий сценарій, який дозволяє це автоматично?
fatuhoku

@fatuhoku так
funroll

Жодне з цих рішень не працювало для мене, схоже, це було зіткнення болтів. Рамки в моєму випадку. Видалення це вирішило проблему: stackoverflow.com/a/33114309/3324388
Агресор

Відповіді:


316

Ваш заголовок загальнодоступний?

Виберіть файл заголовка в провіднику проектів. Потім у розділі праворуч у xcode ви помітите, що поруч із ціллю є спадне місце. Змініть це з "проекту" на "загальнодоступне". Це працювало для мене.

загальнодоступний заголовок


Я приймаю цю відповідь, навіть це те саме, що я заявив.
Стефан

Ви також можете перейти до фази побудови заголовків вашого фреймворку та швидко побачити, які заголовки є загальнодоступними, проектними та приватними.
Хосе Ібанез

Я не думав, що це просте завдання могло б бути вирішенням, оскільки я боровся з цим більше години, перш ніж приїхати сюди до SO. Ось, ось це РЕШИМЕ рішення і працював негайно.
TMc

1
А що, якщо я хочу, щоб ці заголовки були внутрішніми?
Рафаель

2
Це також вирішує мою проблему! У моєму випадку мій один стручок, який залежить від іншого стручка, не може імпортувати його через модульну проблему. Тож я зробив деякі заголовки, включені як ціль для іншого стручка, використовуючи загальнодоступний режим. І це вирішує питання!
Чень Лі Йонг

135

Це очікувана поведінка компілятора і з дуже поважної причини.

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

Він не повинен використовуватися як місце, яке виставляє заголовки Objective-C / C, які не є частиною вашої системи, швидким кодом вашої рамки. Тому що в цьому випадку ці заголовки також будуть піддані впливу зовнішнього світу як частини нашого базового модуля, що часто не є тим, що ми хочемо зробити, оскільки це порушує модульність. (І саме тому Дозволяє Немодульна Включає в Рамкові модулі за замовчуванням НІ )

Для того, щоб відкрити бібліотеку Objective-C / C до вашого швидкого коду фреймворку, ми повинні визначити окремий модуль swift для такої бібліотеки. Тоді import YourLegacyLibraryможна використовувати стандартний стрімкий .

Дозвольте мені продемонструвати це за деяким типовим сценарієм: вбудовування libxml2у наші рамки.

1. Спочатку потрібно створити module.modulemapфайл, який виглядатиме так:

Для ОСX:

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

Все, що він робить, - це загортання заголовка та будь-яких інших заголовків, на які він посилається всередині модуля швидкого переходу, так що швидкий зможе потім створити швидкі прив’язки для цих інтерфейсів С.

2. Тоді у своєму каталозі проектів xcode створіть папку SwiftLibXML2і помістіть туди цей module.modulemap

3. У Налаштуваннях збірки додайте $(SDKROOT)/usr/include/libxml2до Шляхів пошуку заголовків

4. У налаштуваннях збірки додайте $(SRCROOT)/SwiftLibXML2до імпорту шляхів

5. На вкладці Загальне проекту додайте libxml2.tbdдо пов'язаних рамок і бібліотек .

Тепер ви імпортуєте цей модуль, де потрібно:

import SwiftLibXML2

(якщо ви хочете переглянути більш повний приклад module.map, я б запропонував посилатись на модуль Dar.'s module.modulemap /usr/include/module.modulemap, вам потрібно буде встановити інструменти командного рядка Xcode, щоб перейти туди, посилання Missing / usr / включити в 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

29

Для мене вирішенням було стати на цільову-> налаштування збірки-> Дозволити немодульні включення в рамкові модулі перейти на ТАК!


Тут також працювали з Cocoapods. Не потрібно робити магію з іншої відповіді після встановлення стручка
мозковий масив

3
Я зробив цей крок .. він працював деякий час .. і зараз він не працює ... Я також включив крок встановлення pod. Але вона знову провалюється. Що ще я повинен перевірити? Я не бачу GoogleMobileAds.Framework як варіант зміни заголовків на Public.
Майкл Роу

Це не спрацювало для мене. Проблема все ще отримує Parse. Xcode 7.3.1
C0D3

Мені довелося перезапустити XCode після внесення цієї зміни для роботи.
Джон Фоулер

1
Який вплив може змінити цей параметр?
nr5

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. Використовуйте останню останню версію, доступну для iOS SDK GoogleMaps (використовуйте 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, а не просто libs. Копіювання всього із заголовків до моїх заголовків додатків вирішує проблему.
Jason Short

Це єдине рішення? У мене є 6 рамок, і кожен фреймворк має близько 20 заголовків. Це створює безлад. Будь-який заступник?
vivin

1
Більше ніж ймовірно. Це, мабуть, більше не актуально, оскільки це було вирішенням помилки Xcode.
seo

6

Не варто

#import "MyOtherFramework.h"

Зробіть

#import <MyOtherFramework/MyOtherFramework.h>

3

Файл заголовка був виділений цілі, але він був позначений лише як проект, який видно, лише зміна для загального користування призвела до вирішення цієї помилки.


Як саме я можу це зробити? У мене виникають проблеми з моїми файлами заголовків TwitterKit
Vinod Sobale

2

Я знаю, що це давнє питання, але у мене було те саме питання, і нічого зверху мені не допомогло. Тож сподіваюся, що моя відповідь комусь буде корисною. У моєму випадку проблема була в налаштуваннях ALWAYS_SEARCH_USER_PATHS. Коли було встановлено НІ проект, побудований і працював нормально. Але наскільки один із стручків вимагав, щоб його було встановлено ТАК, я отримував помилку

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

Після декількох чашок кави та цілодобових досліджень я з’ясував, що згідно з відомими випусками Xcode 7.1 Beta 2 примітки до випуску :

• Якщо ви отримаєте помилку, вказуючи "Включити немодульний заголовок всередині модуля рамки" для рамки, яка раніше була скомпільована, переконайтесь, що для параметра збірки "Завжди шукати шляхи користувача" встановлено значення "Ні". За замовчуванням є "Так" лише зі застарілих причин. (22784786)

Хоча я використовував XCode 7.3, але, здається, ця помилка ще не виправлена.


Це мені допомогло! Мені довелося змінити деякий імпорт після переходу на НІ, але тепер я зміг імпортувати потрібну рамку!
Павло Гуров

2

Переключення налаштувань збірки> Дозволити немодульні включення в рамкові модулі на ТАК! вирішив те саме питання для мене.


2

Я також хотів би додати свій досвід проблеми.

Просто підсумовуючи:

  • @ відповідь навколишнього середовища чудова, і вона усуває більшість проблем.
  • дозволити немодульні заголовки - це ще одне рішення (див. деякі відповіді вище).
  • позначення заголовків рамки як загальнодоступних (лише тих, які ви хочете викрити) та імпортування їх у заголовку парасольки.

Ось два мої доповнення до вищевказаних відповідей:

  • уважно перевіряйте імпорт у вашому проекті на предмет заголовків, які імпортують ваші рамки безпосередньо в них (замість того, щоб використовувати форвардне декларування, якщо це можливо) - недоцільно включати файл заголовка всередині іншого файлу заголовка; іноді це спричиняє проблеми, тому що якщо не зробити належним чином, це може призвести до багаторазового включення одного заголовка та створення проблем з посиланням.
  • ОНОВЛЕННЯ: переконайтеся, що архітектури бібліотеки та цілі, з якими ви хочете пов’язати її, відповідають.
  • і нарешті, зробивши все вищесказане, я все одно натикався на цю помилку. Тож я ще трохи перекопав і виявив (на форумах для розробників яблук, але я втратив посилання :(), що якщо включити заголовки до заголовка парасольки не так <framework/headerName.h>, а лише так "headerName.h", проблема відходить.

Я спробував цю останню, і до цих пір я вже не відчував цієї проблеми, однак я підозрюю, що це рішення справедливе лише в тому випадку, якщо ви застосували деякі основні відповіді (зверніть увагу: вони не всі сумісні між собою, наприклад , модульний підхід і включення немодульного заголовка включає).


1

У мене була така точна проблема, коли я включав власну структуру в проект. Виправлено це, поставивши весь імпорт sqlite3.h у .m файли, не в загальнодоступних .h. Я припускаю, що інші бібліотеки можуть позначити подібні проблеми з Xcode.


1

У мене була специфічна проблема з Facebook 4.02 sdk та FBSDKCoreKit.

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

Потім автоматично створюється копія заголовка на навігаторі проекту вгорі.

Я видалив його з фаз збірки -> заголовка та видалив новий файл і працював чудово.

Як це перезавантажено чи щось таке.


1

У моєму випадку (Xcode 9 beta 6 - Swift 4 - використовуючи Cocoapods) це було вирішено, коли я видалив Podfile.lock та каталог Pods і запустився pod installзнову


1

Цю проблему я отримав після оновлення проекту з swift2 до swift3. Я використовував XCode 8.3.2 для оновлення коду і не міг позбутися помилки "немодульний заголовок всередині модуля фрейму". Коли я відкрив той же проект в іншій версії XCode (версія 9.0.1), помилка не з’явилася.


0

Найчастіше ця помилка викликана обраною відповіддю, але я мав цю помилку один раз випадково під час перетягування файлів фрейму в нову папку проекту. Я натиснув, щоб видалити рамки, але випадково натиснув лише "Видалити посилання" на рамки, а не фактично повністю видалити файли. У цей момент, якщо я відкрив свою папку проекту в Finder, я побачив там файли, як "CoreLocation" та "AudioToolbox". Видалення цих файлів із папки проекту та очищення проекту виправили проблему.


0

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

#import <YandexMobileMetrica/YandexMobileMetrica.h>

0

Я вирішив видалення Modulesпапки з фреймворку.

  • Перейдіть до свого базового місця, яке присутнє в програмі додатків, за допомогою пошуку

  • Перейдіть всередину Test.frameworkпапки (у наведеному вище випадку це буде SOGraphDB.framework) та видалити Modulesпапку.

  • Очистіть і перетворіть додаток, воно вирішить проблему.


-1

У мене виникла проблема із імпортом фреймворку Parse. Єдиний спосіб, який я міг це виправити, - це відмовитись від усіх моїх змін із моєї останньої версії (просто видалення рамки та очищення проекту не вийшло) та додавання Parse знову (після нового завантаження SDK) з іншими необхідними рамками.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.