Untuk menautkan program macOS native, setiap irisan pustaka yang dipilih harus sesuai dengan arsitektur CPU dan platform Apple, serta memiliki ABI bahasa yang kompatibel. Panduan ini menunjukkan cara membangun dan memeriksa pustaka C kecil yang digunakan oleh alat baris perintah desktop C++.
Tugas konkretnya adalah menghasilkan executable macOS dari kode sumber lokal dan mendiagnosis dependensi native yang tidak kompatibel. Contoh ini menggunakan aritmetika bilangan bulat sintetis, tidak memerlukan pustaka yang diunduh, dan memisahkan keluaran khusus arsitektur.
Apa saja yang harus cocok sebelum pustaka native dapat ditautkan?
Periksa tiga hal secara terpisah: arsitektur, platform, dan antarmuka biner ant bahasa. Spesifikasi target Clang mencakup lebih dari prosesor; target dan lingkungannya memengaruhi pembuatan kode dan pemilihan pustaka. Dependensi juga harus dibangun untuk target yang dimaksud. Kompilasi silang menggunakan Clang.
| Pemeriksaan | Pertanyaan untuk tugas macOS ini | Arti ketidakcocokan |
|---|---|---|
| Arsitektur CPU | Apakah dependensi berisi irisan arm64 atau x86_64 yang ditautkan? |
Dapatkan atau bangun arsitektur yang hilang. |
| Platform Apple | Apakah irisan tersebut dibangun untuk macOS native? | Dapatkan build macOS; build iOS atau Simulator adalah varian yang berbeda. |
| ABI bahasa | Apakah deklarasi, konvensi pemanggilan, dan runtime yang diperlukan sudah sesuai? | Perbaiki antarmuka atau gunakan jalur interoperabilitas yang didukung oleh bahasa tersebut. |
Daftar arsitektur tidak dapat menjawab pertanyaan tentang platform. Format Mach-O Apple mencatat informasi CPU secara terpisah dari informasi build platform, serta menetapkan pengenal platform yang berbeda untuk macOS, iOS, Mac Catalyst, dan iOS Simulator. Karena itu, dependensi yang hanya dideskripsikan sebagai arm64 perlu diperiksa lebih lanjut. Definisi format Mach-O Apple.
Untuk contoh ini, kontrak build yang dimaksud adalah macOS native, target deployment macOS 13.0, dan satu build untuk setiap arsitektur. Pustaka C menyediakan antarmuka C; executable menggunakan C++17. Versi ini adalah pilihan ilustratif, bukan persyaratan minimum universal untuk perangkat lunak Mac.
Bangun contoh macOS lengkap dengan target eksplisit
Gunakan Mac dengan instalasi Xcode terkini yang dipilih untuk pengembangan baris perintah. Apple mendokumentasikan xcrun sebagai mekanisme untuk menemukan atau menjalankan alat di instalasi pengembang yang dipilih. Periksa pilihan tersebut sebelum menyelidiki perubahan kode sumber. FAQ Membangun dari Baris Perintah dengan Xcode.
Perintah di bawah dirancang untuk Bash di macOS. Perintah tersebut telah diperiksa, tetapi tidak dijalankan di sini karena lingkungan riset menggunakan Linux dan tidak memiliki toolchain Apple.
xcode-select --print-path
xcrun --sdk macosx --find clang
xcrun --sdk macosx --find clang++
xcrun --sdk macosx --show-sdk-path
Jika pemeriksaan ini gagal, atasi terlebih dahulu pemilihan atau instalasi alat pengembang. Build memerlukan SDK macOS selain compiler. SDK menyediakan header dan pustaka platform yang digunakan untuk membangun produk. Referensi Pengaturan Build Xcode: SDK Dasar.
Buat file kode sumber
Jalankan blok penyiapan ini di Bash. Blok ini membuat direktori sementara baru dan mencetak lokasinya, sehingga file proyek yang sudah ada tidak tersentuh. Lanjutkan dengan blok-blok berikutnya di shell yang sama.
set -euo pipefail
example_dir="$(mktemp -d "${TMPDIR:-/tmp}/mac-link-demo.XXXXXX")"
cd "$example_dir"
printf 'Example directory: %s\n' "$example_dir"
mkdir -p include src build/arm64 build/x86_64
cat > include/tile.h <<'EOF'
#ifndef TILE_H
#define TILE_H
#ifdef __cplusplus
extern "C" {
#endif
int tile_total(int rows, int columns);
#ifdef __cplusplus
}
#endif
#endif
EOF
cat > src/tile.c <<'EOF'
#include "tile.h"
int tile_total(int rows, int columns)
{
return rows * columns;
}
EOF
cat > src/main.cpp <<'EOF'
#include <cstdio>
#include "tile.h"
int main()
{
const int total = tile_total(3, 4);
std::printf("Tiles: %d\n", total);
return total == 12 ? 0 : 1;
}
EOF
Header tersebut mendeklarasikan linkage bahasa C saat translation unit C++ menyertakannya. Ini mencegah pemanggil C++ meminta nama fungsi C++ yang di-mangle secara berbeda. FAQ C++ juga menyarankan agar compiler C++ mengarahkan proses tautan akhir supaya pustaka yang diperlukan ikut disertakan. FAQ C++ Standar: Cara mencampur C dan C++.
Kompilasi, arsipkan, dan tautkan setiap arsitektur
Blok berikut membangun kedua varian macOS. Untuk setiap arsitektur, blok ini meneruskan target dan SDK yang sama ke kompilasi pustaka dan penautan executable. Clang mendokumentasikan -c sebagai opsi untuk menghasilkan file objek; tanpa opsi pemilihan tahap, driver-nya melanjutkan ke proses penautan. Panduan perintah compiler Clang.
mac_sdk="$(xcrun --sdk macosx --show-sdk-path)"
for cpu in arm64 x86_64; do
mac_target="${cpu}-apple-macos13.0"
xcrun --sdk macosx clang \
-target "$mac_target" -isysroot "$mac_sdk" \
-std=c17 -Wall -Wextra -Werror \
-I include -c src/tile.c \
-o "build/$cpu/tile.o"
xcrun ar rcs "build/$cpu/libtile.a" "build/$cpu/tile.o"
xcrun --sdk macosx clang++ \
-target "$mac_target" -isysroot "$mac_sdk" \
-std=c++17 -stdlib=libc++ -Wall -Wextra -Werror \
-I include src/main.cpp "build/$cpu/libtile.a" \
-o "build/$cpu/tile-demo"
done
Di sini, -target memilih arsitektur dan target deployment macOS, sedangkan -isysroot menyediakan root SDK. Keduanya merupakan input terpisah. Jalur arsip yang ditentukan secara eksplisit juga memperjelas dependensi yang dipilih dalam perintah. Panduan kompilasi silang Clang, Referensi argumen baris perintah Clang.
Perintah ar rcs mengemas objek yang telah dikompilasi ke dalam arsip statis dan menyediakan indeks simbol. Pengarsipan mengemas objek yang sudah ada; proses ini tidak mengompilasinya untuk target lain. LLVM mendokumentasikan operasi arsip dan kompatibilitasnya dengan implementasi ar lainnya. Dokumentasi pengarsip LLVM.
Input contoh 3 dan 4 seharusnya menghasilkan Tiles: 12. Fungsi kecil ini hanya contoh penautan; antarmukanya tidak menetapkan perilaku untuk sembarang dimensi yang hasil kalinya melampaui rentang int.
Bagaimana cara memeriksa arsitektur, platform, dan simbol?
Periksa executable, pustaka, atau file objek yang sebenarnya. Apple mendokumentasikan lipo -archs untuk mencantumkan arsitektur dan menyatakan bahwa executable aplikasi berada di dalam direktori Contents/MacOS/ pada bundelnya. Membangun biner macOS universal.
xcrun lipo -archs build/arm64/tile-demo
xcrun lipo -archs build/x86_64/tile-demo
xcrun otool -l build/arm64/tile.o
xcrun otool -l build/arm64/tile-demo
xcrun nm -g build/arm64/libtile.a
Dua perintah pertama seharusnya menunjukkan arsitekturnya masing-masing. Untuk memeriksa platform, periksa perintah load yang dicetak oleh otool -l; llvm-otool yang kompatibel dari LLVM mendokumentasikan opsi yang sama. Alat penampil Mach-O LLVM.
Cari LC_BUILD_VERSION. platform-nya harus menunjukkan macOS, dan minos mencatat versi minimum sistem operasi. Kolom sdk terpisah. Beberapa biner lama menggunakan perintah LC_VERSION_MIN_* sebagai gantinya. Definisi format Apple mendokumentasikan kedua representasi tersebut, termasuk pengenal platform macOS 1. Struktur versi build Mach-O.
Untuk pustaka statis, periksa objek anggotanya alih-alih menganggap pembungkus arsip sebagai bukti kompatibilitas platform. Contoh ini mempertahankan tile.o untuk keperluan tersebut. Untuk arsip yang belum dikenal, gunakan xcrun ar t untuk mencantumkan anggotanya dan periksa di direktori kerja terpisah. LLVM mendokumentasikan operasi pencantuman dan ekstraksi arsip. Dokumentasi pengarsip LLVM.
Terakhir, periksa simbol. Pustaka contoh seharusnya mendefinisikan _tile_total pada Mach-O. Dalam keluaran nm tradisional, T menunjukkan simbol kode global dan U menunjukkan referensi yang belum terdefinisi. Definisi dan referensi merupakan bukti yang berbeda. Dokumentasi tabel simbol LLVM.
Gunakan urutan diagnosis ini untuk menentukan tindakan selanjutnya:
- Irisan CPU yang diperlukan tidak ada: bangun ulang dependensi untuk arsitektur tersebut atau dapatkan biner yang sesuai.
- CPU cocok tetapi platform berbeda: dapatkan varian macOS native. Mengubah arsitektur pemanggil tidak membuktikan kompatibilitas platform.
- CPU dan platform cocok tetapi fungsi belum terselesaikan: bandingkan fungsi yang dideklarasikan dengan simbol yang diekspor pustaka dan pastikan arsip yang dimaksud tercantum dalam perintah tautan.
- Nama berbeda antara C dan C++: perbaiki linkage bahasa di header bersama, lalu bangun ulang pemanggil.
- Versi deployment berbeda: periksa versi minimum dependensi dan bangun ulang untuk target deployment yang dimaksud jika didukung, atau naikkan persyaratan aplikasi secara sengaja.
Urutan ini merupakan panduan pengambilan keputusan yang disusun berdasarkan dokumentasi target, Mach-O, dan linkage di atas. Urutan ini memisahkan kode mesin yang hilang dari metadata platform yang tidak kompatibel dan masalah antarmuka bahasa, sehingga setiap build ulang menangani temuan tertentu.
Apa yang berubah saat Swift memanggil pustaka native?
CPU dan platform yang cocok tidak membuat setiap antarmuka bahasa dapat dipanggil. Swift mendukung interoperabilitas C secara default; interoperabilitas C++ langsung harus diaktifkan dan hanya mendukung subset fitur C++ yang terdokumentasi. Header yang menghadap C dalam contoh ini menyediakan salah satu pilihan antarmuka yang didukung, asalkan build Swift mengimpornya melalui mekanisme header atau modul yang dikonfigurasi. Mencampur Swift dan C++.
Untuk antarmuka C++ langsung, Swift mendokumentasikan -cxx-interoperability-mode=default untuk build baris perintah, modul Clang untuk mengimpor header, dan -Xcc untuk meneruskan pengaturan importer C++. Konfigurasi impor dan penautan implementasi yang telah dikompilasi tetap menjadi persyaratan build yang terpisah. Menyiapkan Proyek Swift dan C++ dengan Bahasa Campuran.
Patuhi batasan yang terdokumentasi: interoperabilitas C++ memerlukan Swift 5.9 atau lebih baru dan C++14 atau lebih baru. Kode Swift dan C++ campuran harus menggunakan pustaka standar C++ yang sama; platform Apple menggunakan libc++. Pemanggilan Swift dari C++ memerlukan antarmuka yang dihasilkan dan compiler Clang yang didukung. Tipe referensi C++ yang diimpor juga memiliki persyaratan deployment macOS 13.3 tambahan. Periksa API secara spesifik terhadap dokumentasi kompatibilitas terkini sebelum memilih jalur ini. Fitur dan Batasan Interoperabilitas C++ yang Didukung.
Kapan sebaiknya Anda menggunakan biner universal atau XCFramework?
Untuk executable yang hanya ditujukan bagi macOS ini, gabungkan dua build macOS yang telah selesai menjadi biner universal. Apple mendokumentasikan kompilasi dan penautan setiap arsitektur sebelum menggabungkan executable yang dihasilkan dengan lipo. Membangun biner macOS universal.
xcrun lipo -create \
build/arm64/tile-demo \
build/x86_64/tile-demo \
-output build/tile-demo
xcrun lipo -archs build/tile-demo
./build/tile-demo
Pada Mac yang didukung dan menjalankan macOS 13.0 atau lebih baru, perintah terakhir seharusnya mencetak Tiles: 12 dan berhasil. Membangun kedua irisan berbeda dengan menguji keduanya: Mac Intel tidak dapat menjalankan irisan arm64. Panduan biner universal Apple.
Untuk pustaka yang mendukung beberapa platform atau varian platform Apple, gunakan XCFramework untuk mengemas varian yang dibangun secara terpisah. Apple secara eksplisit menginstruksikan pengembang agar memisahkan pustaka statis iOS dan iOS Simulator, serta mendukung penyertaan varian macOS native dan Mac Catalyst dalam XCFramework yang sama. Untuk alur kerja arsip Xcode, pendekatan yang didokumentasikan menggunakan destination untuk memilih platform dan SDK. Membuat bundel framework biner multiplatform.
Saat menghadapi kegagalan penautan macOS berikutnya, catat target yang dimaksud, periksa arsitektur dan platform dependensi yang dipilih, lalu periksa antarmuka bahasanya. Simpan temuan tersebut bersama perintah tautan yang persis digunakan. Dengan begitu, Anda memiliki dasar konkret untuk memilih biner yang tepat atau membangunnya ulang dari kode sumber.
Sumber
Kompilasi silang menggunakan Clang — Proyek LLVM.
Referensi pengaturan build — Apple.
clang — compiler Clang untuk C, C++, dan Objective-C — Proyek LLVM.
Referensi argumen baris perintah Clang — Proyek LLVM.
C++ Standar: Cara mencampur C dan C++ — Yayasan C++ Standar.
llvm-ar — pengarsip LLVM — Proyek LLVM.
llvm-otool — alat penampil Mach-O — Proyek LLVM.
llvm-nm — mencantumkan bitcode LLVM dan tabel simbol file objek — Proyek LLVM.
Definisi format Mach-O: loader.h — Apple.
Mencampur Swift dan C++ — Swift.org.
Menyiapkan Proyek Swift dan C++ dengan Bahasa Campuran — Swift.org.
Fitur dan Batasan Interoperabilitas C++ yang Didukung — Swift.org.
Membangun biner macOS universal — Apple.