Kompilasi silang

Menghasilkan biner untuk platform lain dengan satu toolchain melalui opsi -target.

Daftar isi

Kompilasi silang adalah kemampuan menghasilkan program untuk platform yang berbeda dari mesin yang sedang dipakai. Zig mengusungnya sebagai fitur inti karena zig cc menyertakan komponen clang beserta sysroot untuk setiap target yang didukung, sehingga tidak ada pemasangan toolchain tambahan, cross compiler, maupun pustaka tautan terpisah. Topik ini mempraktikkan opsi -target, membaca hasil binernya, dan menyingkap peran ABI pada nama target.

Konsep#

Target pada Zig dinyatakan sebagai rangkaian tiga bagian, yaitu arsitektur prosesor, sistem operasi, dan ABI, contohnya x86_64-windows dan aarch64-linux-musl. Arsitektur menentukan set instruksi, sistem operasi menentukan format berkas dan panggilan sistem, sedangkan ABI menentukan konvensi pemanggilan serta pustaka C yang ditautkan, misalnya gnu untuk glibc dan musl untuk musl yang statis. Bila bagian ABI ditiadakan, Zig memilih nilai wajar berdasarkan sistem operasi yang dituju.

Perintah yang sama menerima opsi ini. zig build-exe sumber.zig -target <triple> menghasilkan biner untuk target yang disebut, sedangkan pada proyek ber-build.zig opsi -Dtarget=<triple> memasok nilai yang sama ke standardTargetOptions yang dipasang pada build.zig. Tidak ada langkah konfigurasi tambahan, dan seluruh pustaka standar dikompilasi ulang untuk target tersebut secara otomatis.

Hasil setiap target tersimpan pada cache yang terpisah, sehingga perintah kompilasi silang yang diulang hanya mengompilasi ulang bila sumber atau targetnya berubah. Kemampuan yang sama berlaku untuk kode C, karena zig cc adalah pembungkus kompiler C yang memakai mesin yang sama, dan berkas C yang dikompilasi untuk target jauh memakai sysroot milik toolchain itu. Proyek campuran Zig dan C karenanya ikut dikompilasi silang tanpa perancah tambahan.

Contoh Lengkap#

Program berikut membaca target tempat ia dikompilasi melalui builtin dan mencetak tiga identitasnya. Satu berkas sumber ini dipakai untuk seluruh demonstrasi, karena perubahan target tidak mengubah kode sedikit pun.

zig info-target.zig
const std = @import("std");
const builtin = @import("builtin");

pub fn main() void {
    std.debug.print("os: {s}\n", .{@tagName(builtin.os.tag)});
    std.debug.print("arsitektur: {s}\n", .{@tagName(builtin.cpu.arch)});
    std.debug.print("abi: {s}\n", .{@tagName(builtin.abi)});
}

Kompilasi pertama berjalan untuk mesin sendiri, dan programnya langsung dijalankan.

bash
zig build-exe info-target.zig -femit-bin=info-linux
./info-linux
text Keluaran
os: linux
arsitektur: x86_64
abi: gnu

Angka x86_64 dan gnu mengikuti mesin tempat kompilasi berlangsung. Kompilasi berikutnya memilih dua target yang berbeda, yaitu Windows x86-64 dan Linux ARM64 dengan musl.

bash
zig build-exe info-target.zig -target x86_64-windows -femit-bin=info.exe
zig build-exe info-target.zig -target aarch64-linux-musl -femit-bin=info-arm64

Tidak ada keluaran yang dicetak, dan dua berkas baru muncul di direktori kerja. Periksa identitas berkasnya dengan perintah file.

bash
file info.exe info-arm64
text Keluaran
info.exe:   PE32+ executable for MS Windows 6.00 (console), x86-64, 7 sections
info-arm64: ELF 64-bit LSB executable, ARM aarch64, version 1 (SYSV), statically linked, with debug_info, not stripped

Baris pertama menunjukkan format PE khas Windows, sedangkan baris kedua menunjukkan format ELF untuk ARM64 dengan tautan statis karena musl. Ukuran ketiga biner dapat diperiksa dengan perintah seperti stat -c "%n: %s byte" nama-berkas, tetapi angka pastinya berbeda antar lingkungan karena bagian jejak debug memuat jalur berkas tempat kompilasi berlangsung. Yang dibandingkan adalah perbandingan kasarnya, bukan angka byte yang persis.

Ukuran yang berbeda bukan kebetulan, karena setiap target menyertakan runtime dan format debug yang berbeda. Yang penting diperhatikan adalah ketiga biner berasal dari satu berkas sumber yang sama tanpa satu pun perubahan kode, dan prosesnya berlangsung pada satu toolchain yang sama.

Biner ARM64 dapat diuji di mesin x86-64 melalui emulator seperti QEMU, misalnya qemu-aarch64 ./info-arm64 bila paketnya terpasang. Pemisahan ini menegaskan peran masing-masing sisi, yaitu Zig menghasilkan biner yang benar untuk target mana pun, sedangkan eksekusinya menuntut perangkat keras atau emulator yang sesuai. Untuk target Windows, pengujiannya berlangsung pada mesin Windows, pada mesin virtual, atau melalui lapisan kesesuaian seperti Wine.

Kompilasi silang juga mengubah cara pustaka C disertakan. Pustaka standar C untuk target gnu diambil dari glibc yang dikompilasi ulang oleh toolchain, sedangkan target musl memakai musl yang menghasilkan tautan statis, dan keduanya disediakan toolchain tanpa pemasangan tambahan. Akibatnya, perintah yang sama berjalan di mesin tanpa pustaka target sekalipun, dan inilah yang membedakan praktik Zig dari alur kompilasi silang C tradisional yang meminta toolchain per target dipasang dahulu.

Kesalahan umum#

Kesalahan berikutnya berupa menjalankan biner hasil silang pada mesin sendiri. Biner info-arm64 tidak dapat dieksekusi di mesin x86-64 Linux, dan sistem operasi menolaknya dengan pesan Exec format error pada tingkat shell. Binernya sah, hanya saja ditujukan untuk prosesor yang berbeda, sehingga pengujian dilakukan di mesin target, mesin virtual, atau emulator seperti QEMU.

Ketidaktahuan tentang bagian ABI juga sering menimbulkan kebingungan. Kompilasi untuk x86_64-linux-gnu menautkan glibc dan menuntut pustaka tersebut hadir pada mesin tujuan, sedangkan aarch64-linux-musl menghasilkan biner statis yang berdiri sendiri. Memilih ABI adalah bagian dari keputusan distribusi, bukan sekadar detail nama target.

Ringkasan#

  • Opsi -target menerima rangkaian arsitektur, sistem operasi, dan ABI, dan seluruh kombinasi didukung oleh toolchain yang sama.
  • zig build-exe dan -Dtarget pada proyek ber-build.zig memakai mekanisme target yang sama.
  • Format biner, ukuran, dan cara penautan berubah mengikuti target, dengan musl menghasilkan biner statis.
  • Biner hasil silang diuji pada platform tujuannya, bukan pada mesin yang mengompilasi.

Referensi#