Kompilasi program C ++ melibatkan tiga langkah:
Preprocessing: preprocessor mengambil file kode sumber C ++ dan berkaitan dengan #include
s, #define
s dan arahan preprocessor lainnya. Output dari langkah ini adalah file C ++ "murni" tanpa arahan pra-prosesor.
Kompilasi: kompiler mengambil output pra-prosesor dan menghasilkan file objek darinya.
Menautkan: tautan mengambil file objek yang dihasilkan oleh kompiler dan menghasilkan pustaka atau file yang dapat dieksekusi.
Preprocessing
Preprocessor menangani arahan preprocessor , seperti #include
dan #define
. Ini agnostik dari sintaksis C ++, oleh karena itu harus digunakan dengan hati-hati.
Ia bekerja pada satu file sumber C ++ pada satu waktu dengan mengganti #include
arahan dengan konten dari masing-masing file (yang biasanya hanya deklarasi), melakukan penggantian makro ( #define
), dan memilih bagian teks yang berbeda tergantung dari #if
, #ifdef
dan #ifndef
arahan.
Preprocessor bekerja pada aliran token preprocessing. Substitusi makro didefinisikan sebagai mengganti token dengan token lain (operator ##
memungkinkan penggabungan dua token saat masuk akal).
Setelah semua ini, preprocessor menghasilkan output tunggal yang merupakan aliran token yang dihasilkan dari transformasi yang dijelaskan di atas. Itu juga menambahkan beberapa spidol khusus yang memberitahu kompiler dari mana setiap baris berasal sehingga dapat menggunakannya untuk menghasilkan pesan kesalahan yang masuk akal.
Beberapa kesalahan dapat dihasilkan pada tahap ini dengan penggunaan #if
dan #error
arahan yang cerdas .
Kompilasi
Langkah kompilasi dilakukan pada setiap output preprosesor. Compiler mem-parsing kode sumber C ++ murni (sekarang tanpa arahan preprocessor) dan mengubahnya menjadi kode assembly. Kemudian gunakan back-end yang mendasari (assembler dalam toolchain) yang merakit kode itu ke dalam kode mesin yang menghasilkan file biner aktual dalam beberapa format (ELF, COFF, a.out, ...). File objek ini berisi kode yang dikompilasi (dalam bentuk biner) dari simbol-simbol yang didefinisikan dalam input. Simbol dalam file objek disebut dengan nama.
File objek dapat merujuk ke simbol yang tidak didefinisikan. Ini adalah kasus ketika Anda menggunakan deklarasi, dan tidak memberikan definisi untuk itu. Compiler tidak keberatan dengan hal ini, dan dengan senang hati akan menghasilkan file objek selama kode sumbernya terbentuk dengan baik.
Compiler biasanya membiarkan Anda menghentikan kompilasi pada saat ini. Ini sangat berguna karena dengan itu Anda dapat mengkompilasi setiap file kode sumber secara terpisah. Keuntungan yang diberikan ini adalah Anda tidak perlu mengkompilasi ulang semuanya jika Anda hanya mengubah satu file.
File objek yang dihasilkan dapat dimasukkan ke dalam arsip khusus yang disebut perpustakaan statis, untuk digunakan kembali nanti.
Pada tahap ini dilaporkan kesalahan "reguler", seperti kesalahan sintaksis atau kesalahan resolusi kelebihan beban yang dilaporkan.
Menautkan
Tautan adalah yang menghasilkan keluaran kompilasi akhir dari file objek yang dihasilkan kompiler. Output ini bisa berupa pustaka bersama (atau dinamis) (dan meskipun namanya mirip, pustaka tersebut tidak memiliki banyak kesamaan dengan pustaka statis yang disebutkan sebelumnya) atau yang dapat dieksekusi.
Ini menautkan semua file objek dengan mengganti referensi ke simbol yang tidak terdefinisi dengan alamat yang benar. Masing-masing simbol ini dapat didefinisikan dalam file objek lain atau di perpustakaan. Jika mereka didefinisikan di perpustakaan selain dari perpustakaan standar, Anda perlu memberi tahu linker tentang mereka.
Pada tahap ini kesalahan yang paling umum adalah definisi yang hilang atau definisi duplikat. Yang pertama berarti bahwa definisi tidak ada (yaitu mereka tidak ditulis), atau bahwa file objek atau pustaka tempat mereka berada tidak diberikan kepada linker. Yang terakhir jelas: simbol yang sama didefinisikan dalam dua file objek atau pustaka yang berbeda.