Xcode 4 non è in grado di individuare i file di intestazione pubblici dalla dipendenza dalla libreria statica

Titoli alternativi per aiutare la ricerca

  • Xcode non trova l’intestazione
  • .H mancante in Xcode
  • Xcode .h file non trovato
  • file di rilascio lessicale o preprocessore non trovato

Sto lavorando a un progetto di applicazione iOS che proviene da Xcode 3. Ora mi sono spostato su Xcode 4 il mio progetto crea un certo numero di librerie statiche.

Queste librerie statiche dichiarano anche intestazioni pubbliche e quelle intestazioni vengono utilizzate dal codice dell’applicazione. In Xcode 3.x le intestazioni sono state copiate (come fase di costruzione) nella public headers directory , quindi nel progetto di applicazione la public headers directory stata aggiunta headers search list .

Sotto Xcode 4 la directory di compilazione viene spostata in ~/Library/Developer/Xcode/DerivedData/my-project .

Il problema è come faccio a fare riferimento a questa nuova posizione nelle impostazioni di ricerca delle intestazioni? Sembra che:

  • public headers directory è relativa alla directory DerivedData , ma
  • headers search directory di headers search è relativa a qualcos’altro (probabilmente la posizione del progetto)

Come dovrei impostare un target di libreria statico per lo sviluppo iOS in Xcode 4 che garantisca che i file di intestazione siano resi disponibili ai client che usano la libreria statica quando provano a compilare come una dipendenza?

Ognuna delle soluzioni che ho visto a questo problema è sembrata inelegante (copiando le intestazioni nel progetto dell’applicazione) o eccessivamente semplificata al punto che funzionano solo in situazioni banali.

La risposta breve

Aggiungi il seguente percorso ai percorsi di ricerca dell’intestazione dell’utente

“$ (BUILD_ROOT) /../ IntermediateBuildFilesPath / UninstalledProducts”

Perché funziona?

In primo luogo, dobbiamo capire il problema. In circostanze normali, vale a dire quando si esegue, test, profilo o analisi, Xcode crea il progetto e inserisce l’output nella directory Build / Products / Configuration / Products, disponibile tramite la macro $ BUILT_PRODUCTS_DIR .

La maggior parte delle guide relative alle librerie statiche consiglia di impostare il percorso della cartella degli header pubblici su $ TARGET_NAME , il che significa che il file lib diventa $ BUILT_PRODUCTS_DIR /libTargetName.a e le intestazioni vengono inserite in $ BUILT_PRODUCTS_DIR / TargetName. Finché l’app include $ BUILT_PRODUCTS_DIR nei suoi percorsi di ricerca, le importazioni funzioneranno nelle 4 situazioni sopra riportate. Tuttavia, questo non funzionerà quando si tenta di archiviare.

L’archiviazione funziona in modo leggermente diverso

Quando si archivia un progetto, Xcode utilizza una cartella diversa denominata ArchiveIntermediates. All’interno di quella cartella troverai / YourAppName / BuildProductsPath / Release-iphoneos /. Questa è la cartella a cui $ BUILT_PRODUCTS_DIR punta quando si fa un archivio. Se guardi qui, vedrai che c’è un link simbolico al tuo file di libreria statica costruito ma manca la cartella con le intestazioni.

Per trovare le intestazioni (e il file lib) devi andare a IntermediateBuildFilesPath / UninstalledProducts /. Ricordi quando ti è stato detto di impostare Skip Install su YES per le librerie statiche? Bene, questo è l’effetto che l’impostazione ha quando si crea un archivio.

Nota a margine: se non lo imposti per saltare l’installazione, le intestazioni verranno inserite in un’altra posizione e il file lib verrà copiato nel tuo archivio, impedendoti di esportare un file .ipa che puoi inviare all’App Store .

Dopo molte ricerche, non sono riuscito a trovare alcuna macro che corrisponda esattamente alla cartella UninstalledProducts, quindi la necessità di build il percorso con “$ (BUILD_ROOT) /../ IntermediateBuildFilesPath / UninstalledProducts”

Sommario

Per la tua libreria statica, assicurati di saltare l’installazione e che le intestazioni pubbliche siano inserite in $ TARGET_NAME.

Per la tua app, imposta i percorsi di ricerca dell’intestazione dell’utente su “$ (BUILT_PRODUCTS_DIR)”, che funziona bene per le build regolari, e “$ (BUILD_ROOT) /../ IntermediateBuildFilesPath / UninstalledProducts”, che funziona per le build di archivio.

Mi sono imbattuto in questo stesso problema quando sviluppavo la mia libreria statica e sebbene la risposta di Colin fosse molto utile, ho dovuto modificarla un po ‘per lavorare in modo coerente e semplice quando eseguivo e archivavo progetti sotto Xcode 4 usando un Workspace.

La differenza nel mio metodo è che puoi utilizzare un singolo percorso di intestazione utente per tutte le configurazioni di build.

Il mio metodo è il seguente:

Crea uno spazio di lavoro

  1. Sotto Xcode 4, vai su File, Nuovo, Spazio di lavoro.
  2. Dal Finder puoi quindi trascinare i progetti .xcodeproj sia per la libreria statica che vuoi utilizzare, sia per la nuova app che stai costruendo che utilizza la libreria. Vedi Apple Docs per maggiori informazioni su come configurare gli spazi di lavoro: https://developer.apple.com/library/content/featuredarticles/XcodeConcepts/Concept-Workspace.html

Impostazioni del progetto Libreria statica

  1. Assicurati che tutte le intestazioni della libreria statica siano impostate su “Pubblico”. Questo viene fatto sotto le impostazioni per la destinazione della libreria statica> Fasi di creazione. Nella fase “Copia intestazioni”, assicurati che tutte le intestazioni siano nella sezione “Pubblico”.
  2. Successivamente vai su Impostazioni di costruzione, trova “Percorso cartella intestazioni pubbliche” e digita un percorso per la tua libreria. Ho scelto di usare questo:

include / LibraryName

Ho adottato questo da utilizzare con RestKit e ho trovato che funziona meglio con tutte le mie librerie statiche. Quello che fa è dire a Xcode di copiare tutte le intestazioni che abbiamo spostato nella sezione delle intestazioni “Pubblico” nel passaggio 1 alla cartella specificata qui che risiede nella cartella Dati derivati ​​durante la costruzione. Come con RestKit, mi piace usare una singola cartella “include” per contenere ogni libreria statica che sto usando in un progetto.

Inoltre, non mi piace usare i macro qui perché ci permetterà di utilizzare un singolo percorso di ricerca dell’intestazione dell’utente in seguito quando configureremo il progetto usando la libreria statica.

  1. Trova “Skip Install” e assicurati che sia impostato su YES.

Impostazioni per il progetto utilizzando la libreria statica

  1. Aggiungi la libreria statica come framework in Fasi di compilazione> Collega binario con librerie e aggiungi il file libLibraryName.a per qualsiasi libreria statica che desideri utilizzare.
  2. Quindi assicurati che il progetto sia impostato per cercare i percorsi di ricerca degli utenti. Questo viene fatto in Impostazioni build> Cerca sempre percorsi utente e assicurati che sia impostato su SÌ.
  3. Nella stessa area trova Percorsi di ricerca intestazione utente e aggiungi:

    “$ (PROJECT_TEMP_DIR) /../ UninstalledProducts / includono”

Questo dice a Xcode di cercare le librerie statiche all’interno della cartella di creazione intermedia creata da Xcode durante il processo di compilazione. Qui abbiamo la cartella “include” che stiamo usando per le nostre posizioni di librerie statiche che impostiamo nel passaggio 2 per le impostazioni del progetto di libreria statica. Questo è il passo più importante per far sì che Xcode trovi correttamente le tue librerie statiche.

Configura l’area di lavoro

Qui vogliamo configurare lo spazio di lavoro in modo che costruisca la libreria statica quando costruiamo la nostra app. Questo viene fatto modificando lo schema utilizzato per la nostra app.

  1. Assicurati di aver selezionato lo schema che creerà la tua applicazione.
  2. Dal menu a discesa dello schema, selezionare Modifica schema.
  3. Seleziona Costruisci nella parte superiore dell’elenco a sinistra. Aggiungi un nuovo objective premendo il + nel riquadro centrale.
  4. Dovresti vedere la libreria statica mostrare per la libreria che stai cercando di colbind. Scegli la libreria statica iOS.
  5. Fare clic su Esegui e Archivia. Ciò indica allo schema di compilare le librerie per la libreria statica ogni volta che si crea l’app.
  6. Trascina la libreria statica sopra il target dell’applicazione. Questo rende le librerie statiche compilate prima del target dell’applicazione.

Inizia a utilizzare la libreria

Ora, dovresti essere in grado di importare la tua libreria statica usando

 import  

Questo metodo risolve il problema di dover avere percorsi di intestazione utente diversi per configurazioni diverse, quindi non dovresti avere problemi di compilazione per gli archivi.

Perché funziona?

Tutto dipende da questo percorso:

 "$(PROJECT_TEMP_DIR)/../UninstalledProducts/include" 

Poiché configuriamo la nostra libreria statica per utilizzare “Skip Install”, i file compilati vengono spostati nella cartella “UninstalledProjects” all’interno della directory di build temporanea. Il nostro percorso qui si risolve anche nella cartella “include” che abbiamo configurato per la nostra libreria statica e utilizzata per il nostro percorso di ricerca dell’intestazione dell’utente. I due lavorano insieme consentono a Xcode di sapere dove trovare la nostra libreria durante il processo di compilazione. Poiché questa directory di generazione temporanea esiste per entrambe le configurazioni di debug e release, è necessario un solo percorso per Xcode per la ricerca di librerie statiche.

Xcode 4 Project Non riesce a compilare una libreria statica

Domanda correlata: “file di rilascio lessicale o preprocessore non trovato” in Xcode 4

Gli errori potrebbero includere; file di intestazione mancanti, “problema lessicale o preprocessore”

soluzioni:

  1. Verificare che i “percorsi di intestazione dell’utente” siano corretti
  2. Impostare “Cerca sempre percorsi utente” su SÌ
  3. Crea una chiamata di gruppo “Indicizzazione intestazioni” nel tuo progetto e trascina le intestazioni su questo gruppo, NON aggiungere a nessun objective quando richiesto.

Questa è stata una discussione molto utile. Nella ricerca per la mia situazione, ho trovato che Apple ha un documento di 12 pagine datato settembre 2012 intitolato “Uso di librerie statiche in iOS”. Ecco il link pdf: http://developer.apple.com/library/ios/technotes/iOSStaticLibraries/iOSStaticLibraries.pdf

È molto più semplice della maggior parte della discussione su Internet, e con alcune piccole mod per tenere conto di come sono configurate le librerie esterne che sto usando, sta funzionando bene per me. La parte più importante è probabilmente:

Se il tuo target di libreria ha una fase di costruzione “Copie di intestazione”, dovresti eliminarlo; le fasi di costruzione delle intestazioni di copia non funzionano correttamente con i target di libreria statici quando si esegue l’azione “Archivia” in Xcode.

I nuovi target di librerie statiche create con Xcode 4.4 o versioni successive verranno dotati di una fase Copy Files configurata in modo appropriato per le intestazioni, quindi è necessario verificare se ne esiste già una prima di crearne una. In caso contrario, premere “Aggiungi fase di creazione” nella parte inferiore dell’editor di destinazione e scegliere “Aggiungi file di copia”. Divulgare la nuova fase di copia dei file di copia e impostare la destinazione su “Elenco prodotti”. Impostare il sottotracciato da includere / $ {PRODUCT_NAME}. Questo copierà i file in una cartella che prende il nome dalla tua libreria (presa dall’impostazione di build di PRODUCT_NAME), all’interno di una cartella chiamata include, all’interno della directory dei prodotti creati. La cartella include all’interno di una directory di prodotti build si trova nel percorso di ricerca dell’intestazione predefinito per le applicazioni, quindi questa è una posizione appropriata per inserire i file di intestazione.

Sono sicuro che in molte situazioni esistenti l’approccio di Apple potrebbe non essere sufficiente. Inserisco questo articolo qui per tutti coloro che stanno appena iniziando il loro percorso sul percorso del giardino della biblioteca statica: questo potrebbe essere il miglior punto di partenza per casi semplici.

http://developer.apple.com/library/ios/#technotes/iOSStaticLibraries/Articles/creating.html

Documentazione di Apple:

La libreria avrà uno o più file di intestazione che i client di tale libreria devono importare. Per configurare le intestazioni da esportare ai client, selezionare il progetto della libreria per aprire l’editor di progetto, selezionare la destinazione della libreria per aprire l’editor di destinazione e selezionare la scheda Fasi di costruzione. Se il tuo target di libreria ha una fase di costruzione “Copie di intestazione”, dovresti eliminarlo; le fasi di costruzione delle intestazioni di copia non funzionano correttamente con i target di libreria statici quando si esegue l’azione “Archivia” in Xcode.

Dai un’occhiata alla soluzione di Jonah Wlliam (a metà strada) e al modello GitHub (nei commenti) per un approfondimento. http://blog.carbonfive.com/2011/04/04/using-open-source-static-libraries-in-xcode-4/

Aggiungi $ (OBJROOT) / UninstalledProducts / exactPathToHeaders ai percorsi di ricerca dell’intestazione.

Per qualche motivo la casella di controllo ricorsiva non ha funzionato per me e ho dovuto aggiungere il resto del percorso dove si trovano le intestazioni.

Sotto il Log Navigator in Xcode (la scheda a destra del navigatore dei punti di interruzione) puoi vedere la cronologia delle build. Se si seleziona l’errore di compilazione effettivo, è ansible espandere i dettagli per visualizzare il PATH setenv e verificare che il percorso dei file di intestazione sia presente.

Aggiungi il seguente percorso ai tuoi percorsi di ricerca intestazione utente:

 $(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts 

Questo è verificato!

A rischio di mostrare che idiota sono … Ho sofferto di XCode che si è rifiutato di trovare i miei file .h tutto il pomeriggio.

Poi ho capito.

Dato che stavo usando “XCode 4”, avevo “intelligentemente” deciso di mettere tutti i miei progetti in una sottocartella di una cartella chiamata ” progetti XCode 4 “.

Quegli spazi nel nome della cartella hanno incasinato XCode alla grande!

Rinominare questa cartella in ” XCode_4_Projects ” ha portato gioia (e meno parolacce) nella mia vita.

Ricordami di nuovo, che anno è questo?

Forse qualcuno potrebbe dire agli sviluppatori Apple …

Nessuna di queste risposte ha funzionato per me. Ecco cosa ha fatto. Aggiungi esattamente quanto segue (copia e incolla includendo le doppie virgolette) nell’impostazione di creazione dei Percorsi di ricerca intestazione utente :

 "$(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts/include/" 

Notare l’aggiunta della sottodirectory “/ include /” rispetto ad altre risposte. Come altri utenti hanno sottolineato, l’opzione “ricorsiva” non sembra fare nulla, quindi puoi ignorarla.

Il mio progetto è ora in grado di archiviare correttamente quando si importano i file di intestazione della libreria statica nel seguente formato:

 #import "LibraryName/HeaderFile.h" 

Non è necessario abilitare l’impostazione Cerca sempre percorsi utente a meno che non si includano le intestazioni delle librerie statiche con parentesi angolari ( #import ), ma in realtà non si dovrebbe farlo in questo modo se non lo è un’intestazione di sistema / framework.

Nessuna delle risposte sopra ha funzionato per me su Xcode 7, ma mi hanno dato comunque una buona idea. Per i ragazzi che hanno problemi con Xcode 7, ho risolto questo problema aggiungendo quanto segue a Percorsi di ricerca intestazione utente (includi virgolette)

 "$(BUILT_PRODUCTS_DIR)/usr/local/include" 

Modifica la relativa parte URL usr/local/include base a ciò che è presente nell’impostazione “Percorso cartella intestazione pubblica” della libreria statica

Nel mio caso il mio spazio di lavoro aveva un paio di progetti di librerie statiche e uno di loro ha dipendenza, inclusi i file di intestazione con l’altro. Il problema era con l’ordine di costruzione. Nella pagina Modifica schema nella sezione Crea, ho deselezionato l’opzione parallelizza e ho ordinato l’ordine degli obiettivi secondo le dipendenze e risolto dal problema

Questo è un problema correlato che mi ha portato a questa domanda quindi sto aggiungendo la mia soluzione rigorosamente per la documentazione / potrebbe salvare un’altra anima ore di sudorazione

DropboxSDK.h file non trovato

Dopo giorni di tentativi di compilare VES per iOS, mi sono imbattuto in questo problema. DropboxSDK.h era decisamente alla portata delle search headers di search headers ho persino aggiunto al percorso di ricerca delle framework headers , include direttamente il .h e sono andato a tutti i tipi di lunghezze per provare a trovare DropboxSDK.h .

Soluzione

DropboxSDK.framework trascina il file DropboxSDK.framework in Project Navigation Xcode e assicurati che sia selezionato Copy Files if needed . Assicurati anche che il tuo objective sia controllato secondo necessità.

avvertimento

L’impostazione della posizione del framework esplicito nelle build phases non ha funzionato per me. Ho dovuto trascinare il .framework in Xcode e assicurarmi che i file siano stati copiati nel mio progetto.

# mbp2015 # xcode7 # ios9

Esistono vari modi complessi per eseguire questa operazione e in questo thread vengono proposte alcune soluzioni molto intelligenti.

Il problema principale di tutte queste soluzioni è che riduce drasticamente la portabilità della libreria.

  • Ogni volta che devi avviare un nuovo progetto utilizzando la tua libreria e archiviarlo per iTunes, è un inferno di configurazione.
  • Ogni volta che hai bisogno di condividere il tuo progetto con il tuo team o clienti, può rompersi per qualsiasi motivo (contesto, versione Xcode, qualunque cosa, ..)

La mia scelta è stata finalmente quella di utilizzare semplicemente i framework – sempre – come raccomandato da Apple (video WWDC).

È così semplice e fa lo stesso lavoro alla fine!

Un’altra soluzione abbastanza elegante che sembra funzionare è l’utilizzo di Cocoapods privati. Cocoapods fa tutto il lavoro di configurazione, copia dell’intestazione e così via.

Strutture rock!

Ecco cosa ha risolto lo stesso problema per me.

Ho una destinazione app e una destinazione estensione iMessage. Poi ho avuto 2 SDK (i miei), a cui sono indirizzati i collegamenti di App Target.

Il problema era il seguente: il mio target iMessage utilizzava anche i 2 SDK di mine (progetti separati), ma non si collegava a loro in Build Fasi -> Link Binary With Libraries. Ho dovuto aggiungere i miei 2 SDK all’iMessage Target lì, per abbinare il mio objective App, e ora archivi.

Quindi la morale della trama è: se hai più obiettivi, come le estensioni, assicurati che tutti i tuoi obiettivi siano collegati alle librerie di cui hanno bisogno. È stato in grado di creare e distribuire su simulatore e dispositivo, ma non su archivio.

Aggiornamento: Xcode 9

Le risposte di cui sopra non hanno funzionato con me usando Xcode 9, ma questa risposta ha funzionato perfettamente per me. Ho aggiunto $(OBJROOT)/UninstalledProducts/$(PLATFORM_NAME)/include al mio “Header Search Paths” e Xcode ha linkato l’intestazione della mia libreria statica senza problemi.

Risparmia il problema e fai questo = crea un nuovo account utente sul tuo Mac – apri il progetto con il nuovo account utente – tutti i problemi scompaiono. Risparmia tempo e mantieni la tua sanità mentale. tutte quelle risposte da nerd non aiutano !!

In bocca al lupo