Błąd szybkiego kompilatora: „niemodularny nagłówek w module frameworka”


204

Teraz chciałbym zmigrować moją platformę ObjC do Swift i otrzymałem następujący błąd:

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

Odniesienia dotyczą pliku nagłówkowego, który po prostu definiuje protokół, i używam tego pliku nagłówkowego w niektórych klasach, aby używać tego protokołu.

Wydaje się, że jest związany z funkcją modułu, ale w tej chwili nie jest całkiem jasne, jak to naprawić, czy znasz rozwiązanie?

AKTUALIZACJA:

To jest błąd kompilatora Swift.

AKTUALIZACJA 2:

Szybką poprawką (ale nie rozwiązującą podstawowej przyczyny) jest ustawienie następującego ustawienia na tak: CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = TAK


3
Wygląda na to, że istnieje nowe ustawienie kompilacji „CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES”
Stephan

1
Czy ktoś widział to na opakowaniach publicznych i modułowych? Widzę to w projekcie waniliowym (cocoapods): github.com/CocoaPods/CocoaPods/issues/3092 i dropbox.com/s/trhe5vwhzoa9bf5/…
Chris Conover

Czy ktoś stworzył szybki skrypt, który automatycznie to włącza?
fatuhoku,

@fatuhoku yeah
funroll

Żadne z tych rozwiązań nie działało dla mnie, wygląda na to, że w moim przypadku była to kolizja bolts.framework. Usunięcie go rozwiązało problem: stackoverflow.com/a/33114309/3324388
Aggressor,

Odpowiedzi:


316

Czy twój nagłówek jest publiczny?

Wybierz plik nagłówka w eksploratorze projektów. Następnie w sekcji po prawej stronie w xcode zauważysz, że obok celu znajduje się menu rozwijane. Zmień to z „projektu” na „publiczne”. To zadziałało dla mnie.

nagłówek publiczny


Przyjmuję tę odpowiedź, nawet jeśli jest taka sama, jak powiedziałem.
Stephan

Możesz także przejść do fazy kompilowania nagłówków w swoim frameworku i szybko sprawdzić, które nagłówki są publiczne, projektowe i prywatne.
Jose Ibanez

Nie sądziłem, że to proste zadanie może być rozwiązaniem, ponieważ walczyłem z tym przez ponad godzinę, zanim przybyłem do SO. Oto i oto było DOKŁADNIE rozwiązanie i zadziałało natychmiast.
TMc

1
A jeśli chcę, aby nagłówki te były wewnętrzne?
Raphael

2
To także rozwiązuje mój problem! W moim przypadku mój jeden zasobnik zależny od innego zasobnika nie może go zaimportować z powodu problemu modułowego. Zrobiłem więc kilka nagłówków uwzględnionych jako cel dla innej kapsuły, używając trybu publicznego. I to rozwiązuje problem!
Chen Li Yong,

135

Jest to oczekiwane zachowanie kompilatora i nie bez powodu.

Myślę, że większość ludzi pracujących w tej kwestii jest spowodowane po przełączyć się one od Application Targetcelu Framework Targeti rozpocząć dodawanie nagłówków C i Objective C do frameworka parasol nagłówku spodziewałem się, że mają takie samo zachowanie jak Pomostowych Nagłówek aplikacji , która zachowuje się inaczej. Nagłówek parasolowy jest tak naprawdę przeznaczony dla mieszanej frakcji swift, obj-c, a jej celem jest udostępnienie interfejsów API zewnętrznemu światu, który twoja struktura ma w celu-c lub c. Oznacza to, że nagłówki, które tam umieszczamy, powinny znajdować się w zasięgu publicznym.

Nie należy go używać jako miejsca, które naraża nagłówki Objective-C / C, które nie są częścią twojego frameworka na szybki kod twojego frameworka. Ponieważ w takim przypadku nagłówki te zostaną również udostępnione jako część naszego modułu frameworka zewnętrznemu światu, co często nie jest tym, co chcemy robić, ponieważ psuje modułowość. (I właśnie dlatego opcja Zezwala na modułowe dołączanie w modułach szkieletowych domyślnie NIE )

Aby udostępnić bibliotekę Objective-C / C w twoim szybkim kodzie frameworka, powinniśmy zdefiniować osobny moduł swift dla takiej biblioteki. Następnie import YourLegacyLibrarymożna użyć standardowego swift .

Pokażę to w typowym scenariuszu: osadzenie libxml2w naszych ramach.

1. Najpierw musisz utworzyć module.modulemapplik, który wyglądałby w ten sposób:

W systemie OSX:

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

W systemie iOS:

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

Wszystko, co robi, to to, że zawija nagłówek i wszelkie inne nagłówki, do których się odwołuje, w module swift, dzięki czemu swift będzie mógł następnie wygenerować szybkie powiązania dla tych interfejsów C.

2. Następnie w katalogu projektu xcode utwórz folder SwiftLibXML2i umieść tam ten moduł.modulemap

3. W Ustawieniach kompilacji dodaj $(SDKROOT)/usr/include/libxml2do Ścieżki wyszukiwania nagłówka

4. W Ustawieniach kompilacji dodaj $(SRCROOT)/SwiftLibXML2do Importuj ścieżki

5. W zakładce Ogólne projektu dodaj libxml2.tbddo Linked Frameworks and Libraries .

Teraz zaimportuj ten moduł w razie potrzeby za pomocą:

import SwiftLibXML2

(jeśli chcesz spojrzeć na bardziej kompletny przykład module.map, sugerowałbym powołać się na Dar.moduł module.modulemap na /usr/include/module.modulemap, musisz mieć zainstalowane narzędzia wiersza polecenia Xcode, aby przejść tam, odwołanie Missing / usr / include w OS X El Capitan )


1
Nazwa pliku module.mapjest przestarzała, należy zmienić jej nazwę na module.modulemap clang.llvm.org/docs/Modules.html#attributes
Hyperbole

Jak import SwiftLibXML2w Objective-C? Dzięki!
Itachi

w taki sam sposób jak każdy inny import obj-c: #import <libxml / xpath.h>, ale upewnij się, że zrobiłeś kroki 3-5.
ambientlight

Zrobiliśmy to, ale artefaktu kompilacji nie można przenosić między komputerami: moduł (pod) Objective-C najwyraźniej jest połączony przy użyciu ścieżek bezwzględnych, co powoduje błędy podczas kompilacji, powiedzmy, aplikacji korzystającej z dostarczonego środowiska.
Raphael

błąd jest najprawdopodobniej specyficzny dla twojego procesu kompilacji, jest to tylko definicja modułu, więc języki lvv, które obsługują moduły, mogą współpracować z innymi, nie sądzę, aby samo to mogło wpłynąć na twoje artefakty kompilacji, czy społeczność może mnie poprawić, jeśli ja mylę się
ambientlight

55

Oto jak automatycznie zastosować szybką poprawkę, aby nie trzeba było zmieniać Pods.xcodeprojręcznie po każdym pod install.

Dodaj ten fragment kodu na końcu pliku 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

29

Rozwiązaniem było dla mnie przejście do celu-> kompilacja ustawień-> Zezwól na włączenie modułów niemodułowych w moduły frameworku na TAK!


Współpracował również tutaj z Cocoapods. Nie trzeba robić magii z drugiej odpowiedzi po instalacji kapsuły
brainray

3
Zrobiłem ten krok ... działało przez chwilę .. a teraz nie działa ... Podałem również krok instalacji pod. Ale teraz znowu zawodzi. Coś jeszcze powinienem sprawdzić? Nie widzę GoogleMobileAds.Framework jako opcji zmiany nagłówków na Publiczne.
Michael Rowe,

To mi nie zadziałało. Nadal pojawia się błąd przy analizie składni. Xcode 7.3.1
C0D3

Po wprowadzeniu tej zmiany musiałem zrestartować XCode, aby działał.
John Fowler,

1
Jaki jest wpływ zmiany tego ustawienia?
nr5

15

Chyba mi się to udało. Mam kod modelu, który używa sqlite3 w ramach. W moim przypadku winowajcą był <sqlite3.h>.

Problem polegał na tym, że w moim nagłówku Module / Module.h zaimportowałem nagłówek publiczny, który zaimportował <sqlite3.h>. Rozwiązaniem było ukrycie wszystkich typów sqlite3_xxx i upewnienie się, że nie są widoczne w żadnej publicznej .h. Wszystkie bezpośrednie odniesienia do sqlite3 zostały ustawione jako prywatne lub widoczne dla projektu. Na przykład miałem publiczny singleton, który miał pewne wskaźniki sqlite3_stmt. Przeniosłem je do osobnej klasy, która jest teraz tylko deklaracją forward w tym nagłówku publicznym. Teraz mogę budować.

Nawiasem mówiąc, ustawienie CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES nie działa. Próbowałem ustawić to zarówno w ramach, jak i projekcie zależnym. To obejście było konieczne, chociaż nie jestem pewien, dlaczego.


To całkowicie pomogło! W moim przypadku była to Zasięg.
Daniel Brim

4
Jestem prawie pewien, że jest to rozwiązanie mojego problemu, gdy próbuję włączyć SSZipArchive do mojego modułu frameworka. Nagłówek publiczny imporing <zlib.h> i podaje ten sam błąd. Czy możesz gdzieś opublikować kod źródłowy, ponieważ staram się go uruchomić, ponieważ rozumiem tylko część twojej odpowiedzi ... dzięki!
Bruce

15

W Swift :

1. Zmodyfikuj ustawienia kompilacji projektu Xcode i celów, jak wspomniano poniżej:

Zezwalaj na moduły nieuwzględnione w modułach szkieletowych: Nie

Włącz kod bitowy: Tak

2. Użyj bieżącej najnowszej wersji dostępnej dla GoogleMaps iOS SDK (użyj CocoaPods, aby ją zdobyć):

GoogleMaps (1.10.4)

3. Skomentuj problematyczny import:

//import GoogleMaps

4. Utwórz lub zmodyfikuj mostkowy plik nagłówka, dodając problematyczny import:

[Nazwa twojego projektu 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. Wyczyść i ponownie zbuduj projekt Xcode.


1
To bardzo pomaga! Świetnie współpracuje również z frameworkiem GoogleMobilAds (z Cocoapods)
bluenowhere

Aby uzyskać bardziej szczegółowe informacje na temat tworzenia pliku nagłówka, patrz: stackoverflow.com/a/51227304/529663
lenooh

6

Ta odpowiedź jest nieaktualna.

Podczas importowania frameworków należy zaimportować wszystkie pliki nagłówkowe, które współdzielą zależności z nagłówkiem głównym. Najłatwiejszym sposobem, aby upewnić się, że to zawsze działa, jest zaimportowanie wszystkich nagłówków w folderze „Headers” frameworka na ścieżkę publicznych nagłówków.

wprowadź opis zdjęcia tutaj

Kompilator Swift wykorzystuje te informacje do wygenerowania mapy nie zniekształconych symboli wraz z powiązanymi informacjami o typie.


Wydaje się, że pokonuje to cel posiadania plików Framework, ale zadziałało to dla mnie. Chartboost i RevMob niedawno zaczęły używać plików Framework zamiast zwykłych bibliotek. Kopiowanie wszystkiego z ich nagłówków do moich nagłówków aplikacji rozwiązuje problem.
Jason Short,

Czy to jedyne rozwiązanie? Mam 6 ram i każda z nich ma około 20 nagłówków. Stwarza bałagan. Jakiś zastępca?
vivin

1
Bardziej niż prawdopodbnie. Prawdopodobnie nie jest to już istotne, ponieważ było to obejście błędu Xcode.
seo

6

Nie rób

#import "MyOtherFramework.h"

Robić

#import <MyOtherFramework/MyOtherFramework.h>

3

Plik nagłówka został przydzielony do celu, ale został oznaczony tylko jako widoczny projekt, po prostu zmiana w polu publicznym prowadzi do rozwiązania tego błędu.


Jak dokładnie mogę to zrobić? Mam problem z plikami nagłówkowymi TwitterKit
Vinod Sobale

2

Wiem, że to stare pytanie, ale miałem ten sam problem i nic z góry mi nie pomogło. Mam więc nadzieję, że moja odpowiedź będzie dla kogoś pomocna. W moim przypadku problem dotyczył ustawienia ALWAYS_SEARCH_USER_PATHS. Gdy był ustawiony na ŻADNY projekt nie został zbudowany i działał poprawnie. Ale tak długo, jak jeden z kapsuł wymagał ustawienia TAK, otrzymywałem błąd

Uwzględnij niemodularny nagłówek w module frameworka

Po kilku filiżankach kawy i całodziennych badaniach odkryłem, że zgodnie ze znanymi wydaniami Xcode 7.1 Beta 2 informacje o wydaniu :

• Jeśli pojawi się błąd z informacją „Dołącz nagłówek niemodułowy do modułu frameworka” dla frameworku, który wcześniej skompilował, upewnij się, że ustawienie kompilacji „Zawsze wyszukuj ścieżki użytkownika” jest ustawione na „Nie”. Domyślna wartość to „Tak” tylko ze względów starszych. (22784786)

Używałem XCode 7.3, ale wygląda na to, że ten błąd nie został jeszcze naprawiony.


To mi pomogło! Musiałem zmienić część importu po zmianie na NIE, ale teraz byłem w stanie zaimportować potrzebne ramy!
Pavel Gurov

2

Przełączanie ustawień kompilacji> Zezwalaj na moduły ramowe na TAK na TAK! rozwiązałem ten sam problem dla mnie.


2

Chciałbym również dodać swoje doświadczenie z tym problemem.

Podsumowując:

  • Odpowiedź @ ambientlight jest świetna i rozwiązuje większość problemów.
  • zezwalanie na nagłówki niemodułowe to kolejne rozwiązanie (patrz niektóre odpowiedzi powyżej).
  • oznaczanie nagłówków frameworka jako publicznych (tylko te, które chcesz ujawnić) i importowanie ich w nagłówku parasola.

Oto moje 2 dodatki do powyższych odpowiedzi:

  • dokładnie sprawdź import w swoim projekcie pod kątem nagłówków, które importują twoje frameworki bezpośrednio do nich (zamiast, jeśli to możliwe, używaj deklaracji forward) - nie jest dobrą praktyką dołączanie pliku nagłówka do innego pliku nagłówka; czasami powoduje to problemy, ponieważ jeśli nie zostanie to zrobione poprawnie, może to prowadzić do wielokrotnego dołączania jednego nagłówka i powodować problemy z linkerem.
  • AKTUALIZACJA: upewnij się, że architektura biblioteki i obiektu docelowego, które chcesz połączyć, aby pasowały.
  • i wreszcie, po wykonaniu wszystkich powyższych czynności, wciąż napotykałem ten błąd. Więc wykopałem trochę więcej i znalazłem (na forach programistów Apple, ale zgubiłem link :(), że jeśli umieścisz nagłówki w nagłówku parasola nie w ten sposób <framework/headerName.h>, ale tylko w ten sposób "headerName.h", problem zniknie.

Próbowałem tego ostatniego i do tej pory nie spotkałem się z tym problemem, ale podejrzewam, że to rozwiązanie jest ważne tylko wtedy, gdy zastosowałeś niektóre z najlepszych odpowiedzi (uwaga: na przykład nie wszystkie są ze sobą kompatybilne , podejście modułowe i dopuszczanie nagłówka niemodułowego obejmuje).


1

Miałem właśnie ten problem, gdy włączyłem własną strukturę do projektu. Naprawiono to, umieszczając cały import pliku sqlite3.h w plikach .m, które nie są publiczne .h. Zakładam, że inne biblioteki mogą oznaczać podobne problemy z Xcode.


1

Miałem konkretny problem z Facebook 4.02 sdk i FBSDKCoreKit.

Zrobiłem wszystkie kroki, ale nadal mam błąd dotyczący nagłówka niemodułowego. Przeciągnąłem i upuściłem tylko określony nagłówek z frameworka, aby utworzyć sekcję fazy-> nagłówek.

Następnie automatycznie utworzono kopię nagłówka w nawigatorze projektu u góry.

Usunąłem go z faz kompilacji -> nagłówek, usunąłem nowy plik i działałem dobrze.

Jak zresetowany czy coś.


1

W moim przypadku (Xcode 9 beta 6 - Swift 4 - przy użyciu Cocoapods) zostało to rozwiązane, gdy usunąłem Podfile.lock i katalog Pods i uruchomiłem pod installponownie


1

Ten problem wystąpił po aktualizacji projektu ze swift2 do swift3. Użyłem XCode 8.3.2 do aktualizacji kodu i nie mogłem pozbyć się błędu „niemodularny nagłówek w module frameworka”. Kiedy otworzyłem ten sam projekt w innej wersji XCode (wersja 9.0.1) błąd nie pojawił się.


0

Najczęściej ten błąd jest spowodowany wybraną odpowiedzią, ale ten błąd pojawił się raz przez przypadek podczas przeciągania plików środowiska do mojego nowego folderu projektu. Kliknąłem, aby usunąć frameworki, ale przypadkowo nacisnąłem tylko, aby usunąć „Odwołanie” do frameworków, a nie całkowicie usunąć pliki. W tym momencie, gdy otworzyłem folder projektu w Finderze, zobaczyłem tam pliki takie jak „CoreLocation” i „AudioToolbox”. Usunięcie tych plików z folderu projektu i wyczyszczenie projektu rozwiązało problem.


0

Po zezwoleniu na import elementów niemodularnych możesz spróbować zaimportować ten moduł za pomocą nagłówka mostkowania Objective-C:

#import <YandexMobileMetrica/YandexMobileMetrica.h>

0

Rozwiązałem go usuwając Modulesfolder z frameworka.

  • Przejdź do swojej lokalizacji frameworka, która jest obecna w App Project za pomocą wyszukiwarki

  • Przejdź do Test.frameworkfolderu (w powyższym przypadku będzie SOGraphDB.framework) i Usuń Modulesfolder.

  • Wyczyść i ponownie zbuduj aplikację, rozwiąże to problem.


-1

Miałem ten problem podczas importowania frameworka Parse. Jedynym sposobem, w jaki mogłem to naprawić, było odrzucić wszystkie moje zmiany od czasu ostatniego zatwierdzenia (po prostu usunięcie frameworka i czyszczenie projektu nie działały) i dodanie Parse ponownie (po ponownym pobraniu SDK) z innymi wymaganymi frameworkami.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.