wake-up-neo.com

Xcode 4 kann keine öffentlichen Header-Dateien in Abhängigkeit von statischen Bibliotheken finden

Alternative Titel zur Unterstützung der Suche

  • Xcode kann Header nicht finden
  • Fehlende .h in Xcode
  • Xcode .h Datei nicht gefunden
  • lexikalische oder Präprozessor-Problemdatei nicht gefunden

Ich arbeite an einem iOS-Anwendungsprojekt, das von Xcode 3 stammt. Ich bin jetzt zu Xcode 4 übergegangen. Mein Projekt erstellt eine Reihe von statischen Bibliotheken.

Diese statischen Bibliotheken deklarieren auch öffentliche Header und diese Header werden vom Anwendungscode verwendet. In Xcode 3.x wurden die Header (als Erstellungsphase) in den public headers directory Kopiert, dann wurde im Anwendungsprojekt der public headers directory In den headers search list Eingefügt.

Unter Xcode 4 wird das Build-Verzeichnis nach ~/Library/Developer/Xcode/DerivedData/my-project Verschoben.

Das Problem besteht darin, wie ich in den Einstellungen für die Headersuche auf diesen neuen Speicherort verweise. Es scheint, dass:

  • public headers directory Ist relativ zum Verzeichnis DerivedData, aber
  • headers search - Verzeichnis ist relativ zu etwas anderem (möglicherweise dem Projektspeicherort)

Wie sollte ich ein statisches Bibliotheksziel für die iOS-Entwicklung in Xcode 4 einrichten, das sicherstellt, dass die Header-Dateien den Clients zur Verfügung gestellt werden, die die statische Bibliothek verwenden, wenn sie versuchen, als Abhängigkeit zu kompilieren?

91
rjstelling

Xcode 4-Projekt Fehler beim Kompilieren einer statischen Bibliothek

Verwandte Frage: "lexikalische oder Präprozessor-Problemdatei nicht gefunden" in Xcode 4

Fehler können sein: fehlende Header-Dateien, "Lexikal- oder Präprozessor-Problem"

Lösungen:

  1. Überprüfen Sie, ob die "Benutzerkopfzeilenpfade" korrekt sind
  2. Setzen Sie "Benutzerpfade immer durchsuchen" auf JA
  3. Erstellen Sie in Ihrem Projekt einen Gruppenaufruf "Indizieren von Headern" und ziehen Sie die Header in diese Gruppe, NICHT fügen Sie nach Aufforderung Ziele hinzu.
16
rjstelling

Jede der Lösungen, die ich für dieses Problem gesehen habe, wirkte entweder unelegant (Kopieren von Headern in das Projekt der Anwendung) oder zu stark vereinfacht, sodass sie nur in trivialen Situationen funktionieren.

Die kurze Antwort

Fügen Sie den folgenden Pfad zu Ihren ser Header Search Paths hinzu

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

Warum funktioniert das?

Zunächst müssen wir das Problem verstehen. Unter normalen Umständen, dh beim Ausführen, Testen, Profilieren oder Analysieren, erstellt Xcode Ihr Projekt und legt die Ausgabe in der Build/Products/ -Konfiguration ab /Products-Verzeichnis, das über das Makro $ BUILT_PRODUCTS_DIR verfügbar ist.

In den meisten Handbüchern zu statischen Bibliotheken wird empfohlen, den Pfad Öffentlicher Header-Ordner auf $ TARGET_NAME zu setzen. Dies bedeutet, dass Ihre lib-Datei $ BUILT_PRODUCTS_DIR/libTargetName.a wird und Ihre Header werden in $ BUILT_PRODUCTS_DIR/TargetName abgelegt. Solange Ihre App $ BUILT_PRODUCTS_DIR in den Suchpfaden enthält, funktionieren die Importe in den oben angegebenen 4 Situationen. Dies funktioniert jedoch nicht, wenn Sie versuchen, zu archivieren.

Die Archivierung funktioniert etwas anders

Wenn Sie ein Projekt archivieren, verwendet Xcode einen anderen Ordner mit dem Namen ArchiveIntermediates. In diesem Ordner finden Sie/YourAppName/BuildProductsPath/Release-iphoneos /. Dies ist der Ordner, auf den $ BUILT_PRODUCTS_DIR zeigt, wenn Sie eine Archivierung durchführen. Wenn Sie dort nachschauen, werden Sie feststellen, dass ein Symlink zu Ihrer erstellten statischen Bibliotheksdatei vorhanden ist, der Ordner mit den Überschriften jedoch fehlt.

Um die Header (und die lib-Datei) zu finden, müssen Sie zu IntermediateBuildFilesPath/UninstalledProducts/wechseln. Erinnern Sie sich, als Sie aufgefordert wurden, Skip Install für statische Bibliotheken auf YES zu setzen? Nun, das ist der Effekt, den diese Einstellung hat, wenn Sie ein Archiv erstellen.

Anmerkung: Wenn Sie nicht festlegen, dass die Installation übersprungen werden soll, werden Ihre Header an einen anderen Speicherort verschoben und die lib-Datei wird in Ihr Archiv kopiert, sodass Sie keine .ipa-Datei exportieren können, die Sie an den App Store senden können .

Nach langem Suchen konnte ich kein Makro finden, das genau dem Ordner "UninstalledProducts" entspricht. Daher muss der Pfad mit "$ (BUILD_ROOT) /../ IntermediateBuildFilesPath/UninstalledProducts" erstellt werden.

Zusammenfassung

Stellen Sie für Ihre statische Bibliothek sicher, dass Sie die Installation überspringen und Ihre öffentlichen Header in $ TARGET_NAME platziert sind.

Legen Sie für Ihre App die Suchpfade für Benutzerkopfzeilen auf "$ (BUILT_PRODUCTS_DIR)" fest, was für reguläre Builds geeignet ist, und auf "$ (BUILD_ROOT) /../ IntermediateBuildFilesPath/UninstalledProducts", was für Archivbuilds geeignet ist.

125
Colin

Ich bin beim Entwickeln meiner eigenen statischen Bibliothek auf dasselbe Problem gestoßen, und obwohl Colins Antwort sehr hilfreich war, musste ich sie etwas modifizieren, damit sie unter Xcode 4 unter Verwendung eines Workspace konsistent und einfach ausgeführt und archiviert werden konnte.

Das Besondere an meiner Methode ist, dass Sie für alle Build-Konfigurationen einen einzelnen Benutzerheaderpfad verwenden können.

Meine Methode ist wie folgt:

Erstellen Sie einen Arbeitsbereich

  1. Gehen Sie unter Xcode 4 zu Datei, Neu, Arbeitsbereich.
  2. Im Finder können Sie dann die .xcodeproj-Projekte sowohl für die statische Bibliothek, die Sie verwenden möchten, als auch für die neue App, die Sie erstellen und die die Bibliothek verwendet, ziehen. Weitere Informationen zum Einrichten von Arbeitsbereichen finden Sie in den Apple Docs): https://developer.Apple.com/library/content/featuredarticles/XcodeConcepts/Concept-Workspace .html

Projekteinstellungen für statische Bibliotheken

  1. Stellen Sie sicher, dass alle Header der statischen Bibliothek auf "Öffentlich" gesetzt sind. Dies erfolgt unter den Einstellungen für das statische Bibliotheksziel> Phasen erstellen. Stellen Sie in der Phase "Überschriften kopieren" sicher, dass sich alle Ihre Überschriften im Bereich "Öffentlich" befinden.
  2. Gehen Sie dann zu Build Settings, suchen Sie nach "Public Headers Folder Path" und geben Sie einen Pfad für Ihre Bibliothek ein. Ich entscheide mich dazu:

include/LibraryName

Ich habe dies aus der Verwendung mit RestKit übernommen und festgestellt, dass es mit all meinen statischen Bibliotheken am besten funktioniert. Dadurch wird Xcode angewiesen, alle in Schritt 1 in den Abschnitt "Öffentliche" Header verschobenen Header in den hier angegebenen Ordner zu kopieren, der sich beim Erstellen im Ordner "Abgeleitete Daten" befindet. Wie bei RestKit verwende ich gerne einen einzelnen "include" -Ordner, um jede statische Bibliothek zu enthalten, die ich in einem Projekt verwende.

Ich mag es auch nicht, hier Makros zu verwenden, da wir später einen einzelnen Benutzerkopfzeilensuchpfad verwenden können, wenn wir das Projekt mithilfe der statischen Bibliothek konfigurieren.

  1. Suchen Sie "Skip Install" und stellen Sie sicher, dass dies auf YES gesetzt ist.

Einstellungen für das Projekt über die statische Bibliothek

  1. Fügen Sie die statische Bibliothek als Framework unter Phasen erstellen> Binär mit Bibliotheken verknüpfen hinzu und fügen Sie die Datei libLibraryName.a für jede statische Bibliothek hinzu, die Sie verwenden möchten.
  2. Stellen Sie als Nächstes sicher, dass das Projekt auf die Suche nach Benutzersuchpfaden eingestellt ist. Dies erfolgt unter Build-Einstellungen> Benutzerpfade immer durchsuchen und muss auf JA gesetzt sein.
  3. Suchen Sie im selben Bereich nach User Header Search Paths und fügen Sie Folgendes hinzu:

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

Dadurch wird Xcode angewiesen, nach statischen Bibliotheken in dem Zwischenerstellungsordner zu suchen, den Xcode während des Erstellungsprozesses erstellt. Hier haben wir den Ordner "include", den wir für unsere statischen Bibliotheksverzeichnisse verwenden, die wir in Schritt 2 für die Projekteinstellungen der statischen Bibliothek eingerichtet haben. Dies ist der wichtigste Schritt, damit Xcode Ihre statischen Bibliotheken korrekt findet.

Konfigurieren Sie den Arbeitsbereich

Hier möchten wir den Arbeitsbereich so konfigurieren, dass er beim Erstellen unserer App die statische Bibliothek erstellt. Dies erfolgt durch Bearbeiten des für unsere App verwendeten Schemas.

  1. Stellen Sie sicher, dass Sie das Schema ausgewählt haben, mit dem Ihre Anwendung erstellt wird.
  2. Wählen Sie in der Dropdown-Liste Schema die Option Schema bearbeiten.
  3. Wählen Sie links oben in der Liste Build aus. Fügen Sie ein neues Ziel hinzu, indem Sie das + im mittleren Bereich drücken.
  4. Die statische Bibliothek sollte für die Bibliothek angezeigt werden, die Sie verknüpfen möchten. Wählen Sie die statische iOS-Bibliothek.
  5. Klicken Sie auf Ausführen und Archivieren. Dies weist das Schema an, die Bibliotheken für die statische Bibliothek zu kompilieren, wenn Sie Ihre App erstellen.
  6. Ziehen Sie die statische Bibliothek über Ihr Anwendungsziel. Dadurch werden die statischen Bibliotheken vor Ihrem Anwendungsziel kompiliert.

Starten Sie die Bibliothek

Jetzt sollten Sie in der Lage sein, Ihre statische Bibliothek mit zu importieren

import <LibraryName/LibraryName.h>

Diese Methode umgeht den Aufwand, unterschiedliche Benutzerheaderpfade für unterschiedliche Konfigurationen zu haben, sodass Sie keine Probleme beim Kompilieren für Archive haben sollten.

Warum funktioniert das?

Auf diesen Weg kommt es an:

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

Da wir unsere statische Bibliothek für die Verwendung von "Skip Install" konfigurieren, werden die kompilierten Dateien in den Ordner "UninstalledProjects" im temporären Erstellungsverzeichnis verschoben. Unser Pfad hier wird auch in den Ordner "include" aufgelöst, den wir für unsere statische Bibliothek eingerichtet und für unseren Benutzerheader-Suchpfad verwendet haben. Die beiden arbeiten zusammen und lassen Xcode während des Kompiliervorgangs wissen, wo sich unsere Bibliothek befindet. Da dieses temporäre Erstellungsverzeichnis sowohl für Debug- als auch für Release-Konfigurationen vorhanden ist, benötigen Sie nur einen einzigen Pfad für Xcode, um nach statischen Bibliotheken zu suchen.

85
gdavis

Dies war ein sehr hilfreicher Thread. Bei der Suche nach meiner eigenen Situation stellte ich fest, dass Apple ein 12-seitiges Dokument mit dem Titel "Using Static Libraries in iOS" vom September 2012 enthält. Hier der PDF-Link: http://developer.Apple.com/library/ios/technotes/iOSStaticLibraries/iOSStaticLibraries.pdf

Es ist viel einfacher als die meisten Internetdiskussionen und mit einigen kleinen Mods, die erklären, wie die von mir verwendeten externen Bibliotheken konfiguriert sind, funktioniert es gut für mich. Der wichtigste Teil ist wahrscheinlich:

Wenn Ihr Bibliotheksziel über eine Erstellungsphase "Header kopieren" verfügt, sollten Sie diese löschen. Kopier-Header-Erstellungsphasen funktionieren mit statischen Bibliothekszielen nicht ordnungsgemäß, wenn die Aktion "Archivieren" in Xcode ausgeführt wird.

Neue statische Bibliotheksziele, die mit Xcode 4.4 oder höher erstellt wurden, werden mit einer entsprechend konfigurierten Phase "Dateien kopieren" für Header geliefert. Überprüfen Sie daher, ob bereits eines vorhanden ist, bevor Sie eines erstellen. Wenn dies nicht der Fall ist, klicken Sie unten im Zieleditor auf "Build-Phase hinzufügen" und wählen Sie "Copy Files hinzufügen". Öffnen Sie die neue Build-Phase "Copy Files" und setzen Sie das Ziel auf "Products Directory". Stellen Sie den Unterpfad auf include/$ {PRODUCT_NAME}. Dadurch werden Dateien in einen Ordner kopiert, der nach Ihrer Bibliothek benannt ist (entnommen aus der Build-Einstellung PRODUCT_NAME) und sich in einem Ordner mit dem Namen include in Ihrem Build-Produktverzeichnis befindet. Der Include-Ordner in einem Build Products-Verzeichnis befindet sich im standardmäßigen Header-Suchpfad für Anwendungen. Daher ist dies ein geeigneter Ort, um Header-Dateien abzulegen.

Ich bin mir sicher, dass der Ansatz von Apple in vielen bestehenden Situationen möglicherweise nicht ausreicht. Ich poste dies hier für alle, die gerade ihre Reise auf dem Gartenweg der statischen Bibliothek beginnen - dies ist möglicherweise der beste Ausgangspunkt für einfache Fälle.

15
Michael J.

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

Per Apple documentation:

Ihre Bibliothek enthält eine oder mehrere Header-Dateien, die Clients dieser Bibliothek importieren müssen. Um zu konfigurieren, welche Header an Clients exportiert werden, wählen Sie Ihr Bibliotheksprojekt aus, um den Projekteditor zu öffnen, wählen Sie das Bibliotheksziel aus, um den Zieleditor zu öffnen, und wählen Sie die Registerkarte Erstellungsphasen. Wenn Ihr Bibliotheksziel über eine Erstellungsphase "Header kopieren" verfügt, sollten Sie diese löschen. Kopier-Header-Erstellungsphasen funktionieren mit statischen Bibliothekszielen nicht ordnungsgemäß, wenn die Aktion "Archivieren" in Xcode ausgeführt wird.

4
dmarnel

Werfen Sie einen Blick auf Jonah Wlliams Lösung (auf halber Strecke) und GitHub-Modell (in Kommentaren), um einen Einblick zu erhalten. http://blog.carbonfive.com/2011/04/04/using-open-source-static-libraries-in-xcode-4/

3
d1bru

In meinem Fall hatte mein Arbeitsbereich einige statische Bibliotheksprojekte und eines davon ist abhängig, einschließlich der Header-Dateien mit dem anderen. Das Problem war mit der Reihenfolge des Aufbaus. Auf der Seite "Schema bearbeiten" im Abschnitt "Erstellen" habe ich die Option "Parallelisieren" deaktiviert und die Reihenfolge der Ziele gemäß den Abhängigkeiten angeordnet und das Problem behoben

2
Vamshi

Fügen Sie $ (OBJROOT)/UninstalledProducts/exactPathToHeaders zu Header Search Paths. hinzu

Aus irgendeinem Grund funktionierte das Kontrollkästchen "Rekursiv" bei mir nicht und ich musste den Rest des Pfades dort einfügen, wo sich die Überschriften befinden.

Unter dem Protokollnavigator in Xcode (der Registerkarte rechts neben dem Haltepunktnavigator) können Sie den Buildverlauf anzeigen. Wenn Sie den tatsächlichen Build-Fehler auswählen, können Sie dessen Details erweitern, um setenv PATH anzuzeigen, und überprüfen, ob der Pfad zu Ihren Header-Dateien vorhanden ist.

2
Collin

Ich habe das Risiko, zu zeigen, was für ein Idiot ich bin ... Ich habe den ganzen Nachmittag unter XCode gelitten und mich geweigert, meine .h-Dateien zu finden.

Dann wurde mir klar.

Da ich "XCode 4" verwendete, hatte ich "intelligent" beschlossen, alle meine Projekte in einem Unterordner des Ordners "XCode 4-Projekte" abzulegen.

Diese Leerzeichen im Ordnernamen haben XCode total durcheinander gebracht!

Das Umbenennen dieses Ordners in "XCode_4_Projects" hat Freude (und weniger Fluchen) in mein Leben zurückgebracht.

Erinnern Sie mich noch einmal, welches Jahr ist das?

Vielleicht könnte jemand den Apple Entwicklern sagen ...

1
Mike Gledhill

Keine der obigen Antworten funktionierte für mich auf Xcode 7, aber sie gaben mir eine gute Idee. Für Leute, die mit Xcode 7 zu kämpfen haben, habe ich dies behoben, indem ich Folgendes zu den Suchpfaden für Benutzerkopfzeilen hinzufügte (Anführungszeichen einschließen).

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

Ändern Sie den relativen URL-Teil usr/local/include entsprechend den Angaben in der Einstellung "Pfad des öffentlichen Header-Ordners" der statischen Bibliothek

1
Evol Gate

Keine dieser Antworten hat bei mir funktioniert. Hier ist was gemacht wurde. Fügen Sie Ihrer Build-Einstellung ser Header Search Paths genau Folgendes hinzu (kopieren und einfügen, einschließlich doppelter Anführungszeichen):

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

Beachten Sie das Hinzufügen des Unterverzeichnisses "/ include /" im Vergleich zu anderen Antworten. Wie andere Benutzer bereits betont haben, scheint die Option "rekursiv" nichts zu bewirken, sodass Sie sie ignorieren können.

Mein Projekt konnte jetzt erfolgreich archiviert werden, wenn statische Bibliotheksheaderdateien in der folgenden Form importiert wurden:

#import "LibraryName/HeaderFile.h"

Sie müssen nicht die Einstellung Benutzerpfade immer durchsuchen aktivieren, es sei denn, Sie fügen Ihre statischen Bibliotheksüberschriften in spitzen Klammern (#import <LibraryName/HeaderFile.h>), aber Sie sollten es auf keinen Fall so machen, wenn es sich nicht um einen System-/Framework-Header handelt.

1
devios1

Fügen Sie den folgenden Pfad zu Ihren Suchpfaden für Benutzerkopfzeilen hinzu:

$(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts

Dies ist verifiziert!

1
yirenjun

Hier ist, was das gleiche Problem für mich gelöst hat.

Ich habe ein App-Ziel und ein iMessage-Erweiterungsziel. Dann hatte ich 2 SDKs (meine eigenen), gegen die das App-Ziel verlinkt.

Das Problem war: Mein iMessage-Ziel verwendete auch die 2 SDKs von mir (separate Projekte), aber es wurde keine Verknüpfung mit ihnen in Build-Phasen -> Binär mit Bibliotheken verknüpfen hergestellt. Ich musste meine 2 SDKs dort zum iMessage-Ziel hinzufügen, um meinem App-Ziel zu entsprechen, und jetzt wird es archiviert.

Die Moral der Geschichte lautet also: Wenn Sie mehrere Ziele haben, wie z. B. Erweiterungen, stellen Sie sicher, dass alle Ihre Ziele mit den Bibliotheken verknüpft sind, die sie benötigen. Es war in der Lage, Simulator und Gerät zu erstellen und bereitzustellen, aber nicht zu archivieren.

0
FranticRock

Hierfür gibt es verschiedene komplexe Möglichkeiten, und in diesem Thread werden einige sehr clevere Lösungen vorgeschlagen.

Das Hauptproblem bei all diesen Lösungen besteht darin, dass die Portabilität Ihrer Bibliothek erheblich beeinträchtigt wird.

  • Jedes Mal, wenn Sie ein neues Projekt mit Ihrer Bibliothek starten und für iTunes archivieren müssen, ist dies eine Hölle der Konfiguration.
  • Jedes Mal, wenn Sie Ihr Projekt mit Ihrem Team oder Ihren Kunden teilen müssen, kann es aus irgendeinem Grund zu Problemen kommen (Kontext, Xcode-Version usw.).

Endlich habe ich mich dafür entschieden, einfach - immer - Frameworks zu verwenden, wie von Apple (WWDC-Videos) empfohlen.

Es ist so einfacher und macht am Ende den gleichen Job!

Eine andere sehr elegante Lösung, die zu funktionieren scheint, ist die Verwendung von Private Cocoapods. Cocoapods erledigt die gesamte Konfigurationsarbeit, das Kopieren der Header und so weiter.

Frameworks rock!

0
Moose

Dies ist ein verwandtes Problem, das mich zu dieser Frage geführt hat. Daher füge ich meine Lösung ausschließlich zur Dokumentation hinzu. Dies könnte weitere Seelenstunden des Schwitzens ersparen.

DropboxSDK.h-Datei nicht gefunden

Nachdem ich tagelang versucht hatte, VES zum Kompilieren für iOS zu bringen, stieß ich schließlich auf dieses Problem. Der DropboxSDK.h war definitiv in Reichweite von search headers. Ich habe ihn sogar zum framework headers - Suchpfad hinzugefügt, included den .h direkt und ging zu alle möglichen Längen, um DropboxSDK.h zu finden.

Lösung

EXPLICITY Ziehen Sie die Datei DropboxSDK.framework in Xcodes Project Navigation und vergewissern Sie sich, dass Copy Files if needed markiert ist. Stellen Sie außerdem sicher, dass Ihr Ziel nach Bedarf überprüft wird.

Warnung

Das Setzen des expliziten Framework-Speicherorts in build phases Hat bei mir nicht funktioniert. Ich musste das .framework in Xcode ziehen und sicherstellen, dass die Dateien in mein Projekt kopiert wurden.

# mbp2015 # xcode7 # ios9

0
Jacksonkr

Update: Xcode 9

Die obigen Antworten haben bei mir mit Xcode 9 nicht funktioniert, aber dies Antwort hat bei mir perfekt funktioniert. Ich habe $(OBJROOT)/UninstalledProducts/$(PLATFORM_NAME)/include zu meinen "Header Search Paths" hinzugefügt und Xcode hat den Header meiner statischen Bibliothek ohne Probleme verlinkt.

0