Kesalahan kompiler Swift: “header non-modular di dalam modul kerangka kerja”

204

Sekarang saya ingin memigrasi kerangka kerja ObjC saya ke Swift dan saya mendapat kesalahan berikut:

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

Referensi adalah file header yang hanya mendefinisikan protokol dan saya menggunakan file header ini di beberapa kelas untuk menggunakan protokol ini.

Tampaknya terkait dengan fitur modul tetapi saat ini tidak cukup jelas bagaimana cara memperbaikinya, apakah Anda tahu solusinya?

MEMPERBARUI:

Ini adalah kesalahan kompilasi Swift.

PEMBARUAN 2:

Perbaikan cepat (tetapi tidak menyelesaikan akar permasalahan) adalah untuk menetapkan pengaturan berikut ke yes: CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YA

Stephan
sumber
3
Tampaknya ada pengaturan bangunan baru untuk "CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES"
Stephan
1
Adakah yang melihat ini termasuk yang bersifat publik dan modular? Saya melihat ini dengan proyek vanilla (cocoapods): github.com/CocoaPods/CocoaPods/issues/3092 dan dropbox.com/s/trhe5vwhzoa9bf5/…
Chris Conover
Adakah yang membuat skrip cepat yang memungkinkan ini secara otomatis?
fatuhoku
@fatuhoku yeah
funroll
Tak satu pun dari solusi ini bekerja untuk saya, sepertinya itu adalah baut. Pekerjaan tabrakan dalam kasus saya. Menghapusnya memecahkan masalah: stackoverflow.com/a/33114309/3324388
Aggressor

Jawaban:

316

Apakah tajuk Anda publik?

Pilih file header di penjelajah proyek. Kemudian pada bagian di sebelah kanan dalam xcode, Anda akan melihat ada dropdown di sebelah target. Ubah itu dari "proyek" menjadi "publik". Ini berhasil untuk saya.

tajuk publik

kgreenek
sumber
Saya menerima jawaban ini bahkan sama dengan yang saya nyatakan.
Stephan
Anda juga dapat pergi ke tahap pembuatan header dari kerangka kerja Anda dan dengan cepat melihat header mana yang Publik, Proyek, dan Pribadi.
Jose Ibanez
Saya tidak berpikir tugas sederhana ini mungkin bisa menjadi solusi karena saya telah berjuang dengan ini selama lebih dari satu jam sebelum datang ke sini untuk SO. Lihatlah, ini adalah solusi yang tepat dan langsung bekerja.
TMc
1
Dan bagaimana jika saya ingin header ini internal?
Raphael
2
Ini juga menyelesaikan masalah saya! Dalam kasus saya, satu pod saya yang bergantung pada pod lain tidak dapat mengimpornya karena masalah modular. Jadi saya membuat beberapa header dimasukkan sebagai target untuk pod lain, menggunakan mode publik. Dan itu memecahkan masalah!
Chen Li Yong
135

Ini adalah perilaku kompiler yang diharapkan dan untuk alasan yang sangat bagus.

Saya pikir sebagian besar orang mengalami masalah ini disebabkan setelah mereka beralih dari Application Targetke Framework Targetdan mulai menambahkan header C dan Objective C ke header payung kerangka kerja yang mengharapkannya memiliki perilaku yang sama dengan Bridging Header aplikasi , yang berperilaku berbeda. Header payung sebenarnya dirancang untuk kerangka kerja Swift, obj-c campuran dan tujuannya adalah mengekspos API ke dunia luar yang memiliki kerangka kerja Anda dalam tujuan-c atau c. Itu artinya tajuk yang kami taruh di sana harus ada dalam ruang publik.

Seharusnya tidak digunakan sebagai tempat yang mengekspos header Objective-C / C yang bukan bagian dari kerangka kerja Anda ke kode cepat kerangka kerja Anda. Karena dalam hal ini tajuk ini juga akan diekspos sebagai bagian dari modul kerangka kerja kami ke dunia luar, yang sering kali bukan yang ingin kita lakukan karena merusak modularitas. (Dan itulah mengapa Memungkinkan Non-modular Termasuk dalam Kerangka Modul default untuk TIDAK )

Untuk mengekspos pustaka Objective-C / C ke kode kerangka kerja Anda, kita harus mendefinisikan modul swift terpisah untuk pustaka tersebut. Maka cepat standar import YourLegacyLibrarydapat digunakan.

Biarkan saya menunjukkan ini pada beberapa skenario umum: menanamkan libxml2ke dalam kerangka kerja kami.

1. Pertama-tama Anda perlu membuat module.modulemapfile yang akan terlihat seperti ini:

Untuk kerangka OSX:

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

Untuk kerangka kerja iOS:

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

Yang perlu dilakukan adalah membungkus header dan header lain yang dirujuk di dalam modul swift, sehingga swift kemudian dapat menghasilkan binding cepat untuk antarmuka C ini.

2. Kemudian di direktori proyek xcode Anda, buat folder SwiftLibXML2dan letakkan module.modulemap di sana

3. Dalam Pengaturan Bangun , tambahkan $(SDKROOT)/usr/include/libxml2ke Jalur Pencarian Header

4. Di Bangun Pengaturan , tambahkan $(SRCROOT)/SwiftLibXML2ke Impor Jalur

5. Di bawah tab General Project , tambahkan libxml2.tbdke Linked Frameworks and Libraries .

Sekarang Anda mengimpor modul ini jika diperlukan dengan:

import SwiftLibXML2

(Jika Anda ingin melihat contoh module.map yang lebih lengkap, saya sarankan merujuk modul Darwin.modulemap di /usr/include/module.modulemap, Anda perlu menginstal alat baris perintah Xcode untuk pergi ke sana, referensi Hilang / usr / termasuk dalam OS X El Capitan )

ambientlight
sumber
1
Nama file module.mapsudah tidak digunakan lagi, harus diubah namanya module.modulemap clang.llvm.org/docs/Modules.html#attributes
Hyperbole
Bagaimana import SwiftLibXML2di Objective-C? Terima kasih!
Itachi
cara yang sama seperti impor obj-c lainnya: # impor <libxml / xpath.h> tetapi pastikan Anda melakukan langkah 3-5
ambientlight
Kami melakukan ini, tetapi kemudian artefak build tidak dapat dipindahkan di antara mesin: modul Objective-C (sub) tampaknya ditautkan menggunakan jalur absolut, menyebabkan kesalahan saat mengkompilasi, katakanlah, aplikasi yang menggunakan kerangka kerja yang Anda kirim.
Raphael
kesalahan tersebut kemungkinan besar spesifik untuk proses pembuatan Anda, ini hanya definisi modul sehingga bahasa llvm yang mendukung modul dapat berinteraksi dengan orang lain, saya tidak berpikir itu dapat dengan sendirinya mempengaruhi artefak pembuatan Anda, semoga masyarakat memperbaiki saya jika saya saya salah
ambientlight
55

Berikut cara menerapkan perbaikan cepat secara otomatis sehingga Anda tidak perlu mengubah Pods.xcodeprojsecara manual setelah masing-masing pod install.

Tambahkan potongan ini ke akhir Podfile Anda:

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
sumber
29

Solusi bagi saya adalah untuk pergi pada target-> membangun pengaturan-> Izinkan non-modular termasuk dalam Modul Kerangka beralih ke YA!

Vlad Burlaciuc
sumber
Juga bekerja dengan Cocoapods di sini. Tidak perlu melakukan keajaiban dari jawaban lain setelah menginstal pod
brainray
3
Saya telah melakukan langkah ini .. ini bekerja untuk sementara waktu .. dan sekarang tidak berfungsi ... Saya juga memasukkan langkah pod-install. Tetapi sekarang gagal lagi. Ada lagi yang harus saya periksa? Saya tidak melihat GoogleMobileAds.Framework sebagai opsi untuk mengubah tajuk menjadi Publik.
Michael Rowe
Ini tidak berhasil untuk saya. Masih mendapatkan kesalahan dengan Parse. Xcode 7.3.1
C0D3
Saya harus memulai ulang XCode setelah membuat perubahan ini agar berfungsi.
John Fowler
1
Apa dampak dari mengubah pengaturan ini?
nr5
15

Saya pikir saya bisa mengatasi ini. Saya punya beberapa kode model yang menggunakan sqlite3 dalam suatu framework. Dalam kasus saya, pelakunya adalah <sqlite3.h>.

Masalahnya adalah bahwa di header Module / Module.h saya, saya mengimpor header publik yang mengimpor <sqlite3.h>. Solusinya adalah menyembunyikan semua tipe sqlite3_xxx dan memastikannya tidak terlihat di publik .h. Semua referensi langsung ke sqlite3 dibuat visibilitas pribadi atau proyek. Sebagai contoh, saya memiliki singleton publik yang memiliki beberapa pointer sqlite3_stmt menggantungnya. Saya memindahkan mereka ke kelas terpisah yang sekarang hanya deklarasi maju di header publik itu. Sekarang saya bisa membangun.

Secara kebetulan, pengaturan CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES tidak berfungsi. Saya mencoba mengaturnya baik dalam kerangka kerja dan proyek dependen. Solusi ini diperlukan, meskipun saya tidak yakin mengapa.

Jimmy Dee
sumber
Ini sangat membantu! Dalam kasus saya, itu adalah Reachability.
Daniel Brim
4
Saya cukup yakin ini adalah solusi untuk masalah saya ketika saya mencoba memasukkan SSZipArchive dalam modul framework saya. Header publik menerapkan <zlib.h> dan memberikan kesalahan yang sama. Dapatkah Anda memposting kode sumber Anda di suatu tempat karena saya berjuang untuk membuatnya berfungsi karena saya hanya mengerti sebagian dari jawaban Anda .. terima kasih!
Bruce
15

Dalam Swift :

1. Ubah proyek Xcode Anda dan Pengaturan Bangun target seperti yang disebutkan di bawah ini:

Izinkan Non-modular Termasuk Dalam Modul Kerangka: Tidak

Aktifkan Bitcode: Ya

2. Gunakan versi terbaru saat ini yang tersedia untuk GoogleMaps iOS SDK (gunakan CocoaPods untuk mendapatkannya):

GoogleMaps (1.10.4)

3. Komentari impor yang bermasalah:

//import GoogleMaps

4. Buat atau modifikasi file header bridging Anda, tambahkan impor yang bermasalah:

[Nama Proyek Xcode Anda] -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. Bersihkan dan bangun kembali proyek Xcode Anda.

Raja-Penyihir
sumber
1
Ini sangat membantu! Juga bekerja sangat baik dengan kerangka GoogleMobilAds (dengan Cocoapods)
bluenowhere
untuk informasi lebih lanjut cara membuat file heading, lihat: stackoverflow.com/a/51227304/529663
lenooh
6

Jawaban ini kedaluwarsa.

Saat mengimpor kerangka kerja, Anda harus mengimpor semua file header yang berbagi dependensi dengan header root. Cara termudah untuk memastikan ini selalu berhasil adalah dengan mengimpor semua header di folder "Header" kerangka kerja ke jalur header publik Anda.

masukkan deskripsi gambar di sini

Kompiler Swift menggunakan informasi ini untuk menghasilkan peta simbol yang tidak cacat bersama dengan informasi jenis yang terkait.

seo
sumber
Ini tampaknya mengalahkan tujuan memiliki file Framework, tetapi itu berhasil untuk saya. Chartboost dan RevMob baru-baru ini mulai menggunakan file Framework, bukan hanya libs. Menyalin segala sesuatu dari header mereka ke header aplikasi saya menyelesaikan masalah.
Jason Short
Apakah ini satu-satunya solusi? Saya memiliki 6 kerangka kerja dan masing-masing kerangka kerja memiliki sekitar 20 header. Itu menciptakan kekacauan. Ada alternatif?
vivin
1
Lebih dari mungkin. Ini mungkin tidak lagi relevan karena merupakan solusi dalam bug Xcode.
seo
6

Jangan

#import "MyOtherFramework.h"

Melakukan

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

File header dialokasikan ke target tetapi hanya ditandai sebagai proyek yang terlihat, hanya perubahan untuk mengarahkan publik ke resolusi kesalahan ini.

Stephan
sumber
Bagaimana tepatnya saya bisa melakukan itu? Saya mengalami masalah dengan file tajuk TwitterKit saya
Vinod Sobale
2

Saya tahu bahwa ini adalah pertanyaan lama, tetapi saya memiliki masalah yang sama dan tidak ada yang membantu saya. Jadi saya berharap jawaban saya akan bermanfaat bagi seseorang. Dalam kasus saya masalahnya ada di pengaturan ALWAYS_SEARCH_USER_PATHS. Ketika diatur ke proyek TIDAK dibangun dan bekerja ok. Tetapi sejauh salah satu pod mengharuskannya disetel ke YA, saya menerima pesan kesalahan

Termasuk header non-modular di dalam modul framework

Setelah beberapa cangkir kopi dan meneliti sepanjang hari, saya menemukan bahwa menurut masalah yang diketahui dari catatan rilis Xcode 7.1 Beta 2 :

• Jika Anda mendapatkan kesalahan yang menyatakan "Sertakan tajuk non-modular di dalam modul kerangka kerja" untuk kerangka kerja yang dikompilasi sebelumnya, pastikan pengaturan bangunan "Selalu Cari Jalur Pengguna" disetel ke "Tidak". Standarnya adalah "Ya" hanya untuk alasan warisan. (22784786)

Saya menggunakan XCode 7.3, tetapi sepertinya bug ini belum diperbaiki.

iyuna
sumber
Inilah yang membantu saya! Saya harus mengubah beberapa impor setelah beralih ke TIDAK tetapi sekarang saya dapat mengimpor kerangka kerja yang saya butuhkan!
Pavel Gurov
2

Beralih pengaturan Build> Izinkan non-modular termasuk dalam Modul Kerangka ke YA! memecahkan masalah yang sama untuk saya.

Mohamed TAIEB
sumber
2

Saya ingin menambahkan pengalaman saya dengan masalah ini juga.

Hanya untuk meringkas:

  • @ ambientlight adalah jawaban yang bagus dan itu memperbaiki sebagian besar masalah.
  • memungkinkan tajuk non-modular adalah solusi lain (lihat beberapa jawaban di atas).
  • menandai header kerangka kerja sebagai publik (hanya yang ingin Anda tampilkan) dan mengimpornya di header payung.

Inilah 2 tambahan saya untuk jawaban di atas:

  • hati-hati memeriksa impor dalam proyek Anda untuk header yang mengimpor kerangka kerja Anda secara langsung di dalamnya (alih-alih menggunakan deklarasi maju, jika mungkin) - itu bukan praktik yang baik untuk memasukkan file header di dalam file header lain; kadang-kadang ini menyebabkan masalah, karena jika tidak dilakukan dengan benar ini dapat menyebabkan banyak memasukkan satu header dan membuat masalah linker.
  • PEMBARUAN: pastikan bahwa arsitektur perpustakaan dan target yang ingin Anda tautkan agar sesuai.
  • dan terakhir, setelah melakukan semua hal di atas, saya masih terus menabrak kesalahan itu. Jadi saya menggali sedikit lebih banyak dan menemukan (di forum pengembang apel, tapi saya kehilangan tautan :() bahwa jika Anda memasukkan header di header payung tidak seperti ini <framework/headerName.h>, tetapi hanya seperti ini "headerName.h", masalahnya hilang.

Saya mencoba yang terakhir ini, dan sejauh ini saya tidak mengalami masalah ini lagi, namun saya menduga bahwa solusi ini hanya valid jika Anda telah menerapkan beberapa jawaban teratas (perhatikan: mereka tidak semua kompatibel satu sama lain, misalnya , pendekatan modul dan pemberian header non-modular mencakup).

Georgi Boyadzhiev
sumber
1

Saya memiliki masalah ini ketika memasukkan kerangka kerja saya sendiri dalam sebuah proyek. Memperbaikinya dengan meletakkan semua impor sqlite3.h ke file .m, bukan yang publik .h. Saya berasumsi bahwa perpustakaan lain mungkin menandai masalah serupa dengan Xcode.

Rob Sanders
sumber
1

Saya punya masalah khusus dengan Facebook 4.02 SDK dan FBSDKCoreKit.

Saya melakukan semua langkah tetapi masih kesalahan tentang header non modular. saya seret dan jatuhkan hanya header spesifik dari kerangka kerja untuk membangun bagian header fase->.

Kemudian secara otomatis membuat salinan tajuk pada navigator proyek di bagian atas.

Saya menghapusnya dari fase build -> header dan menghapus file baru dan bekerja dengan baik.

Suka itu ulang atau sesuatu.

Haris
sumber
1

Dalam kasus saya (Xcode 9 beta 6 - Swift 4 - menggunakan Cocoapods) ini diselesaikan ketika saya menghapus Podfile.lock dan direktori Pods dan berlari pod installlagi

m_katsifarakis
sumber
1

Saya mendapat masalah ini setelah memperbarui proyek dari swift2 ke swift3. Saya menggunakan XCode 8.3.2 untuk memperbarui kode dan tidak bisa menghilangkan kesalahan "header non-modular di dalam modul kerangka kerja". Ketika saya membuka proyek yang sama di versi lain XCode (versi 9.0.1) kesalahan tidak muncul.

DevB2F
sumber
0

Paling umum kesalahan ini disebabkan oleh jawaban yang dipilih, namun saya memiliki kesalahan ini muncul sekali secara tidak sengaja ketika menyeret file kerangka kerja ke folder proyek baru saya. Saya mengklik untuk menghapus kerangka kerja tetapi secara tidak sengaja menekan hanya 'Hapus Referensi' ke kerangka kerja daripada benar-benar menghapus file sepenuhnya. Pada titik ini jika saya membuka folder proyek saya di Finder saya melihat file seperti 'CoreLocation' dan 'AudioToolbox' di sana. Menghapus file-file ini dari folder proyek dan membersihkan proyek memperbaiki masalah.

ColossalChris
sumber
0

Setelah mengizinkan untuk mengimpor termasuk non modular, Anda dapat mencoba untuk mengimpor modul itu menggunakan header Objective-C Bridging:

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

Saya menyelesaikannya dengan menghapus Modulesfolder dari framework.

  • Jelajahi lokasi kerangka kerja Anda yang ada di Proyek Aplikasi menggunakan finder

  • Masuk ke Test.frameworkfolder (Dalam kasus di atas akan SOGraphDB.framework) & Hapus Modulesfolder.

  • Bersihkan dan Bangun ulang aplikasi, itu akan menyelesaikan masalah.

Vittal Pai
sumber
-1

Saya mengalami masalah ini mengimpor kerangka Parse. Satu-satunya cara saya bisa memperbaikinya adalah membuang semua perubahan saya sejak komit terakhir saya (hanya menghapus kerangka kerja dan membersihkan proyek tidak berfungsi) dan menambahkan Parse lagi (setelah unduhan baru SDK) dengan kerangka kerja lain yang diperlukan.

amurray4
sumber