Erro do compilador Swift: "cabeçalho não modular dentro do módulo de estrutura"

204

Agora eu gostaria de migrar minha estrutura ObjC para o Swift e recebi o seguinte erro:

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

As referências são para um arquivo de cabeçalho que apenas define um protocolo e eu uso esse arquivo de cabeçalho em algumas classes para usar esse protocolo.

Parece relacionado ao recurso do módulo, mas ainda não está claro como corrigir, você conhece uma solução?

ATUALIZAR:

Este é um erro do compilador Swift.

ATUALIZAÇÃO 2:

Uma solução rápida (mas não solucionando a causa raiz) é definir a seguinte configuração como yes: CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES

Stephan
fonte
3
Parece que há uma nova configuração de compilação de "CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES"
Stephan
1
Alguém viu isso em inclusões públicas e modulares? Eu vejo isso com um projeto de baunilha (CocoaPods): github.com/CocoaPods/CocoaPods/issues/3092 e dropbox.com/s/trhe5vwhzoa9bf5/...
Chris Conover
Alguém criou um script rápido que permite isso automaticamente?
Fatuhoku
@fatuhoku yeah
funroll
Nenhuma dessas soluções funcionou para mim, parece que foi uma colisão de parafusos. Excluí-lo resolveu o problema: stackoverflow.com/a/33114309/3324388
Aggressor

Respostas:

316

O seu cabeçalho é público?

Selecione o arquivo de cabeçalho no explorador de projeto. Em seguida, na seção à direita no xcode, você notará uma lista suspensa ao lado do destino. Mude isso de "projeto" para "público". Isso funcionou para mim.

cabeçalho público

kgreenek
fonte
Eu aceito esta resposta, mesmo que seja a mesma que afirmei.
Stephan
Você também pode ir para a fase de criação de cabeçalhos de sua estrutura e ver rapidamente quais cabeçalhos são públicos, projeto e privado.
21134 Jose Ibanez
Não achei que essa tarefa simples pudesse ser a solução, pois lutei com isso por mais de uma hora antes de vir para a SO. Eis que essa foi EXATAMENTE a solução e funcionou imediatamente.
TMc 31/05
1
E se eu quiser que esses cabeçalhos sejam internos?
Raphael
2
Isso também resolve meu problema! No meu caso, meu único pod que depende de outro pod não pode importá-lo devido a um problema modular. Então, eu fiz alguns cabeçalhos incluídos como destino para outro pod, usando o modo público. E resolve o problema!
Chen Li Yong
135

Esse é um comportamento esperado do compilador e por um motivo muito bom.

Eu acho que a maioria das pessoas que se deparam com esses problemas é causada depois que eles alternam Application Targetpara Framework Targete começam a adicionar cabeçalhos C e Objective C no cabeçalho guarda-chuva da estrutura, esperando que ele tenha o mesmo comportamento do Bridging Header do aplicativo , que se comporta de maneira diferente. O cabeçalho guarda-chuva é realmente designado para uma estrutura mista rápida, obj-c e seu objetivo é expor as APIs para o mundo externo que sua estrutura possui na objetiva-c ou c. Isso significa que os cabeçalhos que colocamos devem estar no âmbito público.

Não deve ser usado como um local que expõe os cabeçalhos de Objective-C / C que não fazem parte da sua estrutura ao código rápido da sua estrutura. Porque, nesse caso, esses cabeçalhos também serão expostos como parte do nosso módulo de estrutura ao mundo exterior, o que geralmente não é o que queremos fazer, pois quebra a modularidade. (E é exatamente por isso que permite a inclusão de módulos não modulares no padrão para NO )

Para expor a biblioteca Objective-C / C ao seu código swift da estrutura, devemos definir um módulo swift separado para essa biblioteca. Em seguida, um swift padrão import YourLegacyLibrarypode ser usado.

Deixe-me demonstrar isso em um cenário típico: incorporação libxml2em nossa estrutura.

1. Você primeiro precisa criar um module.modulemaparquivo com a seguinte aparência:

Para estrutura OSX:

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

Para estrutura iOS:

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

Tudo o que faz é envolver o cabeçalho e quaisquer outros cabeçalhos que ele referenciar dentro do módulo swift, para que o swift possa gerar as ligações rápidas para essas interfaces C.

2. Em seguida, no diretório do projeto xcode, crie uma pasta SwiftLibXML2e coloque este module.modulemap lá

3. Em Configurações de compilação , adicione $(SDKROOT)/usr/include/libxml2aos Caminhos de pesquisa de cabeçalho

4. Em Configurações de compilação , adicione $(SRCROOT)/SwiftLibXML2aos Caminhos de importação

5. Na guia Geral do projeto , adicione libxml2.tbdàs estruturas e bibliotecas vinculadas .

Agora você importa este módulo onde necessário com:

import SwiftLibXML2

(se você quiser procurar um exemplo module.map mais completo, sugiro que você faça referência ao module.modulemap de Darwin em /usr/include/module.modulemap, você precisará ter as ferramentas de linha de comando do Xcode instaladas para ir até lá, referência Missing / usr / include no OS X El Capitan )

luz ambiente
fonte
1
O nome do arquivo module.mapfoi descontinuado, deve ser renomeado como module.modulemap clang.llvm.org/docs/Modules.html#attributes
Hyperbole
Como import SwiftLibXML2no Objective-C? Obrigado!
Itachi
da mesma maneira que qualquer outra importação obj-c: #import <libxml / xpath.h> mas certifique-se de executar as etapas 3 a 5.
ambientlight
Fizemos isso, mas o artefato de construção não pode ser movido entre máquinas: o módulo Objective-C (sub) aparentemente está vinculado usando caminhos absolutos, causando erros ao compilar, digamos, um aplicativo que usa a estrutura que você enviou.
Raphael
é provável que o erro seja específico do seu processo de compilação, esta é apenas uma definição de módulo para que as linguagens llvm que suportam módulos possam interoperar com outras pessoas, não acho que isso possa afetar por si só seus artefatos de compilação, que a comunidade me corrija se eu estou errado
ambientlight 21/03
55

Veja como aplicar automaticamente a correção rápida para que você não precise alterar Pods.xcodeprojmanualmente após cada uma pod install.

Adicione este trecho ao final do seu 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
fonte
29

A solução para mim foi ir em target-> build settings-> Allow include não modular nos Framework Modules, mudar para YES!

Vlad Burlaciuc
fonte
Também trabalhou com Cocoapods aqui. Não há necessidade de fazer a mágica da outra resposta após o pod instalar
brainray
3
Eu fiz esta etapa .. funcionou por um tempo .. e agora não está funcionando ... Eu incluí a etapa de instalação do pod também. Mas agora está falhando novamente. Mais alguma coisa que eu deveria verificar? Não estou vendo o GoogleMobileAds.Framework como uma opção para alterar cabeçalhos para Público.
Michael Rowe
Isso não funcionou para mim. Ainda obtendo o erro com o Parse. Xcode 7.3.1
C0D3 15/06
Eu tive que reiniciar o XCode depois de fazer essa alteração para que ele funcionasse.
John Fowler
1
Qual é o impacto de alterar essa configuração?
NR 5
15

Eu acho que contornei isso. Eu tenho algum código de modelo que usa sqlite3 em uma estrutura. No meu caso, o culpado foi <sqlite3.h>.

O problema era que, no meu cabeçalho Module / Module.h, importei um cabeçalho público que importou <sqlite3.h>. A solução foi ocultar todos os tipos sqlite3_xxx e garantir que eles não estivessem visíveis em nenhum .h público. Todas as referências diretas ao sqlite3 foram tornadas privadas ou visíveis no projeto. Por exemplo, eu tinha um singleton público que tinha alguns ponteiros sqlite3_stmt pendurados nele. Mudei-os para uma classe separada que agora é apenas uma declaração direta nesse cabeçalho público. Agora eu posso construir.

Aliás, a configuração CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES não funcionou. Eu tentei configurá-lo tanto na estrutura quanto no projeto dependente. Esta solução alternativa foi necessária, embora não tenha certeza do motivo.

Jimmy Dee
fonte
Isso totalmente ajudou! No meu caso, foi acessibilidade.
Daniel Brim
4
Tenho certeza de que esta é a solução para o meu problema quando tento incluir o SSZipArchive no meu módulo de estrutura. O cabeçalho público está importando <zlib.h> e está fornecendo o mesmo erro. Você pode postar seu código-fonte em algum lugar porque estou tendo dificuldades para fazê-lo funcionar, pois só entendo parte de sua resposta .. obrigado!
Bruce
15

Em Swift :

1. Modifique o projeto do Xcode e defina as Configurações de compilação conforme mencionado abaixo:

Permitir inclusões não modulares nos módulos da estrutura: Não

Ativar código de bits: Sim

2. Use a versão mais recente atual disponível para o SDK do GoogleMaps iOS (use CocoaPods para obtê-lo):

GoogleMaps (1.10.4)

3. Comente a importação problemática:

//import GoogleMaps

4. Crie ou modifique seu arquivo de cabeçalho de ponte, adicionando a importação problemática:

[Nome do seu projeto do 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. Limpe e recrie seu projeto do Xcode.

O rei da bruxaria
fonte
1
Isso ajuda muito! Também funciona muito bem com a estrutura do GoogleMobilAds (com Cocoapods)
bluenowhere
para obter informações mais detalhadas sobre como criar o arquivo de cabeçalho, consulte: stackoverflow.com/a/51227304/529663
lenooh
6

Esta resposta está desatualizada.

Ao importar estruturas, você deve importar todos os arquivos de cabeçalho que compartilham dependências com o cabeçalho raiz. A maneira mais fácil de garantir que isso sempre funcione é importar todos os cabeçalhos da pasta "Headers" da estrutura para o caminho público dos cabeçalhos.

insira a descrição da imagem aqui

O compilador Swift usa essas informações para gerar um mapa de símbolos não-mutilados junto com suas informações de tipo associadas.

seo
fonte
Isso parece anular o propósito de ter os arquivos do Framework, mas funcionou para mim. O Chartboost e o RevMob começaram recentemente a usar arquivos Framework em vez de apenas bibliotecas. Copiar tudo, dos cabeçalhos para os cabeçalhos do meu aplicativo, resolve o problema.
21815 Jason Short
Essa é a única solução? Eu tenho 6 estruturas e cada estrutura tem cerca de 20 cabeçalhos. Isso cria uma bagunça. Alguma alternativa?
vivin
1
Mais do que provável. Provavelmente isso não é mais relevante, pois foi uma solução alternativa em um bug do Xcode.
seo
6

Não

#import "MyOtherFramework.h"

Faz

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

O arquivo de cabeçalho foi alocado para o destino, mas foi marcado apenas como projeto visível, apenas uma alteração em público levou à resolução desse erro.

Stephan
fonte
Como exatamente eu posso fazer isso? Estou tendo problemas com meus arquivos de cabeçalho TwitterKit
Vinod Sobale
2

Sei que essa é uma pergunta antiga, mas tive o mesmo problema e nada do alto me ajudou. Então, espero que minha resposta seja útil para alguém. No meu caso, o problema estava na configuração ALWAYS_SEARCH_USER_PATHS. Quando foi definido como NO, o projeto foi construído e funcionou bem. Mas, na medida em que um dos pods exigia que fosse definido como SIM, eu estava recebendo um erro

Incluir cabeçalho não modular dentro do módulo de estrutura

Depois de tomar algumas xícaras de café e pesquisar o dia inteiro, descobri que, de acordo com problemas conhecidos das notas de versão do Xcode 7.1 Beta 2 :

• Se você receber um erro informando "Incluir cabeçalho não modular dentro do módulo da estrutura" para uma estrutura compilada anteriormente, verifique se a configuração de criação "Sempre pesquisar caminhos do usuário" está definida como "Não". O padrão é "Sim" apenas por motivos herdados. (22784786)

Eu estava usando o XCode 7.3, mas parece que esse bug ainda não foi corrigido.

iyuna
fonte
Foi isso que me ajudou! Eu tive que mudar algumas importações depois de mudar para NÃO, mas agora consegui importar minha estrutura necessária!
Pavel Gurov
2

Alternando configurações de compilação> Permitir inclusões não modulares nos módulos da estrutura para YES! resolveu o mesmo problema para mim.

Mohamed TAIEB
fonte
2

Gostaria de acrescentar minha experiência com o problema também.

Apenas para resumir:

  • A resposta do @ ambientlight é ótima e corrige a maioria dos problemas.
  • permitir cabeçalhos não modulares é outra solução (veja algumas das respostas acima).
  • marcando os cabeçalhos da estrutura como públicos (apenas os que você deseja expor) e importando-os no cabeçalho do guarda-chuva.

Aqui estão minhas 2 adições às respostas acima:

  • verifique cuidadosamente as importações no seu projeto em busca de cabeçalhos que importam suas estruturas diretamente neles (em vez de usar declaração direta, se possível) - não é uma boa prática incluir um arquivo de cabeçalho dentro de outro arquivo de cabeçalho; Às vezes, isso causa problemas, porque, se não for feito corretamente, pode levar à inclusão múltipla de um cabeçalho e criar problemas no vinculador.
  • UPDATE: verifique se as arquiteturas da biblioteca e do destino que você deseja vinculá-lo correspondem.
  • e, finalmente, depois de fazer tudo o que precede, eu continuava esbarrando nesse erro. Então, eu cavei um pouco mais e descobri (nos fóruns de desenvolvedores da apple, mas perdi o link :() que se você incluir os cabeçalhos no cabeçalho do guarda-chuva não assim <framework/headerName.h>, mas apenas assim "headerName.h", o problema desaparece.

Tentei esta última e, até agora, não tenho mais esse problema, mas suspeito que essa solução seja válida apenas se você tiver aplicado algumas das principais respostas (nota: elas não são todas compatíveis entre si, por exemplo , a abordagem do módulo e a permissão do cabeçalho não modular inclui).

Georgi Boyadzhiev
fonte
1

Eu tive esse problema exato ao incluir minha própria estrutura em um projeto. Corrigido, colocando todas as importações de sqlite3.h em arquivos .m que não sejam públicos .h. Estou assumindo que outras bibliotecas podem sinalizar problemas semelhantes com o Xcode.

Rob Sanders
fonte
1

Eu tive o problema específico com o Facebook 4.02 sdk e o FBSDKCoreKit.

Eu fiz todas as etapas, mas ainda erro sobre o cabeçalho não modular. Eu arrasto e solto apenas o cabeçalho específico da estrutura para criar fases-> seção de cabeçalho.

Em seguida, criou automaticamente uma cópia do cabeçalho no navegador do projeto na parte superior.

Eu o removi das fases de construção -> cabeçalho e excluí o novo arquivo e funcionou bem.

Como redefinido ou algo assim.

Haris
fonte
1

No meu caso (Xcode 9 beta 6 - Swift 4 - usando Cocoapods), isso foi resolvido quando eu excluí o Podfile.lock e o diretório Pods e executei pod installnovamente

m_katsifarakis
fonte
1

Recebi esse problema depois de atualizar um projeto do swift2 para o swift3. Eu estava usando o XCode 8.3.2 para atualizar o código e não consegui me livrar do erro "cabeçalho não modular dentro do módulo de estrutura". Quando abri o mesmo projeto em outra versão do XCode (versão 9.0.1), o erro não apareceu.

DevB2F
fonte
0

Geralmente, esse erro é causado pela resposta escolhida, mas esse erro ocorreu uma vez por acidente ao arrastar arquivos de estrutura para a minha nova pasta de projeto. Cliquei para excluir as estruturas, mas pressionei acidentalmente apenas para 'Remover referência' nas estruturas, em vez de excluir os arquivos completamente. Nesse ponto, se eu abri minha pasta de projeto no Finder, vi arquivos como 'CoreLocation' e 'AudioToolbox' lá. A exclusão desses arquivos da pasta do projeto e a limpeza do projeto corrigiram o problema.

ColossalChris
fonte
0

Depois de permitir a importação de inclusões não modulares, você pode tentar importar esse módulo usando o cabeçalho Objective-C Bridging:

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

Eu resolvi removendo a Modulespasta da estrutura.

  • Navegue até o local da estrutura presente no App Project usando o finder

  • Vá para dentro da Test.frameworkpasta (no caso acima será SOGraphDB.framework) e apague a Modulespasta.

  • Limpe e re Construa o aplicativo, ele resolverá o problema.

Vittal Pai
fonte
-1

Eu tive esse problema ao importar a estrutura do Parse. A única maneira de corrigir isso foi descartar todas as minhas alterações desde a minha última confirmação (simplesmente excluir a estrutura e limpar o projeto não funcionou) e adicionar o Parse novamente (após um novo download do SDK) com suas outras estruturas necessárias.

amurray4
fonte