Schneller Compilerfehler: "Nicht modularer Header im Framework-Modul"

204

Jetzt möchte ich mein ObjC-Framework auf Swift migrieren und habe den folgenden Fehler erhalten:

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

Die Verweise beziehen sich auf eine Header-Datei, die nur ein Protokoll definiert, und ich verwende diese Header-Datei in einigen Klassen, um dieses Protokoll zu verwenden.

Ist anscheinend mit der Modulfunktion verbunden, aber es ist im Moment nicht ganz klar, wie man das Problem behebt. Kennen Sie eine Lösung?

AKTUALISIEREN:

Dies ist ein Swift-Compilerfehler.

UPDATE 2:

Eine schnelle Lösung (aber keine Lösung der Grundursache) besteht darin, die folgende Einstellung auf yes zu setzen: CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES

Stephan
quelle
3
Es scheint, dass es eine neue Build-Einstellung für "CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES" gibt
Stephan
1
Hat jemand dies auf öffentlichen und modularen Includes gesehen? Ich sehe dies bei einem Vanille (Cocoapods) -Projekt: github.com/CocoaPods/CocoaPods/issues/3092 und dropbox.com/s/trhe5vwhzoa9bf5/…
Chris Conover
Hat jemand ein schnelles Skript erstellt, das dies automatisch aktiviert?
Fatuhoku
@ Fatuhoku ja
Funroll
Keine dieser Lösungen hat bei mir funktioniert, es sieht so aus, als wäre es in meinem Fall eine bolts.framework-Kollision. Das Löschen löste das Problem: stackoverflow.com/a/33114309/3324388
Aggressor

Antworten:

316

Ist Ihr Header öffentlich?

Wählen Sie die Header-Datei im Projektexplorer aus. Dann werden Sie im Abschnitt rechts in xcode feststellen, dass sich neben dem Ziel ein Dropdown befindet. Ändern Sie das von "Projekt" in "öffentlich". Das hat bei mir funktioniert.

öffentlicher Header

kgreenek
quelle
Ich akzeptiere diese Antwort, auch wenn sie dieselbe ist, wie ich angegeben habe.
Stephan
Sie können auch in die Erstellungsphase für Header Ihres Frameworks wechseln und schnell sehen, welche Header öffentlich, projektbezogen und privat sind.
Jose Ibanez
Ich dachte nicht, dass diese einfache Aufgabe möglicherweise die Lösung sein könnte, da ich über eine Stunde damit gekämpft hatte, bevor ich hierher zu SO kam. Und siehe da, dies war genau die Lösung und funktionierte sofort.
TMc
1
Und was , wenn ich will diese Header intern sein?
Raphael
2
Dies löst auch mein Problem! In meinem Fall kann mein einziger Pod, der von einem anderen Pod abhängt, ihn aufgrund eines modularen Problems nicht importieren. Also habe ich einige Header als Ziel für einen anderen Pod im öffentlichen Modus erstellt. Und es löst das Problem!
Chen Li Yong
135

Dies ist ein erwartetes Compilerverhalten und das aus einem sehr guten Grund.

Ich denke , dass die Mehrheit der Menschen in diese Probleme laufen verursacht wird , nachdem sie von Schalter Application Targetzu Framework Targetund starten Sie das Hinzufügen C und Objective - C - Header in Rahmen des Umbrella - Header erwartet , dass es ein gleiches Verhalten wie haben Anwendung Bridging - Header , das unterschiedlich verhält. Der Umbrella-Header ist eigentlich für ein gemischtes schnelles obj-c-Framework vorgesehen und dient dazu, die APIs der Außenwelt auszusetzen, die Ihr Framework in Ziel-c oder c hat. Das bedeutet, dass die Header, die wir dort platzieren, im öffentlichen Bereich sein sollten.

Es sollte nicht als Ort verwendet werden, an dem Objective-C / C-Header, die nicht Teil Ihres Frameworks sind, für den schnellen Code Ihres Frameworks verfügbar gemacht werden. Denn in diesem Fall werden diese Header auch als Teil unseres Framework-Moduls der Außenwelt ausgesetzt, was wir oft nicht wollen, da es die Modularität bricht. (Und genau aus diesem Grund ist die Standardeinstellung für nicht modulare Einschlüsse in Framework-Modulen standardmäßig NO. )

Um die Objective-C / C-Bibliothek für Ihren Framework-Swift-Code verfügbar zu machen, sollten Sie ein separates Swift-Modul für diese Bibliothek definieren. Dann kann ein Standard-Swift import YourLegacyLibraryverwendet werden.

Lassen Sie mich dies anhand eines typischen Szenarios demonstrieren: Einbettung libxml2in unser Framework.

1. Sie müssen zuerst eine module.modulemapDatei erstellen , die folgendermaßen aussieht:

Für das OSX-Framework:

module SwiftLibXML2 [system] {
  header "/usr/include/libxml2/libxml/xpath.h"
  export *
}

Für iOS-Framework:

module SwiftLibXML2 [system] {
  header "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk/usr/include/libxml2/libxml/xpath.h"
  export *
}

Alles, was es tut, ist, dass es den Header und alle anderen Header, auf die es verweist, innerhalb des Swift-Moduls einschließt, so dass Swift dann die Swift-Bindungen für diese C-Schnittstellen generieren kann.

2. Erstellen Sie dann in Ihrem xcode-Projektverzeichnis einen Ordner SwiftLibXML2und legen Sie diese module.modulemap dort ab

3. In Build - Einstellungen , fügen Sie $(SDKROOT)/usr/include/libxml2auf Header - Suchpfade

4. In Build - Einstellungen hinzufügen, $(SRCROOT)/SwiftLibXML2um Import - Pfade

5. Unter Project Allgemein Registerkarte hinzufügen , libxml2.tbdum Linked Frameworks und Bibliotheken .

Jetzt importieren Sie dieses Modul bei Bedarf mit:

import SwiftLibXML2

(Wenn Sie sich ein vollständigeres Beispiel für module.map ansehen möchten, würde ich vorschlagen, auf Darwins module.modulemap zu verweisen. Dazu /usr/include/module.modulemapmüssen Xcode-Befehlszeilentools installiert sein. Verweisen Sie auf Missing / usr / include in OS X El Capitan )

Umgebungslicht
quelle
1
Der Dateiname module.mapist veraltet, er sollte in module.modulemap clang.llvm.org/docs/Modules.html#attributes
Hyperbole
Wie geht es import SwiftLibXML2in Objective-C? Vielen Dank!
Itachi
Genauso wie bei allen anderen obj-c-Importen: #import <libxml / xpath.h>, aber stellen Sie sicher, dass Sie die Schritte 3 bis 5 ausgeführt haben.
Umgebungslicht
Wir haben dies getan, aber dann kann das Build-Artefakt nicht zwischen Computern verschoben werden: Das Objective-C (Sub) -Modul ist anscheinend über absolute Pfade verknüpft, was zu Fehlern beim Kompilieren einer App führt, die das von Ihnen gelieferte Framework verwendet.
Raphael
Der Fehler ist höchstwahrscheinlich spezifisch für Ihren Build-Prozess. Dies ist nur eine Moduldefinition, damit llvm-Sprachen, die Module unterstützen, mit anderen zusammenarbeiten können. Ich glaube nicht, dass er Ihre Build-Artefakte von selbst beeinflussen kann. Möge die Community mich korrigieren, wenn ich bin falsch
Umgebungslicht
55

Hier erfahren Sie, wie Sie die Schnellkorrektur automatisch anwenden, damit Sie sie nicht Pods.xcodeprojnach jedem manuell ändern müssen pod install.

Fügen Sie dieses Snippet am Ende Ihrer Poddatei hinzu:

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
quelle
29

Die Lösung für mich bestand darin, auf Ziel-> Build-Einstellungen-> Nicht-modulare Includes in Framework-Modulen zulassen auf YES umzuschalten!

Vlad Burlaciuc
quelle
Arbeitete hier auch mit Cocoapods. Keine Notwendigkeit, die Magie von der anderen Antwort nach der Pod-Installation zu tun
Brainray
3
Ich habe diesen Schritt gemacht. Es hat eine Weile funktioniert. Und jetzt funktioniert es nicht. Ich habe auch den Schritt der Pod-Installation aufgenommen. Aber jetzt scheitert es wieder. Was sollte ich sonst noch überprüfen? Ich sehe GoogleMobileAds.Framework nicht als Option zum Ändern von Headern in "Öffentlich".
Michael Rowe
Das hat bei mir nicht funktioniert. Immer noch den Fehler mit Parse. Xcode 7.3.1
C0D3
Ich musste XCode neu starten, nachdem ich diese Änderung vorgenommen hatte, damit es funktionierte.
John Fowler
1
Welche Auswirkungen hat die Änderung dieser Einstellung?
Nr. 5
15

Ich glaube, ich habe das umgangen. Ich habe einen Modellcode, der sqlite3 in einem Framework verwendet. In meinem Fall war der Schuldige <sqlite3.h>.

Das Problem war, dass ich in meinem Module / Module.h-Header einen öffentlichen Header importierte, der <sqlite3.h> importierte. Die Lösung bestand darin, alle sqlite3_xxx-Typen auszublenden und sicherzustellen, dass sie in keiner öffentlichen .h-Datei sichtbar sind. Alle direkten Verweise auf sqlite3 wurden privat oder projektsichtbar gemacht. Zum Beispiel hatte ich einen öffentlichen Singleton, an dem einige sqlite3_stmt-Zeiger hingen. Ich habe diese in eine separate Klasse verschoben, die jetzt nur eine Vorwärtsdeklaration in diesem öffentlichen Header ist. Jetzt kann ich bauen.

Die Einstellung CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES hat übrigens nicht funktioniert. Ich habe versucht, es sowohl im Framework als auch im abhängigen Projekt festzulegen. Diese Problemumgehung war notwendig, obwohl ich nicht sicher bin, warum.

Jimmy Dee
quelle
Das hat total geholfen! In meinem Fall war es Erreichbarkeit.
Daniel Brim
4
Ich bin mir ziemlich sicher, dass dies die Lösung für mein Problem ist, wenn ich versuche, SSZipArchive in mein Framework-Modul aufzunehmen. Der öffentliche Header importiert <zlib.h> und gibt den gleichen Fehler aus. Können Sie Ihren Quellcode irgendwo veröffentlichen, weil ich Schwierigkeiten habe, ihn zum Laufen zu bringen, da ich nur einen Teil Ihrer Antwort verstehe. Danke!
Bruce
15

In Swift :

1. Ändern Sie die Build-Einstellungen Ihres Xcode-Projekts und Ihrer Ziele wie folgt:

Nicht modulare Einschlüsse in Framework-Modulen zulassen: Nein

Bitcode aktivieren: Ja

2. Verwenden Sie die aktuellste Version für GoogleMaps iOS SDK (verwenden Sie CocoaPods, um sie zu erhalten):

GoogleMaps (1.10.4)

3. Kommentieren Sie den problematischen Import:

//import GoogleMaps

4. Erstellen oder ändern Sie Ihre Bridging-Header-Datei und fügen Sie den problematischen Import hinzu:

[Ihr Xcode-Projektname] -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. Bereinigen Sie Ihr Xcode-Projekt und erstellen Sie es neu.

König-Zauberer
quelle
1
Das hilft sehr! Funktioniert auch hervorragend mit dem GoogleMobilAds-Framework (mit Cocoapods)
bluenowhere
Weitere Informationen zum Erstellen der Überschriften-Datei finden Sie unter: stackoverflow.com/a/51227304/529663
lenooh
6

Diese Antwort ist veraltet.

Beim Importieren von Frameworks müssen Sie alle Header-Dateien importieren , die Abhängigkeiten mit dem Root-Header teilen. Der einfachste Weg, um sicherzustellen, dass dies immer funktioniert, besteht darin, alle Header im Ordner "Headers" des Frameworks in Ihren öffentlichen Headerpfad zu importieren.

Geben Sie hier die Bildbeschreibung ein

Der Swift-Compiler verwendet diese Informationen, um eine Karte mit nicht entstellten Symbolen zusammen mit den zugehörigen Typinformationen zu generieren.

SEO
quelle
Dies scheint den Zweck der Framework-Dateien zu vereiteln, aber es hat bei mir funktioniert. Chartboost und RevMob haben kürzlich damit begonnen, Framework-Dateien anstelle von nur Bibliotheken zu verwenden. Das Kopieren aller Elemente aus ihren Headern in meine App-Header behebt das Problem.
Jason Short
Ist das die einzige Lösung? Ich habe 6 Frameworks und jedes Framework hat ungefähr 20 Header. Es schafft ein Chaos. Irgendeine Alternative?
Vivin
1
Mehr als wahrscheinlich. Dies ist wahrscheinlich nicht mehr relevant, da es sich um eine Problemumgehung in einem Xcode-Fehler handelte.
SEO
6

Tu es nicht

#import "MyOtherFramework.h"

Machen

#import <MyOtherFramework/MyOtherFramework.h>
hfossli
quelle
3

Die Header-Datei wurde dem Ziel zugewiesen, aber nur als sichtbares Projekt markiert. Nur eine Änderung der öffentlichen Datei führte zur Behebung dieses Fehlers.

Stephan
quelle
Wie genau kann ich das machen? Ich habe Probleme mit meinen TwitterKit-Header-Dateien
Vinod Sobale
2

Ich weiß, dass dies eine alte Frage ist, aber ich hatte das gleiche Problem und nichts von oben hat mir geholfen. Ich hoffe, meine Antwort ist für jemanden hilfreich. In meinem Fall lag das Problem in der Einstellung ALWAYS_SEARCH_USER_PATHS. Als es auf KEIN Projekt gesetzt war, wurde es gebaut und funktionierte in Ordnung. Aber soweit einer der Pods die Einstellung auf JA erforderte, erhielt ich einen Fehler

Aufnahme eines nicht modularen Headers in das Framework-Modul

Nach ein paar Tassen Kaffee und den ganzen Tag Recherche fand ich heraus, dass nach bekannten Problemen von Xcode 7.1 Beta 2 Versionshinweise :

• Wenn für ein zuvor kompiliertes Framework die Fehlermeldung "Nicht modularen Header in Framework-Modul einschließen" angezeigt wird, stellen Sie sicher, dass die Build-Einstellung "Immer Benutzerpfade suchen" auf "Nein" gesetzt ist. Der Standardwert ist "Ja" nur aus älteren Gründen. (22784786)

Ich habe zwar XCode 7.3 verwendet, aber anscheinend wurde dieser Fehler noch nicht behoben.

iyuna
quelle
Das hat mir geholfen! Ich musste einige Importe ändern, nachdem ich auf NO gewechselt hatte, aber jetzt konnte ich mein benötigtes Framework importieren!
Pavel Gurov
2

Ändern der Build-Einstellungen> Nicht modulare Includes in Framework-Modulen auf YES zulassen ! löste das gleiche Problem für mich.

Mohamed TAIEB
quelle
2

Ich möchte auch meine Erfahrungen mit dem Problem hinzufügen.

Nur um es zusammenzufassen:

  • Die Antwort von @ ambientlight ist großartig und behebt die meisten Probleme.
  • Das Zulassen nicht modularer Header ist eine weitere Lösung (siehe einige der obigen Antworten).
  • Markieren Sie die Header des Frameworks als öffentlich (nur diejenigen, die Sie verfügbar machen möchten) und importieren Sie sie in den Umbrella-Header.

Hier sind meine 2 Ergänzungen zu den obigen Antworten:

  • Überprüfen Sie die Importe in Ihrem Projekt sorgfältig auf Header, die Ihre Frameworks direkt in sie importieren (anstatt nach Möglichkeit die Vorwärtsdeklaration zu verwenden). Es wird nicht empfohlen, eine Header-Datei in eine andere Header-Datei aufzunehmen. Dies führt manchmal zu Problemen, da dies bei nicht ordnungsgemäßer Ausführung dazu führen kann, dass ein Header mehrfach eingeschlossen wird und Linkerprobleme auftreten.
  • UPDATE: Stellen Sie sicher, dass die Architekturen der Bibliothek und die des Ziels, mit dem Sie sie verknüpfen möchten, übereinstimmen.
  • und schließlich, nachdem ich all das oben Genannte getan hatte, stieß ich immer noch auf diesen Fehler. Also habe ich ein bisschen mehr gegraben und festgestellt (in den Apple-Entwicklerforen, aber ich habe den Link verloren :(), dass das Problem verschwindet, wenn Sie die Header nicht so in den Umbrella-Header aufnehmen <framework/headerName.h>, sondern nur so "headerName.h".

Ich habe das letzte Mal versucht, und bis jetzt habe ich dieses Problem nicht mehr erlebt. Ich vermute jedoch, dass diese Lösung nur gültig ist, wenn Sie einige der wichtigsten Antworten angewendet haben (Hinweis: Sie sind beispielsweise nicht alle miteinander kompatibel , der Modulansatz und das Zulassen von nicht modularen Headern beinhaltet).

Georgi Boyadzhiev
quelle
1

Ich hatte genau dieses Problem, als ich mein eigenes Framework in ein Projekt einbezog. Es wurde behoben, indem alle Importe von sqlite3.h in .m-Dateien abgelegt wurden, die nicht in öffentlichen .h-Dateien enthalten waren. Ich gehe davon aus, dass andere Bibliotheken ähnliche Probleme mit Xcode melden.

Rob Sanders
quelle
1

Ich hatte das spezielle Problem mit Facebook 4.02 SDK und FBSDKCoreKit.

Ich habe alle Schritte ausgeführt, aber immer noch Fehler bezüglich nicht modularer Header. Ich ziehe und lasse nur den spezifischen Header aus dem Framework, um Phasen-> Header-Abschnitt zu erstellen.

Anschließend wurde automatisch eine Kopie der Kopfzeile im Projektnavigator oben erstellt.

Ich habe es aus den Build-Phasen -> Header entfernt und die neue Datei gelöscht und gut funktioniert.

Wie es zurückgesetzt oder so.

Haris
quelle
1

In meinem Fall (Xcode 9 Beta 6 - Swift 4 - mit Cocoapods) wurde dies behoben, als ich Podfile.lock und das Pods- Verzeichnis löschte und pod installerneut ausführte

m_katsifarakis
quelle
1

Ich habe dieses Problem nach dem Aktualisieren eines Projekts von swift2 auf swift3. Ich habe XCode 8.3.2 verwendet, um den Code zu aktualisieren, und konnte den Fehler "Nicht modularer Header im Framework-Modul" nicht beseitigen. Als ich dasselbe Projekt in einer anderen Version von XCode (Version 9.0.1) geöffnet habe, ist der Fehler nicht aufgetreten.

DevB2F
quelle
0

Am häufigsten wird dieser Fehler durch die gewählte Antwort verursacht. Dieser Fehler wurde jedoch versehentlich einmal beim Ziehen von Framework-Dateien in meinen neuen Projektordner angezeigt. Ich habe geklickt, um die Frameworks zu löschen, aber versehentlich gedrückt, um nur den Verweis auf die Frameworks zu entfernen, anstatt die Dateien tatsächlich vollständig zu löschen. Wenn ich zu diesem Zeitpunkt meinen Projektordner im Finder öffnete, sah ich dort Dateien wie 'CoreLocation' und 'AudioToolbox'. Das Löschen dieser Dateien aus dem Projektordner und das Bereinigen des Projekts haben das Problem behoben.

ColossalChris
quelle
0

Nachdem Sie das Importieren nicht modularer Includes zugelassen haben, können Sie versuchen, dieses Modul mithilfe des Objective-C Bridging-Headers zu importieren:

#import <YandexMobileMetrica/YandexMobileMetrica.h>
Yuri Korshev
quelle
0

Ich habe es gelöst, indem ich den ModulesOrdner aus dem Framework entfernt habe.

  • Navigieren Sie mit dem Finder zu Ihrem Framework-Speicherort, der im App-Projekt vorhanden ist

  • Gehen Sie in den Test.frameworkOrdner (im obigen Fall SOGraphDB.framework) und löschen Sie den ModulesOrdner.

  • Bereinigen und neu erstellen Die App wird das Problem lösen.

Vittal Pai
quelle
-1

Ich hatte dieses Problem beim Importieren des Parse-Frameworks. Die einzige Möglichkeit, dies zu beheben, bestand darin, alle meine Änderungen seit meinem letzten Commit zu verwerfen (das Löschen des Frameworks und das Bereinigen des Projekts funktionierten nicht) und Parse (nach einem erneuten Download des SDK) mit den anderen erforderlichen Frameworks erneut hinzuzufügen.

amurray4
quelle