Xcode 4 non può individuare i file di intestazione pubblici dalla dipendenza della libreria statica


91

Titoli alternativi per facilitare la ricerca

  • Xcode non riesce a trovare l'intestazione
  • .H mancante in Xcode
  • File Xcode .h non trovato
  • file problema lessicale o preprocessore non trovato

Sto lavorando a un progetto di applicazione iOS proveniente da Xcode 3. Ora sono passato a Xcode 4, il mio progetto costruisce una serie di librerie statiche.

Quelle 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 compilazione) in public headers directory, quindi nel progetto dell'applicazione sono public headers directorystate aggiunte a headers search list.

In Xcode 4 viene spostata la directory di build ~/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è relativo alla DerivedDatadirectory, ma
  • headers search directory è relativa a qualcos'altro (possibilmente la posizione del progetto)

Come devo impostare una libreria di destinazione statica per lo sviluppo iOS in Xcode 4 che assicuri che i file di intestazione siano resi disponibili ai client che utilizzano la libreria statica quando provano a compilare come dipendenza?


Potrebbe essere correlato ai nomi dei percorsi. Pl controlla questo post. [Le librerie statiche in Xcode 4] [1] [1]: stackoverflow.com/questions/6074576/static-libraries-in-xcode-4/...
Diego Marafetti

Risposte:


124

Ciascuna 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 utente

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

Perché funziona?

Innanzitutto, dobbiamo capire il problema. In circostanze normali, vale a dire quando si esegue, si verifica, si profila o si analizza, 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 delle intestazioni pubbliche 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é la tua app include $ BUILT_PRODUCTS_DIR nei suoi percorsi di ricerca, le importazioni funzioneranno nelle 4 situazioni sopra indicate. Tuttavia, questo non funzionerà quando si tenta di archiviare.

L'archiviazione funziona in modo leggermente diverso

Quando archivi un progetto, Xcode utilizza una cartella diversa chiamata ArchiveIntermediates. All'interno di quella cartella troverai / YourAppName / BuildProductsPath / Release-iphoneos /. Questa è la cartella a cui punta $ BUILT_PRODUCTS_DIR quando si esegue un archivio. Se guardi lì, vedrai che c'è un collegamento simbolico al file della libreria statica creata ma manca la cartella con le intestazioni.

Per trovare le intestazioni (e il file lib) devi andare su 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 crei 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 corrispondesse esattamente alla cartella UninstalledProducts, da qui la necessità di costruire il percorso con "$ (BUILD_ROOT) /../ IntermediateBuildFilesPath / UninstalledProducts"

Sommario

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

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


Come si collega alla cartella DerivedData?
Richard Stelling

Le build regolari vanno a: DerivedData / WorkspaceName-hash / Build / Products / Debug-iphoneos / TargetName.app --- Le build dell'archivio vanno a: DerivedData / WorkspaceName-hash / Build / Intermediates / ArchiveIntermediates / TargetName / BuildProductsPath / Release-iphoneos / TargetName.app
Colin

3
Per me, l'utilizzo di "$ (BUILD_ROOT) /../ IntermediateBuildFilesPath / UninstalledProducts" con la casella di controllo ricorsiva non ha funzionato. Non appena ho usato "$ (BUILD_ROOT) /../ IntermediateBuildFilesPath / UninstalledProducts / <nameOfStaticLibrary>" senza il flag ricorsivo, ha funzionato per me.
TPoschel

7
Nota che il tuo $ (BUILD_ROOT) /../ IntermediateBuildFilesPath / UninstalledProducts è effettivamente $(TARGET_BUILD_DIR). Anche durante l'archiviazione. ;)
Pascal

1
Per me in Xcode 5: $ (BUILD_ROOT) /../ IntermediateBuildFilesPath / UninstalledProducts / include / NAME OF LIBRARY Non ho impostato su YES: cerca sempre i percorsi utente.
xarly

84

Ho riscontrato lo stesso problema durante lo sviluppo della mia libreria statica e sebbene la risposta di Colin sia stata molto utile, ho dovuto modificarla un po 'per funzionare in modo coerente e semplice sia durante l'esecuzione che l'archiviazione di progetti in Xcode 4 utilizzando un'area di lavoro.

Ciò che è diverso nel mio metodo è che puoi utilizzare un unico percorso di intestazione utente per tutte le configurazioni di build.

Il mio metodo è il seguente:

Crea uno spazio di lavoro

  1. In Xcode 4, vai su File, Nuovo, Area di lavoro.
  2. Dal Finder puoi quindi trascinare nei progetti .xcodeproj sia per la libreria statica che desideri utilizzare, sia per la nuova app che stai costruendo che utilizza la libreria. Vedi Apple Docs per maggiori informazioni sulla configurazione degli spazi di lavoro: https://developer.apple.com/library/content/featuredarticles/XcodeConcepts/Concept-Workspace.html

Impostazioni del progetto di libreria statica

  1. Assicurati che tutte le intestazioni della libreria statica siano impostate per essere copiate su "Pubblico". Questa operazione viene eseguita nelle impostazioni per la destinazione della libreria statica> Fasi di creazione. Nella fase "Copia intestazioni", assicurati che tutte le intestazioni si trovino nella sezione "Pubblico".
  2. Quindi vai su Impostazioni build, trova "Percorso cartella intestazioni pubbliche" e digita un percorso per la tua libreria. Scelgo di usare questo:

include / LibraryName

L'ho adottato dall'uso con RestKit e ho scoperto che funziona meglio con tutte le mie librerie statiche. Ciò che fa è dire a Xcode di copiare tutte le intestazioni che abbiamo spostato nella sezione delle intestazioni "Pubbliche" nel passaggio 1 nella cartella specificata qui che risiede nella cartella Dati derivati ​​durante la creazione. 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 le macro qui perché ci permetterà di utilizzare un singolo percorso di ricerca dell'intestazione utente in un secondo momento quando configureremo il progetto utilizzando la libreria statica.

  1. Trova "Salta installazione" e assicurati che sia impostato su SÌ.

Impostazioni per il progetto utilizzando la libreria statica

  1. Aggiungi la libreria statica come framework in Build Phases> Collega Binary With Libraries e aggiungi il file libLibraryName.a per qualsiasi libreria statica che desideri utilizzare.
  2. Quindi assicurati che il progetto sia impostato per la ricerca dei percorsi di ricerca utente. 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 / include"

Questo dice a Xcode di cercare le librerie statiche all'interno della cartella di build intermedia che Xcode crea durante il processo di build. Qui, abbiamo la cartella "include" che stiamo utilizzando per le posizioni delle nostre librerie statiche che abbiamo impostato nel passaggio 2 per le impostazioni del progetto della libreria statica. Questo è il passaggio 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 crei la libreria statica quando creiamo la nostra app. Questo viene fatto modificando lo schema utilizzato per la nostra app.

  1. Assicurati di avere selezionato lo schema che creerà la tua applicazione.
  2. Dal menu a discesa dello schema, scegli Modifica schema.
  3. Seleziona Build nella parte superiore dell'elenco a sinistra. Aggiungi un nuovo target premendo il + nel riquadro centrale.
  4. Dovresti vedere la libreria statica visualizzata per la libreria che stai tentando di collegare. Scegli la libreria statica di iOS.
  5. Fare clic su Esegui e Archivia. Questo indica allo schema di compilare le librerie per la libreria statica ogni volta che si crea la propria app.
  6. Trascina la libreria statica sopra la destinazione dell'applicazione. In questo modo le librerie statiche vengono compilate prima della destinazione dell'applicazione.

Inizia a usare la libreria

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

import <LibraryName/LibraryName.h>

Questo metodo evita il fastidio di dover avere percorsi di intestazione utente diversi per configurazioni diverse, quindi non dovresti avere problemi a compilare 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 configuriamo per la nostra libreria statica e utilizziamo per il nostro percorso di ricerca dell'intestazione utente. La collaborazione tra i due consente a Xcode di sapere dove trovare la nostra libreria durante il processo di compilazione. Poiché questa directory di build temporanea esiste per entrambe le configurazioni di debug e di rilascio, è necessario un solo percorso per Xcode per cercare le librerie statiche.


3
Sei fantastico, amico! Questo è davvero utile e funziona come hai descritto.
neevek

1
eccezionale. Dove manderò i fiori :)
Ramesh

1
Dopo aver impostato questo, alcuni di voi potrebbero incontrare " ...] selettore non riconosciuto inviato alla classe 0x ... ". Nel caso in cui lo fai, prova ad aggiungerlo in Obiettivi del progetto- > Progetto-> Impostazioni build-> Collegamento-> Altri flag del linker : -all_load
MkVal

Assicurati che i percorsi di ricerca dell'intestazione utente siano tra virgolette se contengono spazi.
rispetta il codice

Xcode 4.6.2 non scrive nulla in "$ (PROJECT_TEMP_DIR) /../ UninstalledProducts / include" per me. Qualche idea di cosa mi manchi? O il comportamento di Xcode è cambiato di nuovo?
c roald

16

Il progetto Xcode 4 non riesce a compilare una libreria statica

Domanda correlata: "File problema 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 dell'intestazione utente" siano corretti
  2. Imposta "Cerca sempre percorsi utente" su SÌ
  3. Crea una chiamata di gruppo "Indicizzazione intestazioni" nel tuo progetto e trascina le intestazioni in questo gruppo, NON aggiungerle a nessuna destinazione quando richiesto.

11
Un altro passaggio facilmente trascurato ma estremamente importante: assicurati che i percorsi di ricerca siano racchiusi tra virgolette doppie per evitare spazi. Mi dimentico sempre di farlo.
Brad

Grazie @ Brad, questa è davvero un'osservazione molto importante e utile.
Julian D.

15

Questo è stato un thread molto utile. Nella ricerca per la mia situazione, ho scoperto che Apple ha un documento di 12 pagine datato settembre 2012 intitolato "Utilizzo di librerie statiche in iOS". Ecco il collegamento al pdf: http://developer.apple.com/library/ios/technotes/iOSStaticLibraries/iOSStaticLibraries.pdf

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

Se la tua libreria di destinazione ha una fase di creazione "Copia intestazioni", dovresti eliminarla; Le fasi di creazione delle intestazioni di copia non funzionano correttamente con le destinazioni della libreria statica quando si esegue l'azione "Archivia" in Xcode.

I nuovi target di libreria statica creati con Xcode 4.4 o versioni successive verranno forniti con una fase di copia dei file configurata in modo appropriato per le intestazioni, quindi è necessario verificare se ne hai già uno prima di crearne uno. In caso contrario, premere "Add Build Phase" nella parte inferiore dell'editor di destinazione e scegliere "Add Copy Files". Rivelare la nuova fase di compilazione Copia file e impostare la destinazione su "Directory prodotti". Imposta il percorso secondario per includere / $ {PRODUCT_NAME}. Questo copierà i file in una cartella denominata in base alla tua libreria (presa dall'impostazione di build di PRODUCT_NAME), all'interno di una cartella denominata include, all'interno della directory dei prodotti creati. La cartella include all'interno di una directory dei prodotti di compilazione si trova nel percorso di ricerca dell'intestazione predefinita per le applicazioni, quindi questo è un posto appropriato per inserire i file di intestazione.

Sono sicuro che in molte situazioni esistenti l'approccio di Apple potrebbe non essere sufficiente. Lo posto qui per chiunque stia appena iniziando il proprio viaggio sul sentiero del giardino statico della biblioteca: questo potrebbe essere il miglior punto di partenza per casi semplici.


per coloro che seguono il link sopra .. attenzione: il passaggio che ti chiede di eliminare i file modello fittizio quando crei il progetto libreria .. NON CANCELLARE IL file * .pch .. alla fine ti perseguiterà + quanto sopra il consiglio non funziona con le categorie .. c'è una soluzione per questo però (l'ho visto da qualche parte)
abbood

Grazie per aver fornito un collegamento a un approccio Apple ufficiale per la creazione di librerie statiche. Ho iniziato costruendo la mia libreria statica utilizzando questo approccio , ma non sono riuscito ad archiviare. @abbood - Qual è il problema con l'eliminazione del file pch che viene generato?
augusto callejas

se elimini il file .pch .. il progetto semplicemente non verrà compilato .. (per scopi di archiviazione o altro) ..
abbood

Non funziona per me. Quando provo l'istruzione import con "" non funziona, ho bisogno di <>. Inoltre durante l'archiviazione non è in grado di trovare le intestazioni. Qualche idea?
user1010819

4

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

Secondo la documentazione Apple:

La tua libreria avrà uno o più file di intestazione che i client di quella libreria dovranno importare. Per configurare quali intestazioni vengono esportate sui client, selezionare il progetto della libreria per aprire l'editor del progetto, selezionare la destinazione della libreria per aprire l'editor di destinazione e selezionare la scheda delle fasi di creazione. Se la tua libreria di destinazione ha una fase di creazione "Copia intestazioni", dovresti eliminarla; Le fasi di creazione delle intestazioni di copia non funzionano correttamente con le destinazioni della libreria statica quando si esegue l'azione "Archivia" in Xcode.


3

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


4
Sebbene questo possa tecnicamente rispondere alla domanda, sarebbe preferibile includere le parti essenziali dell'articolo collegato nella risposta e fornire il collegamento come riferimento. Non farlo lascia la risposta a rischio di marciume del link.
jscs

2

Aggiungi $ (OBJROOT) / UninstalledProducts / exactPathToHeaders al file 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 in cui si trovano le intestazioni.

Sotto il Navigatore log in Xcode (la scheda a destra del navigatore dei punti di interruzione) puoi vedere la cronologia della build. Se selezioni l'effettivo errore di compilazione, puoi espandere i suoi dettagli per vedere setenv PATH e verificare che il percorso dei tuoi file di intestazione sia lì.


Buona nota sulla casella di controllo ricorsiva, stesso problema qui.
Codezy

Sì, ho dovuto specificare anche una particolare sottocartella, il controllo ricorsivo non ha funzionato.
Oliver Pearmain

Tuttavia, ho finito per utilizzare questo percorso (semplicemente perché è più breve) "$ (PROJECT_TEMP_DIR) /../ UninstalledProducts / SubProjectHeaders"
Oliver Pearmain

2

Nel mio caso il mio spazio di lavoro aveva un paio di progetti di libreria statica e uno di questi ha una dipendenza, inclusi i file di intestazione con l'altro. Il problema riguardava l'ordine di costruzione. Nella pagina di modifica dello schema nella sezione Build, ho deselezionato l'opzione parallelize e ho organizzato l'ordine degli obiettivi in ​​base alle dipendenze e risolto dal problema


1

Aggiungi il seguente percorso ai percorsi di ricerca dell'intestazione utente :

$(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts

Questo è verificato!


1

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

Poi ho capito.

Poiché stavo usando "XCode 4", avevo "intelligentemente" deciso di mettere tutti i miei progetti in una sottocartella di una cartella chiamata " XCode 4 projects ".

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

Rinominare questa cartella in " XCode_4_Projects " ha riportato gioia (e meno imprecazioni) nella mia vita.

Ricordami di nuovo, cosa anno è questo?

Forse qualcuno potrebbe dire agli sviluppatori Apple ...


1

Nessuna di queste risposte ha funzionato per me. Ecco cosa ha fatto. Aggiungi esattamente quanto segue (copia e incolla comprese le virgolette doppie) all'impostazione di compilazione Percorsi di ricerca dell'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" sembra non fare nulla, quindi puoi ignorarla.

Il mio progetto è stato ora in grado di archiviare correttamente durante l'importazione di file di intestazione della libreria statica nella seguente forma:

#import "LibraryName/HeaderFile.h"

Non è necessario abilitare l' impostazione Cerca sempre percorsi utente a meno che non si includano le intestazioni della libreria statica con parentesi angolari ( #import <LibraryName/HeaderFile.h>), ma in realtà non dovresti farlo comunque in questo modo se non è un'intestazione di sistema / framework.


1

Nessuna delle risposte sopra ha funzionato per me su Xcode 7 ma mi hanno dato una buona idea. Per i ragazzi che lottano con Xcode 7, ho risolto il problema aggiungendo quanto segue ai percorsi di ricerca dell'intestazione dell'utente (includi le virgolette)

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

Modificare la parte relativa dell'URL in usr/local/includebase a ciò che è presente nell'impostazione "Percorso cartella intestazione pubblica" della libreria statica


0

Questo è un problema correlato che mi ha portato a questa domanda, quindi sto aggiungendo la mia soluzione rigorosamente per la documentazione / potrebbe far risparmiare ad un'altra anima ore di sudore

File DropboxSDK.h non trovato

Dopo giorni di tentativi di compilazione di VES per iOS, alla fine mi sono imbattuto in questo problema. il DropboxSDK.hera decisamente alla portata di l' search headersho anche aggiunto al framework headerspercorso di ricerca, included il .hdirettamente e ho fatto di tutto per cercare di essere DropboxSDK.htrovato.

Soluzione

ESPLICITÀ trascina il DropboxSDK.frameworkfile in Xcode Project Navigatione assicurati che Copy Files if neededsia spuntato. Assicurati anche che il tuo obiettivo sia controllato se necessario.

avvertimento

L'impostazione della posizione del framework esplicito in build phasesnon ha funzionato per me. Ho dovuto trascinare il .framework in Xcode e assicurarmi che i file fossero copiati nel mio progetto.

# mbp2015 # xcode7 # ios9


0

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

Il problema principale di tutte queste soluzioni è che diminuisce seriamente 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 devi condividere il tuo progetto con il tuo team o con i clienti, può interrompersi per qualsiasi motivo (contesto, versione Xcode, qualunque cosa, ..)

La mia scelta è stata infine quella di utilizzare semplicemente i framework - sempre - come consigliato da Apple (WWDC Videos).

È molto più facile e alla fine fa lo stesso lavoro!

Un'altra soluzione abbastanza elegante che sembra funzionare è quella di utilizzare Private Cocoapods. Cocoapods fa tutto il lavoro di configurazione, copia dell'intestazione e così via.

Quadri rock!


1
Dove lo metti? simply use frameworks - always -
Neil Faulkner

Non è ambientato da nessuna parte. È semplicemente una scelta architettonica. I framework sono "librerie moderne" molto più facili da collegare e gestire. Al momento di questo messaggio, swift non consente ancora di creare librerie binarie.
Moose

0

Ecco cosa ha risolto lo stesso problema per me.

Ho un target dell'app e un target di estensione iMessage. Poi ho avuto 2 SDK (il mio), a cui si collega l'App Target.

Il problema era: il mio obiettivo iMessage utilizzava anche i miei 2 SDK (progetti separati), ma non si collegava a loro in Build Phases -> Link Binary With Libraries. Ho dovuto aggiungere i miei 2 SDK a iMessage Target lì, per abbinare il mio obiettivo dell'app, e ora si archivia.

Quindi la morale della storia è: 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 archiviare.


0

Aggiornamento: Xcode 9

Le risposte di cui sopra non hanno funzionato per me usando Xcode 9, ma questa risposta ha funzionato perfettamente per me. Ho aggiunto $(OBJROOT)/UninstalledProducts/$(PLATFORM_NAME)/includeai miei "Percorsi di ricerca intestazione" e Xcode ha collegato l'intestazione della mia libreria statica senza problemi.


-18

Risparmia la fatica e fallo = 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

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.