Chapter Cross-compilation menunjukkan bahwa satu source C++ dapat dibangun menjadi biner untuk arsitektur mana pun, asalkan toolchain targetnya tersedia. Target berikutnya paling tidak terduga: browser web. Sejak format WebAssembly (Wasm) distandarisasi, kode C++ tidak lagi berhenti di terminal dan server — game engine, editor gambar, dan codec media kini berjalan di dalam tab browser setelah dikompilasi dari source C++. Chapter ini membahas kapan porting ke browser masuk akal, bagaimana toolchain Emscripten bekerja, dan batasan apa yang dikenakan sandbox browser terhadap program kita.
Kapan C++ ke Browser Masuk Akal #
Membawa C++ ke browser bukan gerakan untuk semua jenis aplikasi. Keputusan ini masuk akal ketika nilai utama program terletak pada komputasinya, bukan pada antarmukanya. Tiga pola pemakaian yang paling umum:
- Porting library komputasi. Codec audio/video, kompresi, kriptografi, dan pemrosesan gambar adalah pekerjaan berat di CPU yang sudah lama ditulis dalam C++; kompilasi ke Wasm memakai kode itu di browser tanpa menulis ulang di JavaScript.
- Game engine dan rendering. Game engine seperti Unity menyediakan target ekspor WebAssembly, sehingga sebagian besar logika engine identik dengan versi desktop dapat berjalan di browser.
- Reuse kode lintas platform. Ketika satu produk memiliki klien desktop C++ dan klien web, logika inti seperti parser dan mesin perhitungan bisa menjadi satu source yang dibangun dua kali.
Sebaliknya, aplikasi yang antarmukanya sepenuhnya berada di DOM — form, dashboard, tampilan data — lebih alami ditulis langsung dengan JavaScript. Wasm bukan pengganti JavaScript; keduanya berdampingan, dan ada biaya komunikasi di batasnya, sehingga fungsi kecil yang dipanggil bergantian dari dua sisi bisa justru lebih lambat.
WebAssembly dalam Satu Halaman #
WebAssembly adalah format instruksi biner untuk sebuah mesin virtual berbasis stack yang dijalankan browser. Format ini dirancang sebagai target kompilasi portabel — compiler menerjemahkan C++ menjadi bytecode Wasm — dan dieksekusi di dalam sandbox dengan kecepatan mendekati kode native. Bagi browser, modul Wasm adalah pasangan kode dan linear memory: seluruh data program berada di satu blok memori yang ukurannya disepakati dan hanya bertambah bila diminta.
Artefak yang dikirim ke browser biasanya berupa pasangan berkas: .wasm berisi bytecode, sedangkan .js adalah glue code — kode perantara yang memuat modul dan menerjemahkan pemanggilan antara JavaScript dan Wasm. Karena itu, halaman web tetap berkomunikasi dengan program C++ tersebut lewat JavaScript.
Emscripten: Toolchain dari C++ ke Wasm #
Emscripten adalah toolchain standar industri untuk pekerjaan ini. Driver utamanya, emcc, berperilaku seperti pengganti g++: flag -std, -O2, dan -Wall dikenalinya, standard library C++ disediakan oleh toolchain, sehingga source yang ramah compiler GNU umumnya langsung dapat dikompilasi. Pemasangannya memakai emsdk:
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install latest
./emsdk activate latest
source ./emsdk_env.shLima perintah di atas mengikuti panduan resmi Getting Started: install mengunduh toolchain, activate memilih versi aktif, dan source memasukkan emcc ke PATH. Setelah itu, emcc dipakai seperti g++ dengan satu keputusan tambahan — bentuk keluaran:
| Flag keluaran | Hasil yang diperoleh |
|---|---|
-o hitung.html | Halaman web lengkap: wasm + glue + halaman siap dibuka |
-o hitung.js | Glue code saja — untuk dijalankan via Node atau disisipkan ke halaman |
-o hitung.wasm | Bytecode murni tanpa glue — untuk integrasi manual |
Untuk percobaan pertama, -o file.html paling cepat: buka hasilnya di browser dan program berjalan. Flag -O2 bekerja seperti pada Release Build — optimasi penting karena bytecode Wasm yang belum dioptimasi berukuran besar dan lambat.
Fungsi Perhitungan Murni sebagai Bahan Uji #
Kriteria kode yang paling layak dibawa ke Wasm sama dengan prasyarat cross-compilation: komputasi murni tanpa API OS. Program berikut memuat dua fungsi kecil — matematika murni (hitungFpb, algoritma Euclid) dan konversi unit audio (dbKeGain, desibel menjadi faktor gain). Keduanya ditandai extern "C" agar nama simbolnya tidak ter-mangle sehingga daftar ekspor di sisi Emscripten mudah ditulis. Kita bangun program ini dengan g++ di praktikum untuk memverifikasi logikanya; fungsi yang sama persis inilah yang nantinya dikompilasi emcc.
#include <cmath>
#include <cstdint>
#include <iomanip>
#include <iostream>
// Dua fungsi komputasi murni: masukan lewat parameter, hasil lewat return.
// Tanpa I/O, tanpa variabel global, tanpa API OS — kandidat ideal untuk
// dibawa ke WebAssembly. Penanda extern "C" menjaga nama simbol tetap
// tidak ter-mangle sehingga daftar EXPORTED_FUNCTIONS emcc tetap sederhana,
// sedangkan g++ di praktikum tetap membangun source ini apa adanya.
extern "C" std::int64_t hitungFpb(std::int64_t a, std::int64_t b) {
while (b != 0) {
std::int64_t sisa = a % b;
a = b;
b = sisa;
}
return a;
}
extern "C" double dbKeGain(double db) {
return std::pow(10.0, db / 20.0);
}
int main() {
std::cout << "FPB(1071, 462) = " << hitungFpb(1071, 462) << "\n";
for (double db : {-6.0, 0.0, 6.0}) {
std::cout << std::defaultfloat << "Gain " << db << " dB = "
<< std::fixed << std::setprecision(3) << dbKeGain(db) << "\n";
}
return 0;
}Output yang Dihasilkan:
FPB(1071, 462) = 21
Gain -6 dB = 0.501
Gain 0 dB = 1.000
Gain 6 dB = 1.995Mari kita telaah baris-baris yang menentukan:
- Baris 12 (
extern "C" std::int64_t hitungFpb(...)): penandaextern "C"mematikan name mangling C++ untuk fungsi ini; simbolnya tetap bernamahitungFpbdi binary, dan g++ tetap membangun source tanpa keluhan. - Baris 13-18 (algoritma Euclid): loop modulo menghitung FPB tanpa alokasi memori dinamis sama sekali — pola yang ideal untuk linear memory Wasm yang ukurannya disepakati sejak awal.
- Baris 21-23 (
dbKeGain):std::powberasal dari standard library; Emscripten menyediakan implementasinya sebagai bagian dari sysroot-nya, sehingga source tidak perlu diubah. - Baris 28-30 (loop cetak): manipulator
defaultfloatdanfixeddipakai bergantian agar label desibel tampil bulat sementara gain tampil tiga desimal — format yang identik antara hasil g++ dan hasil Node nantinya.
Sesi emcc Ilustratif #
Sesi berikut mengompilasi hitung-wasm.cpp lalu menjalankan hasilnya di Node.js — runtime JavaScript luar browser yang mampu mengeksekusi modul Wasm dari terminal:
emcc -std=c++23 -O2 hitung-wasm.cpp -o hitung.js \
-sEXPORTED_FUNCTIONS=_main,_hitungFpb,_dbKeGain \
-sEXPORTED_RUNTIME_METHODS=ccall
ls hitung.*
node hitung.jsBentuk keluaran yang diharapkan (ilustrasi — nama dan ukuran berkas bergantung pada versi toolchain):
hitung.js hitung.wasm
FPB(1071, 462) = 21
Gain -6 dB = 0.501
Gain 0 dB = 1.000
Gain 6 dB = 1.995Dua hal penting terjadi di sini. Pertama, emcc menghasilkan pasangan hitung.wasm + hitung.js — bytecode beserta glue code-nya; flag -sEXPORTED_FUNCTIONS mencegah optimizer membuang fungsi yang belum dipanggil. Kedua, keluaran Node identik dengan keluaran g++ di bagian sebelumnya: logika tidak berubah, yang berganti hanyalah mesin yang mengeksekusinya. Bila targetnya halaman web, ganti -o hitung.js menjadi -o hitung.html; fungsi yang diekspor dapat dipanggil dari JavaScript, antara lain lewat helper ccall.
Batasan Sandbox: Memori dan I/O #
Program C++ yang pindah ke browser menandatangani kontrak baru. Memori program berada di dalam linear memory Wasm — satu blok berukuran tetap (2 GB secara bawaan) yang hanya bertambah bila toolchain dikonfigurasi dengan ALLOW_MEMORY_GROWTH — dan pointer C++ tidak menunjuk keluar dari blok itu. Berkas tidak dibaca dari disk nyata: Emscripten menyediakan filesystem virtual (MEMFS) di dalam memori, dan berkas host ditanam ke dalamnya lewat flag --preload-file saat kompilasi. Jaringan tidak diakses lewat socket seperti pada chapter Network Programming; jalur keluarnya adalah API browser (fetch, WebSocket) lewat glue code.
Dengan toolchain yang tepat dan kode yang bersih dari API OS, browser menjadi target distribusi yang sah untuk komputasi C++. Selanjutnya kita kembali ke distribusi klasik: menyalurkan aplikasi ke pengguna desktop, dimulai dari Deployment di Linux.
Referensi: Getting Started — Emscripten Docs , WebAssembly — MDN Web Docs .