Xcode 4 no puede localizar archivos de encabezado públicos de la dependencia de la biblioteca estática

91

Títulos alternativos para ayudar a la búsqueda

  • Xcode no puede encontrar el encabezado
  • Falta .h en Xcode
  • Archivo Xcode .h no encontrado
  • archivo de problema léxico o preprocesador no encontrado

Estoy trabajando en un proyecto de aplicación de iOS que vino de Xcode 3. Ahora me he trasladado a Xcode 4, mi proyecto crea una serie de bibliotecas estáticas.

Esas bibliotecas estáticas también declaran encabezados públicos y esos encabezados son utilizados por el código de la aplicación. En Xcode 3.x, los encabezados se copiaron (como una fase de compilación) al public headers directory, luego, en el proyecto de la aplicación, public headers directoryse agregaron al headers search list.

En Xcode 4, se mueve el directorio de compilación ~/Library/Developer/Xcode/DerivedData/my-project.

El problema es ¿cómo hago referencia a esta nueva ubicación en la configuración de búsqueda de encabezados? Parece que:

  • public headers directoryes relativo al DerivedDatadirectorio, pero
  • headers search el directorio es relativo a otra cosa (posiblemente la ubicación del proyecto)

¿Cómo debo configurar un destino de biblioteca estática para el desarrollo de iOS en Xcode 4 que garantice que los archivos de encabezado estén disponibles para los clientes que usan la biblioteca estática al intentar compilar como una dependencia?

Richard Stelling
fuente
Podría estar relacionado con nombres de ruta. Por favor, consulte esta publicación. [Bibliotecas estáticas en Xcode 4] [1] [1]: stackoverflow.com/questions/6074576/static-libraries-in-xcode-4/…
Diego Marafetti

Respuestas:

124

Cada una de las soluciones que he visto para este problema me ha parecido poco elegante (copiar encabezados en el proyecto de la aplicación) o demasiado simplificada hasta el punto de que solo funcionan en situaciones triviales.

La respuesta corta

Agregue la siguiente ruta a sus rutas de búsqueda de encabezado de usuario

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

¿Por qué funciona esto?

Primero, debemos comprender el problema. En circunstancias normales, es decir, cuando ejecuta, prueba, perfila o analiza, Xcode crea su proyecto y coloca la salida en el directorio Build / Products / Configuration / Products, que está disponible a través de $ BUILT_PRODUCTS_DIR macro .

La mayoría de las guías sobre bibliotecas estáticas recomiendan configurar la Ruta de la carpeta de encabezados públicos en $ TARGET_NAME , lo que significa que su archivo lib se convierte en $ BUILT_PRODUCTS_DIR /libTargetName.a y sus encabezados se colocan en $ BUILT_PRODUCTS_DIR / TargetName. Siempre que su aplicación incluya $ BUILT_PRODUCTS_DIR en sus rutas de búsqueda, las importaciones funcionarán en las 4 situaciones indicadas anteriormente. Sin embargo, esto no funcionará cuando intente archivar.

El archivo funciona de forma un poco diferente

Cuando archivas un proyecto, Xcode usa una carpeta diferente llamada ArchiveIntermediates. Dentro de esa carpeta encontrará / YourAppName / BuildProductsPath / Release-iphoneos /. Esta es la carpeta que apunta $ BUILT_PRODUCTS_DIR cuando realiza un archivo. Si mira allí, verá que hay un enlace simbólico a su archivo de biblioteca estático construido, pero falta la carpeta con los encabezados.

Para encontrar los encabezados (y el archivo lib) debe ir a IntermediateBuildFilesPath / UninstalledProducts /. Recuerde cuando le dijeron que configurara Omitir instalación en SÍ para las bibliotecas estáticas? Bueno, este es el efecto que tiene la configuración cuando haces un archivo.

Nota al margen: si no lo configura para omitir la instalación, sus encabezados se colocarán en otra ubicación y el archivo lib se copiará en su archivo, lo que le impedirá exportar un archivo .ipa que puede enviar a la App Store. .

Después de mucha búsqueda, no pude encontrar ninguna macro que se corresponda exactamente con la carpeta UninstalledProducts, de ahí la necesidad de construir la ruta con "$ (BUILD_ROOT) /../ IntermediateBuildFilesPath / UninstalledProducts"

Resumen

Para su biblioteca estática, asegúrese de omitir la instalación y de que sus encabezados públicos se coloquen en $ TARGET_NAME.

Para su aplicación, configure las rutas de búsqueda del encabezado de usuario en "$ (BUILT_PRODUCTS_DIR)", que funciona bien para compilaciones normales, y "$ (BUILD_ROOT) /../ IntermediateBuildFilesPath / UninstalledProducts", que funciona para compilaciones de archivos.

Colin
fuente
¿Cómo se relaciona esto con la carpeta DerivedData?
Richard Stelling
Las compilaciones regulares van a: DerivedData / WorkspaceName-hash / Build / Products / Debug-iphoneos / TargetName.app --- Las compilaciones de archivo van a: DerivedData / WorkspaceName-hash / Build / Intermediates / ArchiveIntermediates / TargetName / BuildProductsPath / Release-iphoneos / TargetName.app
Colin
3
Para mí, el uso de "$ (BUILD_ROOT) /../ IntermediateBuildFilesPath / UninstalledProducts" con la casilla de verificación recursiva no funcionó. Tan pronto como utilicé "$ (BUILD_ROOT) /../ IntermediateBuildFilesPath / UninstalledProducts / <nameOfStaticLibrary>" sin el indicador recursivo, funcionó para mí.
TPoschel
7
Tenga en cuenta que su $ (BUILD_ROOT) /../ IntermediateBuildFilesPath / UninstalledProducts es en realidad $(TARGET_BUILD_DIR). Incluso al archivar. ;)
Pascal
1
Para mí en Xcode 5: $ (BUILD_ROOT) /../ IntermediateBuildFilesPath / UninstalledProducts / include / NAME OF LIBRARY No lo configuré en YES: Siempre busque rutas de usuario.
xarly
84

Me encontré con este mismo problema al desarrollar mi propia biblioteca estática y, aunque la respuesta de Colin fue muy útil, tuve que modificarla un poco para que funcionara de manera consistente y simple al ejecutar y archivar proyectos en Xcode 4 usando un espacio de trabajo.

Lo que es diferente de mi método es que puede usar una ruta de encabezado de usuario único para todas sus configuraciones de compilación.

Mi método es el siguiente:

Crea un espacio de trabajo

  1. En Xcode 4, vaya a Archivo, Nuevo, Espacio de trabajo.
  2. Desde Finder, puede arrastrar los proyectos .xcodeproj tanto para la biblioteca estática que desea usar como para la nueva aplicación que está creando que usa la biblioteca. Consulte Apple Docs para obtener más información sobre cómo configurar áreas de trabajo: https://developer.apple.com/library/content/featuredarticles/XcodeConcepts/Concept-Workspace.html

Configuración del proyecto de biblioteca estática

  1. Asegúrese de que todos los encabezados de la biblioteca estática estén configurados para copiarse en "Público". Esto se hace en la configuración del destino de la biblioteca estática> Fases de compilación. En la fase "Copiar encabezados", asegúrese de que todos sus encabezados estén dentro de la sección "Público".
  2. A continuación, vaya a Configuración de compilación, busque "Ruta de la carpeta de encabezados públicos" y escriba una ruta para su biblioteca. Elijo usar esto:

incluir / LibraryName

Adopté esto del uso con RestKit y descubrí que funciona mejor con todas mis bibliotecas estáticas. Lo que esto hace es decirle a Xcode que copie todos los encabezados que movimos a la sección de encabezados "Públicos" en el paso 1 a la carpeta que especificamos aquí que reside dentro de la carpeta de Datos Derivados al construir. Al igual que con RestKit, me gusta usar una sola carpeta "incluir" para contener cada biblioteca estática que estoy usando en un proyecto.

Tampoco me gusta usar macros aquí porque nos permitirá usar una ruta de búsqueda de encabezado de usuario único más adelante cuando configuremos el proyecto usando la biblioteca estática.

  1. Busque "Omitir instalación" y asegúrese de que esté configurado en SÍ.

Configuración del proyecto que utiliza la biblioteca estática

  1. Agregue la biblioteca estática como un marco en Build Phases> Link Binary With Libraries y agregue el archivo libLibraryName.a para cualquier biblioteca estática que desee usar.
  2. A continuación, asegúrese de que el proyecto esté configurado para buscar rutas de búsqueda de usuarios. Esto se hace en Configuración de compilación> Buscar siempre rutas de usuario y asegúrese de que esté configurado en SÍ.
  3. En la misma área, busque Rutas de búsqueda de encabezados de usuario y agregue:

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

Esto le dice a Xcode que busque bibliotecas estáticas dentro de la carpeta de compilación intermedia que Xcode crea durante el proceso de compilación. Aquí, tenemos la carpeta "incluir" que estamos usando para nuestras ubicaciones de biblioteca estática que configuramos en el paso 2 para la configuración del proyecto de biblioteca estática. Este es el paso más importante para que Xcode encuentre correctamente sus bibliotecas estáticas.

Configurar el espacio de trabajo

Aquí queremos configurar el espacio de trabajo para que construya la biblioteca estática cuando creemos nuestra aplicación. Esto se hace editando el esquema utilizado para nuestra aplicación.

  1. Asegúrese de tener seleccionado el esquema que creará su aplicación.
  2. En el menú desplegable de esquemas, elija Editar esquema.
  3. Seleccione Construir en la parte superior de la lista de la izquierda. Agregue un nuevo objetivo presionando + en el panel central.
  4. Debería ver aparecer la biblioteca estática para la biblioteca que está intentando vincular. Elija la biblioteca estática de iOS.
  5. Haga clic en Ejecutar y Archivar. Esto le dice al esquema que compile las bibliotecas para la biblioteca estática cada vez que construya su aplicación.
  6. Arrastre la biblioteca estática sobre el destino de su aplicación. Esto hace que las bibliotecas estáticas se compilen antes que el destino de su aplicación.

Comience a usar la biblioteca

Ahora, debería poder importar su biblioteca estática usando

import <LibraryName/LibraryName.h>

Este método evita la molestia de tener que tener diferentes rutas de encabezado de usuario para diferentes configuraciones, por lo que no debería tener problemas para compilar archivos.

¿Por qué funciona esto?

Todo depende de este camino:

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

Debido a que configuramos nuestra biblioteca estática para usar "Omitir instalación", los archivos compilados se mueven a la carpeta "Proyectos desinstalados" dentro del directorio de compilación temporal. Nuestra ruta aquí también se resuelve en la carpeta "incluir" que configuramos para nuestra biblioteca estática y usamos para nuestra ruta de búsqueda de encabezado de usuario. Los dos trabajando juntos le permiten a Xcode saber dónde encontrar nuestra biblioteca durante el proceso de compilación. Dado que este directorio de compilación temporal existe para las configuraciones de depuración y versión, solo necesita una ruta única para que Xcode busque bibliotecas estáticas.

gdavis
fuente
3
¡Eres increíble, hombre! Esto es realmente útil y funciona como lo describió.
neevek
1
increíble. ¿Dónde debo enviar flores :)
Ramesh
1
Después de configurar esto, algunos de ustedes pueden encontrar " ...] selector no reconocido enviado a la clase 0x ... ". En caso de que lo haga, intente agregar esto en Targets-> Project-> Build Settings-> Linking-> Other Linker Flags : -all_load
MkVal
Asegúrese de que las rutas de búsqueda del encabezado del usuario estén entre comillas si tienen espacios.
respectTheCode
Xcode 4.6.2 no está escribiendo nada en "$ (PROJECT_TEMP_DIR) /../ UninstalledProducts / include" para mí. ¿Alguna idea de lo que me estoy perdiendo? ¿O el comportamiento de Xcode ha cambiado de nuevo?
c roald
16

El proyecto Xcode 4 no puede compilar una biblioteca estática

Pregunta relacionada: "archivo de problema léxico o preprocesador no encontrado" en Xcode 4

Los errores pueden incluir;faltan archivos de encabezado, "problema léxico o preprocesador"

Soluciones:

  1. Compruebe que las "rutas de encabezado de usuario" sean correctas
  2. Establezca "Buscar siempre rutas de usuario" en SÍ
  3. Cree una llamada de grupo "Encabezados de indexación" en su proyecto y arrastre los encabezados a este grupo, NO agregue a ningún objetivo cuando se le solicite.
Richard Stelling
fuente
11
Otro paso que se pasa por alto fácilmente pero que es extremadamente importante: asegúrese de que sus rutas de búsqueda estén entre comillas dobles para escapar de los espacios. Siempre me olvido de hacer eso.
Brad
Gracias @Brad, este es un comentario muy importante y útil.
Julian D.
15

Este fue un hilo muy útil. Al investigar mi propia situación, descubrí que Apple tiene un documento de 12 páginas con fecha de septiembre de 2012 titulado "Uso de bibliotecas estáticas en iOS". Aquí está el enlace pdf: http://developer.apple.com/library/ios/technotes/iOSStaticLibraries/iOSStaticLibraries.pdf

Es mucho más simple que la mayoría de las discusiones en Internet, y con algunas pequeñas modificaciones para explicar cómo están configuradas las bibliotecas externas que estoy usando, me está funcionando bien. Probablemente la parte más importante sea:

Si el destino de su biblioteca tiene una fase de creación de "Copiar encabezados", debe eliminarlo; Las fases de compilación de los encabezados de copia no funcionan correctamente con los destinos de la biblioteca estática al realizar la acción "Archivar" en Xcode.

Los nuevos destinos de biblioteca estática creados con Xcode 4.4 o posterior vendrán con una fase de Copiar archivos configurada apropiadamente para los encabezados, por lo que debe verificar si ya tiene uno antes de crear uno. Si no lo hace, presione "Agregar fase de compilación" en la parte inferior del editor de destino y elija "Agregar archivos de copia". Revele la nueva fase de creación de archivos de copia y establezca el destino en "Directorio de productos". Configure la Subruta para incluir / $ {PRODUCT_NAME}. Esto copiará los archivos en una carpeta con el nombre de su biblioteca (tomada de la configuración de compilación de PRODUCT_NAME), dentro de una carpeta llamada include, dentro de su directorio de productos compilados. La carpeta de inclusión dentro de un directorio de productos de compilación se encuentra en la ruta de búsqueda de encabezado predeterminada para las aplicaciones, por lo que este es un lugar apropiado para colocar los archivos de encabezado.

Estoy seguro de que en muchas situaciones existentes el enfoque de Apple puede no ser suficiente. Publico esto aquí para cualquiera que esté comenzando su viaje en el camino del jardín de la biblioteca estática; este puede ser el mejor punto de partida para casos simples.

Michael J.
fuente
para aquellos que siguen el enlace anterior ... cuidado: el paso que le pide que elimine los archivos de plantilla ficticios cuando cree el proyecto de la biblioteca ... NO BORRE EL archivo * .pch ... eventualmente lo perseguirá + lo anterior el consejo no funciona con las categorías ... aunque hay una solución para eso (lo vi en alguna parte)
abbood
Gracias por proporcionar un enlace a un enfoque oficial de Apple para crear bibliotecas estáticas. Comencé construyendo mi biblioteca estática usando este enfoque , pero no pude Archivar. @abbood: ¿Cuál es el problema al eliminar el archivo pch que se genera?
augusto callejas
si elimina el archivo .pch ... el proyecto simplemente no se compilará ... (con el propósito de archivar o de otra manera) ..
abbood
No funciona para mí. Cuando intento importar la declaración con "" no funciona, necesito <>. Además, mientras archivo no puedo encontrar encabezados. ¿Alguna idea?
user1010819
4

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

Según la documentación de Apple:

Su biblioteca tendrá uno o más archivos de encabezado que los clientes de esa biblioteca deben importar. Para configurar qué encabezados se exportan a los clientes, seleccione su proyecto de biblioteca para abrir el editor del proyecto, seleccione el destino de la biblioteca para abrir el editor de destino y seleccione la pestaña de fases de compilación. Si el destino de su biblioteca tiene una fase de creación de "Copiar encabezados", debe eliminarlo; Las fases de compilación de encabezados de copia no funcionan correctamente con destinos de biblioteca estática al realizar la acción "Archivar" en Xcode.

dmarnel
fuente
2

Agregue $ (OBJROOT) / UninstalledProducts / exactPathToHeaders a las rutas de búsqueda del encabezado.

Por alguna razón, la casilla de verificación recursiva no funcionó para mí y tuve que agregar el resto de la ruta a donde se encuentran los encabezados.

En el navegador de registros en Xcode (la pestaña a la derecha del navegador de puntos de interrupción) puede ver el historial de compilación. Si selecciona el error de compilación real, puede expandir sus detalles para ver el setenv PATH y verificar para asegurarse de que la ruta a sus archivos de encabezado esté allí.

Collin
fuente
Buena nota sobre la casilla de verificación recursiva, el mismo problema aquí.
Codezy
Sí, también tuve que especificar una subcarpeta en particular, la verificación recursiva no funcionó.
Oliver Pearmain
Sin embargo, terminé usando esta ruta (simplemente porque es más corta) "$ (PROJECT_TEMP_DIR) /../ UninstalledProducts / SubProjectHeaders"
Oliver Pearmain
2

En mi caso, mi espacio de trabajo tenía un par de proyectos de biblioteca estática y uno de ellos tiene dependencia, incluidos los archivos de encabezado, con el otro. El problema estaba en el orden de construcción. En la página de edición de Esquema en la sección Construir, deseleccioné la opción de paralelizar y organicé el orden de los objetivos según las dependencias y se resolvió por problema

Vamshi
fuente
1

Agregue la siguiente ruta a sus rutas de búsqueda de encabezado de usuario:

$(BUILD_ROOT)/../IntermediateBuildFilesPath/UninstalledProducts

¡Esto está verificado!

yirenjun
fuente
1

A riesgo de mostrar lo idiota que soy ... He estado sufriendo de XCode negándome a encontrar mis archivos .h toda la tarde.

Entonces me di cuenta.

Como estaba usando "XCode 4", había decidido "inteligentemente" poner todos mis proyectos en una subcarpeta de una carpeta llamada " Proyectos XCode 4 ".

¡Esos espacios en el nombre de la carpeta arruinaron XCode a lo grande!

Cambiar el nombre de esta carpeta a " XCode_4_Projects " me ha traído alegría (y menos palabrotas) a mi vida.

Recuérdame de nuevo, ¿en qué año es este?

Quizás alguien podría decirle a los desarrolladores de Apple ...

Mike Gledhill
fuente
1

Ninguna de estas respuestas funcionó para mí. Esto es lo que hizo. Agregue exactamente lo siguiente (copie y pegue, incluidas las comillas dobles) a la configuración de compilación de rutas de búsqueda de encabezado de usuario :

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

Tenga en cuenta la adición del subdirectorio "/ include /" en comparación con otras respuestas. Como han señalado otros usuarios, la opción "recursiva" no parece hacer nada, por lo que puede ignorarla.

Mi proyecto ahora podía archivarse correctamente al importar archivos de encabezado de biblioteca estática en la siguiente forma:

#import "LibraryName/HeaderFile.h"

No es necesario que habilite la configuración Buscar siempre rutas de usuario a menos que incluya los encabezados de su biblioteca estática con corchetes angulares ( #import <LibraryName/HeaderFile.h>), pero de todos modos no debería hacerlo de esa manera si no es un encabezado de sistema / marco.

devios1
fuente
1

Ninguna de las respuestas anteriores me funcionó en Xcode 7, pero me dieron una buena idea. Para los chicos que luchan con Xcode 7, solucioné esto agregando lo siguiente a las rutas de búsqueda del encabezado del usuario (incluya comillas)

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

Cambie la parte de la URL relativa de usr/local/includeacuerdo con lo que hay en la configuración 'Ruta de la carpeta de encabezado público' de la biblioteca estática

Puerta Evol
fuente
0

Este es un problema relacionado que me llevó a esta pregunta, así que estoy agregando mi solución estrictamente para la documentación / podría ahorrarme otras horas de sudor.

Archivo DropboxSDK.h no encontrado

Después de días de intentar que VES se compilara para iOS, finalmente encontré este problema. el DropboxSDK.hestaba definitivamente al alcance de search headersincluso lo agregué a la framework headersruta de búsqueda, included .hdirectamente e hice todo tipo de esfuerzos para tratar de obtenerDropboxSDK.h encontrado.

Solución

EXPLICIDAD arrastre el DropboxSDK.frameworkarchivo a Xcode Project Navigationy asegúrese deCopy Files if needed esté marcado. También asegúrese de que su objetivo esté marcado según sea necesario.

Advertencia

Establecer la ubicación explícita del marco en build phasesno funcionó para mí. Tuve que arrastrar el .framework a Xcode y asegurarme de que los archivos se copiaran en mi proyecto.

# mbp2015 # xcode7 # ios9

Jacksonkr
fuente
0

Hay varias formas complejas de hacer esto, y en este hilo se proponen algunas soluciones muy inteligentes.

El principal problema de todas estas soluciones es que disminuyen seriamente la portabilidad de su biblioteca.

  • Cada vez que necesita comenzar un nuevo proyecto usando su biblioteca y archivarlo para iTunes, es un infierno de configuración.
  • Cada vez que necesite compartir su proyecto con su equipo o clientes, puede romperse por cualquier motivo (contexto, versión de Xcode, lo que sea, ..)

Finalmente, mi elección ha sido simplemente usar marcos, siempre, como lo recomienda Apple (Videos WWDC).

¡Es tan fácil y hace el mismo trabajo al final!

Otra solución bastante elegante que parece funcionar es utilizar Private Cocoapods. Cocoapods hace todo el trabajo de configuración, copia de encabezado y demás.

¡Armazones de rock!

Alce
fuente
1
¿Dónde pones esto? simply use frameworks - always -
Neil Faulkner
No se estableció en ninguna parte. Es simplemente una elección arquitectónica. Los marcos son "bibliotecas modernas" que son mucho más fáciles de vincular y administrar. En el momento de este mensaje, swift todavía no permite crear bibliotecas binarias.
Moose
0

Esto es lo que me resolvió el mismo problema.

Tengo un objetivo de aplicación y un objetivo de extensión de iMessage. Luego tuve 2 SDK (el mío), con los que App Target se vincula.

El problema era: mi objetivo de iMessage también estaba usando los 2 SDK míos (proyectos separados), pero no se vinculaba a ellos en Build Phases -> Link Binary With Libraries. Tuve que agregar mis 2 SDK al destino de iMessage allí, para que coincida con el destino de mi aplicación, y ahora se archiva.

Entonces, la moraleja de la historia es: si tiene varios objetivos, como extensiones, asegúrese de que todos sus objetivos estén vinculados con las bibliotecas que necesitan. Pudo compilar e implementar en simulador y dispositivo, pero no archivar.

FranticRock
fuente
0

Actualización: Xcode 9

Las respuestas anteriores no me funcionaron usando Xcode 9, pero esta respuesta funcionó perfectamente para mí. He agregado $(OBJROOT)/UninstalledProducts/$(PLATFORM_NAME)/includea mis "Rutas de búsqueda de encabezado" y Xcode vinculó el encabezado de mi biblioteca estática sin problemas.

Mohammed Abdullatif
fuente
-18

Ahórrese el problema y haga esto = cree una nueva cuenta de usuario en su Mac - abra el proyecto con la nueva cuenta de usuario - todos los problemas desaparecen. Ahorre tiempo y mantenga la cordura. ¡¡Todas esas respuestas nerd no ayudan !!

Buena suerte

Max
fuente