Errore del compilatore Swift: "intestazione non modulare all'interno del modulo framework"


204

Ora vorrei migrare il mio framework ObjC su Swift e ho ricevuto il seguente errore:

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

Il riferimento è a un file di intestazione che definisce semplicemente un protocollo e io uso questo file di intestazione in alcune classi per usare questo protocollo.

Sembra correlato alla funzionalità del modulo ma al momento non è del tutto chiaro come risolvere, conosci una soluzione?

AGGIORNARE:

Questo è un errore del compilatore Swift.

AGGIORNAMENTO 2:

Una soluzione rapida (ma non risolvendo la causa principale) è di impostare su Sì le seguenti impostazioni: CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES


3
Sembra che ci sia una nuova impostazione di build per "CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES"
Stephan

1
Qualcuno l'ha visto su include che sono pubblici e modulari? Vedo questo con un progetto di vaniglia (cocoapods): github.com/CocoaPods/CocoaPods/issues/3092 e dropbox.com/s/trhe5vwhzoa9bf5/…
Chris Conover

Qualcuno ha creato uno script rapido che lo abilita automaticamente?
Fatuhoku,

@fatuhoku yeah
funroll

Nessuna di queste soluzioni ha funzionato per me, sembra che nel mio caso sia stata una collisione con bulloni. L'eliminazione ha risolto il problema: stackoverflow.com/a/33114309/3324388
Aggressor

Risposte:


316

La tua intestazione è pubblica?

Seleziona il file di intestazione in Esplora progetti. Quindi nella sezione a destra in xcode, noterai che c'è un menu a discesa vicino al bersaglio. Cambia da "progetto" a "pubblico". Questo ha funzionato per me.

intestazione pubblica


Accetto questa risposta anche se è la stessa che ho dichiarato.
Stephan,

Puoi anche andare alla fase di costruzione Headers del tuo framework e vedere rapidamente quali header sono Public, Project e Private.
Jose Ibanez,

Non pensavo che questo semplice compito potesse essere la soluzione dato che avevo combattuto con questo per oltre un'ora prima di venire qui a SO. Ecco, questa era ESATTAMENTE la soluzione e ha funzionato immediatamente.
TMc,

1
E se volessi che queste intestazioni fossero interne?
Raffaello

2
Questo risolve anche il mio problema! Nel mio caso, il mio unico pod che dipende da un altro pod non può importarlo a causa di un problema modulare. Quindi ho creato alcune intestazioni incluse come destinazione per un altro pod, usando la modalità pubblica. E risolve il problema!
Chen Li Yong,

135

Questo è un comportamento previsto del compilatore e per un'ottima ragione.

Penso che la maggior parte delle persone in esecuzione in questo questioni è causata dopo si passa da Application Targeta Framework Targete iniziare l'aggiunta di C e le intestazioni Obiettivo C in del framework intestazione ombrello in attesa di avere un stesso comportamento di Bridging colpo di testa di applicazione , che si comporta in modo diverso. L'header ombrello è in realtà designato per un framework misto rapido, obj-c e il suo scopo è quello di esporre le API al mondo esterno che il tuo framework ha in object-c o c. Ciò significa che le intestazioni che inseriamo dovrebbero essere di dominio pubblico.

Non deve essere utilizzato come luogo che espone le intestazioni Objective-C / C che non fanno parte del framework al codice rapido del framework. Perché in quel caso queste intestazioni saranno anche esposte come parte del nostro modulo quadro al mondo esterno, che spesso non è ciò che vogliamo fare poiché rompe la modularità. (Ed è esattamente questo il motivo per cui le impostazioni predefinite per le inclusioni non modulari nei moduli Framework sono NO )

Al fine di esporre la libreria Objective-C / C al codice rapido del framework, è necessario definire un modulo rapido separato per tale libreria. Quindi è import YourLegacyLibrarypossibile utilizzare uno swift standard .

Consentitemi di dimostrarlo in uno scenario tipico: l'integrazione libxml2nel nostro framework.

1. È innanzitutto necessario creare un module.modulemapfile che apparirebbe in questo modo:

Per il framework OSX:

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

Per framework iOS:

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

Tutto ciò che fa è che avvolge l'intestazione e tutte le altre intestazioni a cui fa riferimento all'interno del modulo swift, in modo che swift sarà in grado di generare i collegamenti rapidi per queste interfacce C.

2. Quindi, nella directory del progetto xcode, creare una cartella SwiftLibXML2e inserire questo modulo.modulemap lì

3. In Impostazioni build , aggiungi $(SDKROOT)/usr/include/libxml2a Percorsi di ricerca intestazione

4. In Impostazioni build , aggiungi $(SRCROOT)/SwiftLibXML2a Importa percorsi

5. Nella scheda Generale del progetto , aggiungi libxml2.tbda Strutture e librerie collegate .

Ora importa questo modulo dove necessario con:

import SwiftLibXML2

(se vuoi dare un'occhiata a un esempio di module.map più completo, suggerirei di fare riferimento a module.modulemap di Darwin su /usr/include/module.modulemap, avresti bisogno di avere gli strumenti da riga di comando Xcode installati per andare lì, riferimento Missing / usr / include in OS X El Capitan )


1
Il nome del file module.mapè deprecato, si dovrebbe essere rinominato module.modulemap clang.llvm.org/docs/Modules.html#attributes
Iperbole

Come import SwiftLibXML2in Objective-C? Grazie!
Itachi,

allo stesso modo di qualsiasi altra importazione obj-c: #import <libxml / xpath.h> ma assicurati di aver eseguito i passaggi 3-5.
ambientlight il

Lo abbiamo fatto, ma quindi l'artefatto di costruzione non può essere spostato tra le macchine: il modulo Objective-C (sub) è apparentemente collegato usando percorsi assoluti, causando errori durante la compilazione, diciamo, di un'app che utilizza il framework che hai spedito.
Raffaello,

molto probabilmente l'errore è specifico del tuo processo di compilazione, questa è solo una definizione del modulo in modo che i linguaggi llvm che supportano i moduli possano interagire con gli altri, non penso che possa influenzare da solo i tuoi artefatti di costruzione, che la comunità possa correggermi se io Sono sbagliato
Ambientlight

55

Ecco come applicare automaticamente la correzione rapida in modo da non dover cambiare Pods.xcodeprojmanualmente dopo ciascuna pod install.

Aggiungi questo frammento alla fine del tuo 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

La soluzione per me era quella di andare su target-> costruire impostazioni-> Consenti inclusioni non modulari nei moduli Framework passare a SÌ!


Anche lavorato con Cocoapods qui. Non è necessario eseguire la magia dall'altra risposta dopo l'installazione del pod
brainray

3
Ho fatto questo passaggio .. ha funzionato per un po '.. e ora non funziona ... Ho incluso anche il passaggio di installazione del pod. Ma ora sta fallendo di nuovo. Qualcos'altro che dovrei controllare? Non vedo GoogleMobileAds.Framework come un'opzione per cambiare le intestazioni in Pubblico.
Michael Rowe,

Questo non ha funzionato per me. Ottengo ancora l'errore con Parse. Xcode 7.3.1
C0D3

Ho dovuto riavviare XCode dopo aver apportato questa modifica per farlo funzionare.
John Fowler,

1
Qual è l'impatto della modifica di questa impostazione?
nr5

15

Penso di averlo aggirato. Ho del codice modello che utilizza sqlite3 in un framework. Nel mio caso, il colpevole era <sqlite3.h>.

Il problema era che nella mia intestazione Module / Module.h, ho importato un'intestazione pubblica che importava <sqlite3.h>. La soluzione era nascondere tutti i tipi sqlite3_xxx e assicurarsi che non fossero visibili in nessun pubblico .h. Tutti i riferimenti diretti a sqlite3 sono stati resi privati ​​o visibilità del progetto. Ad esempio, avevo un singleton pubblico con alcuni puntatori sqlite3_stmt sospesi. Ho spostato quelli in una classe separata che ora è solo una dichiarazione in avanti in quell'intestazione pubblica. Ora posso costruire.

Per inciso, l'impostazione CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES non ha funzionato. Ho provato a impostarlo sia nel framework che nel progetto dipendente. Questa soluzione alternativa era necessaria, anche se non sono sicuro del perché.


Questo ha aiutato totalmente! Nel mio caso, è stato Raggiungibilità.
Daniel Brim,

4
Sono abbastanza sicuro che questa sia la soluzione al mio problema quando provo a includere SSZipArchive nel mio modulo framework. L'intestazione pubblica sta imporing <zlib.h> e sta dando lo stesso errore. Puoi pubblicare il tuo codice sorgente da qualche parte perché sto lottando per farlo funzionare poiché capisco solo parte della tua risposta .. grazie!
Bruce,

15

In Swift :

1. Modifica il tuo progetto Xcode e le impostazioni di costruzione dei target come indicato di seguito:

Consenti inclusioni non modulari nei moduli Framework: No

Abilita Bitcode: Sì

2. Usa l'ultima versione disponibile disponibile per Google SDK iOS SDK (usa CocoaPods per ottenerlo):

GoogleMaps (1.10.4)

3. Commenta l'importazione problematica:

//import GoogleMaps

4. Crea o modifica il file di intestazione ponte, aggiungendo l'importazione problematica:

[Nome del tuo progetto 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. Pulisci e ricostruisci il tuo progetto Xcode.


1
Questo aiuta molto! Funziona alla grande anche con il framework GoogleMobilAds (con Cocoapods)
bluenowhere

Per informazioni più dettagliate su come creare il file di intestazione, vedi: stackoverflow.com/a/51227304/529663
lenooh

6

Questa risposta è obsoleta.

Quando si importano framework, è necessario importare tutti i file di intestazione che condividono dipendenze con l'intestazione di root. Il modo più semplice per assicurarsi che funzioni sempre è importare tutte le intestazioni nella cartella "Intestazioni" del framework nel percorso delle intestazioni pubbliche.

inserisci qui la descrizione dell'immagine

Il compilatore Swift utilizza queste informazioni per generare una mappa di simboli non alterati insieme alle informazioni sui tipi associati.


Questo sembra vanificare lo scopo di avere i file Framework, ma ha funzionato per me. Chartboost e RevMob hanno recentemente iniziato a utilizzare i file Framework anziché solo libs. La copia di tutto dalle loro intestazioni alle intestazioni delle mie app risolve il problema.
Jason Short,

Questa è l'unica soluzione? Ho 6 framework e ogni framework ha circa 20 header. Crea un casino. Qualche supplente?
vivin,

1
Più che probabilmente. Questo probabilmente non è più rilevante in quanto era una soluzione alternativa in un bug Xcode.
seo,

6

non

#import "MyOtherFramework.h"

Fare

#import <MyOtherFramework/MyOtherFramework.h>

3

Il file di intestazione è stato assegnato alla destinazione ma è stato contrassegnato solo come progetto visibile, solo una modifica al pubblico ha portato alla risoluzione di questo errore.


Come posso esattamente farlo? Sto riscontrando problemi con i miei file di intestazione TwitterKit
Vinod Sobale,

2

So che questa è una vecchia domanda, ma ho avuto lo stesso problema e nulla dall'alto mi ha aiutato. Quindi spero che la mia risposta sia utile per qualcuno. Nel mio caso il problema era nelle impostazioni ALWAYS_SEARCH_USER_PATHS. Quando è stato impostato su NO, il progetto è stato creato e funzionava bene. Ma per quanto uno dei pod richiedesse che fosse impostato su SÌ stavo ricevendo un errore

Include intestazione non modulare all'interno del modulo framework

Dopo un paio di tazze di caffè e ricerche per tutto il giorno, ho scoperto che, in base ai problemi noti delle note di rilascio di Xcode 7.1 Beta 2 :

• Se viene visualizzato un errore che indica "Includi intestazione non modulare all'interno del modulo framework" per un framework precedentemente compilato, assicurarsi che l'impostazione di build "Cerca sempre percorsi utente" sia impostata su "No". L'impostazione predefinita è "Sì" solo per motivi legacy. (22784786)

Stavo usando XCode 7.3, ma sembra che questo errore non sia stato ancora corretto.


Questo è ciò che mi ha aiutato! Ho dovuto cambiare alcune importazioni dopo essere passato a NO, ma ora sono stato in grado di importare il mio framework necessario!
Pavel Gurov

2

Commutazione delle impostazioni di costruzione> Consenti inclusioni non modulari nei moduli quadro su SÌ! risolto lo stesso problema per me.


2

Vorrei aggiungere anche la mia esperienza con il problema.

Per riassumere:

  • La risposta di @ ambientlight è ottima e risolve la maggior parte dei problemi.
  • consentire intestazioni non modulari è un'altra soluzione (vedere alcune delle risposte sopra).
  • contrassegnare le intestazioni del framework come pubbliche (solo quelle che si desidera esporre) e importarle nell'intestazione dell'ombrello.

Ecco le mie 2 aggiunte alle risposte sopra:

  • controlla attentamente le importazioni nel tuo progetto per le intestazioni che importano i tuoi framework direttamente in loro (invece di usare la dichiarazione forward, se possibile) - non è una buona pratica includere un file header in un altro file header; a volte ciò causa problemi, perché se non eseguito correttamente ciò può comportare l'inclusione multipla di un'intestazione e creare problemi di linker.
  • AGGIORNAMENTO: assicurarsi che le architetture della libreria e quella della destinazione a cui si desidera collegarla corrispondano.
  • e infine, dopo aver fatto tutto quanto sopra, continuavo ancora a imbattermi in quell'errore. Quindi ho scavato un po 'di più e ho scoperto (nei forum degli sviluppatori di Apple, ma ho perso il link :() che se includi le intestazioni nell'intestazione dell'ombrello non in questo modo <framework/headerName.h>, ma solo in questo modo "headerName.h", il problema scompare.

Ho provato quest'ultimo, e finora non ho più riscontrato questo problema, tuttavia sospetto che questa soluzione sia valida solo se hai applicato alcune delle risposte principali (nota: non sono tutte compatibili tra loro, ad esempio , include l'approccio del modulo e la concessione di header non modulari).


1

Ho avuto questo esatto problema quando ho incluso la mia struttura in un progetto. Risolto il problema mettendo tutte le importazioni di sqlite3.h in file .m non in quelli .h pubblici. Suppongo che altre librerie possano segnalare problemi simili con Xcode.


1

Ho avuto il problema specifico con Facebook 4.02 SDK e FBSDKCoreKit.

Ho fatto tutti i passaggi ma ho ancora errori sull'intestazione non modulare. trascino e rilasciamo solo l'intestazione specifica dal framework per creare fasi-> sezione intestazione.

Quindi ha creato automaticamente una copia dell'intestazione sul navigatore del progetto in alto.

L'ho rimosso dalle fasi di compilazione -> intestazione ed eliminato il nuovo file e ha funzionato bene.

Come se fosse ripristinato o qualcosa del genere.


1

Nel mio caso (Xcode 9 beta 6 - Swift 4 - usando Cocoapods) questo è stato risolto quando ho eliminato Podfile.lock e la directory Pods ed eseguito di pod installnuovo


1

Ho riscontrato questo problema dopo aver aggiornato un progetto da swift2 a swift3. Stavo usando XCode 8.3.2 per aggiornare il codice e non riuscivo a liberarmi dell'errore "intestazione non modulare all'interno del modulo framework". Quando ho aperto lo stesso progetto in un'altra versione di XCode (versione 9.0.1) l'errore non è apparso.


0

Più comunemente questo errore è causato dalla risposta scelta, eppure ho avuto questo errore apparire una volta per caso quando trascinavo i file del framework nella mia nuova cartella del progetto. Ho fatto clic per eliminare i framework, ma ho premuto accidentalmente solo "Rimuovi riferimento" ai framework anziché eliminare completamente i file. A questo punto, se aprissi la cartella del mio progetto nel Finder, vedevo lì file come "CoreLocation" e "AudioToolbox". L'eliminazione di questi file dalla cartella del progetto e la pulizia del progetto hanno risolto il problema.


0

Dopo aver permesso di importare inclusioni non modulari, puoi provare a importare quel modulo usando l'intestazione Bridging di Objective-C:

#import <YandexMobileMetrica/YandexMobileMetrica.h>

0

L'ho risolto rimuovendo la Modulescartella dal framework.

  • Passare alla posizione del framework che è presente nel progetto app utilizzando finder

  • Vai all'interno della Test.frameworkcartella (nel caso precedente sarà SOGraphDB.framework) & Elimina Modulescartella.

  • Clean and Re Build the app, risolverà il problema.


-1

Ho avuto questo problema durante l'importazione del framework Parse. L'unico modo per risolverlo è stato di scartare tutte le mie modifiche dal mio ultimo commit (semplicemente eliminando il framework e ripulendo il progetto non funzionava) e aggiungendo di nuovo Parse (dopo un nuovo download dell'SDK) con gli altri framework richiesti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.