Error del compilador Swift: "encabezado no modular dentro del módulo marco"

204

Ahora me gustaría migrar mi marco ObjC a Swift y recibí el siguiente error:

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

Las referencias son a un archivo de encabezado que solo define un protocolo y yo uso este archivo de encabezado en algunas clases para usar este protocolo.

Parece estar relacionado con la función del módulo, pero por el momento no está muy claro cómo solucionarlo, ¿conoce una solución?

ACTUALIZAR:

Este es un error del compilador Swift.

ACTUALIZACIÓN 2:

Una solución rápida (pero no resolver la causa raíz) es establecer la siguiente configuración en sí: CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES

Stephan
fuente
3
Parece que hay una nueva configuración de compilación para "CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES"
Stephan
1
¿Alguien ha visto esto en incluye que son públicos y modulares? Veo esto con un proyecto de vainilla (cocoapods): github.com/CocoaPods/CocoaPods/issues/3092 y dropbox.com/s/trhe5vwhzoa9bf5/…
Chris Conover
¿Alguien ha hecho un script rápido que lo habilita automáticamente?
fatuhoku
@fatuhoku
funroll
Ninguna de estas soluciones funcionó para mí, en mi caso parece que fue una colisión de pernos. Eliminarlo resolvió el problema: stackoverflow.com/a/33114309/3324388
Aggressor

Respuestas:

316

¿Tu encabezado es público?

Seleccione el archivo de encabezado en el explorador de proyectos. Luego, en la sección de la derecha en xcode, notará que hay un menú desplegable junto al objetivo. Cambie eso de "proyecto" a "público". Esto funcionó para mí.

encabezado público

kgreenek
fuente
Acepto esta respuesta, incluso si es la misma que dije.
Stephan
También puede ir a la fase de compilación de Encabezados de su marco y ver rápidamente qué encabezados son Público, Proyecto y Privado.
José Ibáñez
No pensé que esta simple tarea podría ser la solución, ya que había luchado con esto durante más de una hora antes de venir a SO. He aquí que esta era EXACTAMENTE la solución y funcionó de inmediato.
TMc
1
¿Y si quiero que estos encabezados sean internos?
Raphael
2
¡Esto también resuelve mi problema! En mi caso, mi pod que depende de otro pod no puede importarlo debido a un problema modular. Así que hice algunos encabezados incluidos como destino para otro pod, usando el modo público. ¡Y resuelve el problema!
Chen Li Yong
135

Este es un comportamiento esperado del compilador y por una muy buena razón.

Creo que la mayoría de las personas que se encuentran con estos problemas se deben a que cambian de Application Targetuna Framework Targety comienzan a agregar encabezados C y Objective C en el encabezado general del marco esperando que tenga el mismo comportamiento que el Encabezado de puente de la aplicación , que se comporta de manera diferente. El encabezado general está diseñado para un marco obj-c mixto rápido y su propósito es exponer las API al mundo exterior que su marco tiene en el objetivo-c o c. Eso significa que los encabezados que colocamos allí deben estar en el ámbito público.

No debe usarse como un lugar que exponga los encabezados de Objective-C / C que no son parte de su marco al código rápido de su marco. Porque en ese caso, estos encabezados también estarán expuestos como parte de nuestro módulo marco al mundo exterior, que a menudo no es lo que queremos hacer, ya que rompe la modularidad. (Y esa es exactamente la razón por la cual la opción No incluye modular incluye en los módulos de marco el valor predeterminado es NO )

Para exponer la biblioteca Objective-C / C a su código swift marco, debemos definir un módulo swift separado para dicha biblioteca. Entonces import YourLegacyLibraryse puede usar un swift estándar .

Permítanme demostrar esto en un escenario típico: incrustarlo libxml2en nuestro marco.

1. Primero debe crear un module.modulemaparchivo que se vea de esta manera:

Para el marco OSX:

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

Para el marco de iOS:

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

Todo lo que hace es envolver el encabezado y cualquier otro encabezado al que haga referencia dentro del módulo swift, para que swift pueda generar los enlaces rápidos para estas interfaces C.

2. Luego, en el directorio del proyecto xcode, cree una carpeta SwiftLibXML2y coloque este module.modulemap allí

3. En Configuración de compilación , agregue $(SDKROOT)/usr/include/libxml2a las rutas de búsqueda de encabezado

4. En Configuración de compilación , agregue $(SRCROOT)/SwiftLibXML2a Importar rutas

5. En la pestaña General del proyecto , agregue libxml2.tbda Marcos vinculados y Bibliotecas .

Ahora importa este módulo donde sea necesario con:

import SwiftLibXML2

(si desea buscar un módulo más completo, ejemplo de mapa, sugeriría hacer referencia al módulo de módulo de Darwin en /usr/include/module.modulemap, necesitaría tener instaladas las herramientas de línea de comandos de Xcode para ir allí, referencia Falta / usr / incluir en OS X El Capitan )

luz ambiental
fuente
1
El nombre del archivo module.mapestá en desuso, debe module.modulemap cambiarse de
Hyperbole
¿Cómo import SwiftLibXML2en Objective-C? ¡Gracias!
Itachi
de la misma manera que cualquier otra importación de obj-c: #import <libxml / xpath.h> pero asegúrese de haber realizado los pasos 3-5.
luz ambiental
Hicimos esto, pero luego el artefacto de compilación no se puede mover entre máquinas: el módulo (sub) Objective-C aparentemente está vinculado mediante rutas absolutas, lo que provoca errores al compilar, por ejemplo, una aplicación que utiliza el marco que envió.
Raphael
el error probablemente sea específico de su proceso de compilación, esta es solo una definición de módulo para que los lenguajes llvm que admiten módulos puedan interoperar con otros, no creo que pueda afectar por sí mismo sus artefactos de compilación, que la comunidad me corrija si yo estoy equivocado
luz ambiental
55

Aquí se explica cómo aplicar automáticamente la solución rápida para que no tenga que cambiar Pods.xcodeprojmanualmente después de cada uno pod install.

Agregue este fragmento al final de su 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
funroll
fuente
29

La solución para mí fue ir a destino-> configuración de compilación-> Permitir inclusiones no modulares en los Módulos de Framework ¡cambie a SÍ!

Vlad Burlaciuc
fuente
También trabajé con Cocoapods aquí. No es necesario hacer la magia de la otra respuesta después de la instalación del pod
brainray
3
He hecho este paso ... funcionó durante un tiempo ... y ahora no funciona ... También incluí el paso de instalación de pod. Pero ahora está fallando nuevamente. ¿Algo más que deba verificar? No veo GoogleMobileAds.Framework como una opción para cambiar los encabezados a Público.
Michael Rowe
Esto no funcionó para mí. Todavía obtengo el error con Parse. Xcode 7.3.1
C0D3
Tuve que reiniciar XCode después de hacer este cambio para que funcione.
John Fowler
1
¿Cuál es el impacto de cambiar esta configuración?
nr5
15

Creo que lo solucioné. Tengo un código modelo que usa sqlite3 en un marco. En mi caso, el culpable fue <sqlite3.h>.

El problema era que en mi encabezado Module / Module.h, importé un encabezado público que importó <sqlite3.h>. La solución fue ocultar todos los tipos sqlite3_xxx y asegurarse de que no fueran visibles en ningún público .h. Todas las referencias directas a sqlite3 se hicieron privadas o visibilidad del proyecto. Por ejemplo, tenía un singleton público que tenía algunos punteros sqlite3_stmt colgando de él. Los moví a una clase separada que ahora es solo una declaración hacia adelante en ese encabezado público. Ahora puedo construir.

Por cierto, la configuración CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES no funcionó. Intenté configurarlo tanto en el marco como en el proyecto dependiente. Esta solución fue necesaria, aunque no estoy seguro de por qué.

Jimmy Dee
fuente
Esto ayudó totalmente! En mi caso, fue alcanzable.
Daniel Brim
44
Estoy bastante seguro de que esta es la solución a mi problema cuando trato de incluir SSZipArchive en mi módulo marco. El encabezado público está importando <zlib.h> y está dando el mismo error. ¿Puedes publicar tu código fuente en algún lugar porque estoy luchando para que funcione ya que solo entiendo parte de tu respuesta ... gracias!
Bruce
15

En Swift :

1. Modifique la configuración de compilación de su proyecto Xcode y objetivos como se menciona a continuación:

Permitir inclusiones no modulares en módulos de estructura: no

Habilitar código de bits: sí

2. Use la última versión actual disponible para GoogleMaps iOS SDK (use CocoaPods para obtenerlo):

GoogleMaps (1.10.4)

3. Comente la importación problemática:

//import GoogleMaps

4. Cree o modifique su archivo de encabezado de puente, agregando la importación problemática:

[Su nombre de proyecto 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. Limpie y reconstruya su proyecto Xcode.

Rey Mago
fuente
1
Esto ayuda mucho! También funciona muy bien con el marco GoogleMobilAds (con Cocoapods)
bluenowhere
Para obtener información más detallada sobre cómo crear el archivo de encabezado, consulte: stackoverflow.com/a/51227304/529663
lenooh
6

Esta respuesta está desactualizada.

Al importar marcos, debe importar todos los archivos de encabezado que comparten dependencias con el encabezado raíz. La forma más fácil de garantizar que esto siempre funcione es importar todos los encabezados de la carpeta "Encabezados" del marco en la ruta de los encabezados públicos.

ingrese la descripción de la imagen aquí

El compilador Swift utiliza esta información para generar un mapa de símbolos no mutilados junto con su información de tipo asociada.

seo
fuente
Esto parece anular el propósito de tener los archivos de Framework, pero funcionó para mí. Chartboost y RevMob han comenzado recientemente a usar archivos Framework en lugar de solo libs. Copiar todo, desde sus encabezados a los encabezados de mi aplicación, resuelve el problema.
Jason Short
¿Es esta la única solución? Tengo 6 marcos y cada marco tiene alrededor de 20 encabezados. Se crea un desastre. Cualquier alternativa?
vivin
1
Más que probable. Esto probablemente ya no sea relevante, ya que era una solución alternativa en un error de Xcode.
seo
6

No

#import "MyOtherFramework.h"

Hacer

#import <MyOtherFramework/MyOtherFramework.h>
hfossli
fuente
3

El archivo de encabezado se asignó al destino, pero solo se marcó como proyecto visible, solo un cambio en público condujo a la resolución de este error.

Stephan
fuente
¿Cómo puedo hacer eso exactamente? Tengo problemas con los archivos de encabezado de TwitterKit
Vinod Sobale
2

Sé que esta es una vieja pregunta, pero tuve el mismo problema y nada de lo anterior me ayudó. Así que espero que mi respuesta sea útil para alguien. En mi caso, el problema estaba en la configuración ALWAYS_SEARCH_USER_PATHS. Cuando se estableció en NO, el proyecto se construyó y funcionó bien. Pero en la medida en que uno de los pod requirió que se estableciera en YES, recibí un error

Incluye encabezado no modular dentro del módulo marco

Después de un par de tazas de café y todo el día investigando descubrí que de acuerdo con los problemas conocidos de Xcode 7.1 Beta 2 notas de lanzamiento :

• Si recibe un error que dice "Incluir encabezado no modular dentro del módulo de marco" para un marco que se compiló previamente, asegúrese de que la configuración de compilación "Buscar siempre rutas de usuario" esté establecida en "No". El valor predeterminado es "Sí" solo por motivos heredados. (22784786)

Sin embargo, estaba usando XCode 7.3, pero parece que este error aún no se ha solucionado.

iyuna
fuente
¡Esto es lo que me ayudó! Tuve que cambiar algunas importaciones después de cambiar a NO, ¡pero ahora pude importar mi marco necesario!
Pavel Gurov
2

Cambiar la configuración de compilación> Permitir inclusiones no modulares en los módulos de marco a resolvió el mismo problema para mí.

Mohamed TAIEB
fuente
2

También me gustaría agregar mi experiencia con el problema.

Solo para resumir:

  • La respuesta de @ ambientlight es excelente y soluciona la mayoría de los problemas.
  • permitir encabezados no modulares es otra solución (ver algunas de las respuestas anteriores).
  • marcar los encabezados del marco como públicos (solo los que desea exponer) e importarlos en el encabezado general.

Aquí están mis 2 adiciones a las respuestas anteriores:

  • verifique cuidadosamente las importaciones en su proyecto para los encabezados que importan sus marcos directamente en ellos (en lugar de usar la declaración hacia adelante, si es posible); no es una buena práctica incluir un archivo de encabezado dentro de otro archivo de encabezado; a veces esto causa problemas, porque si no se hace correctamente, esto puede llevar a la inclusión múltiple de un encabezado y crear problemas de enlazador.
  • ACTUALIZACIÓN: asegúrese de que las arquitecturas de la biblioteca y la del destino que desea vincular coincidan.
  • y, por último, después de hacer todo lo anterior, seguí tropezando con ese error. Entonces cavé un poco más y encontré (en los foros de desarrolladores de Apple, pero perdí el enlace :() que si incluyes los encabezados en el encabezado general no de esta manera <framework/headerName.h>, sino solo así "headerName.h", el problema desaparece.

Probé esta última, y ​​hasta ahora no he experimentado este problema, sin embargo, sospecho que esta solución es válida solo si ha aplicado algunas de las respuestas principales (nota: no todas son compatibles entre sí, por ejemplo , el enfoque del módulo y la posibilidad de encabezado no modular incluye).

Georgi Boyadzhiev
fuente
1

Tuve este problema exacto al incluir mi propio marco en un proyecto. Se solucionó colocando todas las importaciones de sqlite3.h en archivos .m no en archivos públicos .h. Supongo que otras bibliotecas pueden marcar problemas similares con Xcode.

Rob Sanders
fuente
1

Tuve el problema específico con Facebook 4.02 sdk y FBSDKCoreKit.

Hice todos los pasos pero aún error sobre el encabezado no modular. Arrastro y suelto solo el encabezado específico del marco para construir fases-> sección de encabezado.

Luego, creó automáticamente una copia del encabezado en el navegador de proyectos en la parte superior.

Lo eliminé de las fases de compilación -> encabezado y eliminé el nuevo archivo y funcionó bien.

Como reseteado o algo así.

Haris
fuente
1

En mi caso (Xcode 9 beta 6 - Swift 4 - usando Cocoapods) esto se resolvió cuando he eliminado Podfile.lock y vainas directorio y corrí pod installde nuevo

m_katsifarakis
fuente
1

Tengo este problema después de actualizar un proyecto de swift2 a swift3. Estaba usando XCode 8.3.2 para actualizar el código y no pude deshacerme del error "encabezado no modular dentro del módulo marco". Cuando abrí el mismo proyecto en otra versión de XCode (versión 9.0.1) el error no apareció.

DevB2F
fuente
0

Lo más común es que este error sea causado por la respuesta elegida, sin embargo, este error apareció una vez por accidente al arrastrar archivos de marco a mi nueva carpeta de proyecto. Hice clic para eliminar los marcos, pero accidentalmente presioné para 'Eliminar referencia' a los marcos en lugar de eliminar realmente los archivos por completo. En este punto, si abría mi carpeta de proyectos en Finder, veía archivos como 'CoreLocation' y 'AudioToolbox' allí. Eliminar estos archivos de la carpeta del proyecto y limpiar el proyecto solucionó el problema.

ColosalChris
fuente
0

Después de permitir importar las inclusiones no modulares, puede intentar importar ese módulo utilizando el encabezado de Objective-C Bridging:

#import <YandexMobileMetrica/YandexMobileMetrica.h>
Yuri Korshev
fuente
0

Lo resolví eliminando la Modulescarpeta del marco.

  • Navegue hasta su ubicación de marco que está presente en el Proyecto de aplicación utilizando el buscador

  • Vaya dentro de la Test.frameworkcarpeta (en el caso anterior será SOGraphDB.framework) y elimine la Modulescarpeta.

  • Limpie y vuelva a compilar la aplicación, resolverá el problema.

Vittal Pai
fuente
-1

Tuve este problema al importar el marco Parse. La única forma en que pude solucionarlo fue descartar todos mis cambios desde mi último commit (simplemente eliminar el marco y limpiar el proyecto no funcionó) y agregar Parse nuevamente (después de una nueva descarga del SDK) con sus otros marcos requeridos.

amurray4
fuente