<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Build System on kenji.blog</title><link>http://kenji.blog/id/tags/build-system/</link><description>Recent content in Build System on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>id</language><copyright>kenjinote</copyright><lastBuildDate>Sat, 12 Sep 2026 09:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/id/tags/build-system/index.xml" rel="self" type="application/rss+xml"/><item><title>Langkah-langkah Membangun Lingkungan Build C++ Lintas Platform Menggunakan CMake</title><link>http://kenji.blog/id/p/cmake-cross-platform-build-environment-guide/</link><pubDate>Sat, 12 Sep 2026 09:00:00 +0900</pubDate><guid>http://kenji.blog/id/p/cmake-cross-platform-build-environment-guide/</guid><description>&lt;img src="http://kenji.blog/p/cmake-cross-platform-build-environment-guide/img/eyecatch.jpg" alt="Featured image of post Langkah-langkah Membangun Lingkungan Build C++ Lintas Platform Menggunakan CMake" />&lt;p>Dalam pengembangan perangkat lunak dengan C++, hal yang sering menyusahkan banyak pengembang selama bertahun-tahun adalah pemilihan dan pembangunan &amp;ldquo;sistem build&amp;rdquo;. Karena C++ tidak memiliki manajer paket standar resmi atau sistem build, kita perlu menggunakan kompiler dan alat build yang berbeda-beda (MSVC, GCC, Clang, Make, Ninja, dll.) untuk setiap platform (Windows, Linux, macOS).&lt;/p>
&lt;p>Namun, saat ini &lt;strong>CMake&lt;/strong> telah ditetapkan sebagai standar industri de facto, dan dengan memanfaatkan CMake secara tepat, kita dapat dengan elegan membangun lingkungan build lintas platform dari satu &lt;code>CMakeLists.txt&lt;/code>.&lt;/p>
&lt;p>Pada artikel ini, kita akan membahas secara menyeluruh dan terperinci mengenai langkah-langkah membangun lingkungan build C++ lintas platform terbaru (Modern CMake) menggunakan CMake, dari dasar hingga teknik tingkat lanjut.&lt;/p>
&lt;h2 id="1-apa-itu-cmake-konsep-sistem-meta-build">1. Apa itu CMake? (Konsep Sistem Meta-Build)
&lt;/h2>&lt;p>CMake pada dasarnya bukanlah alat yang mengkompilasi kode sumber secara langsung. CMake adalah &amp;ldquo;sistem yang menghasilkan sistem build&amp;rdquo;, yaitu &lt;strong>Sistem Meta-Build (Meta-Build System)&lt;/strong>.&lt;/p>
&lt;p>Peran utama CMake adalah membaca file konfigurasi abstrak yang independen terhadap platform dan kompiler (&lt;code>CMakeLists.txt&lt;/code>), lalu secara otomatis menghasilkan skrip build asli yang paling sesuai untuk setiap lingkungan (misalnya: &lt;code>Makefile&lt;/code> untuk Linux, file proyek &lt;code>.sln&lt;/code> Visual Studio untuk Windows, atau &lt;code>build.ninja&lt;/code> yang cepat).&lt;/p>
&lt;p>Diagram berikut menunjukkan proses generasi CMake.&lt;/p>
&lt;div class="mermaid">graph TD
A["CMakeLists.txt (Definisi Build Abstrak)"] --> B["CMake (Configure &amp; Generate)"]
B --> C["Unix Makefiles"]
B --> D["Ninja Build Files"]
B --> E["Visual Studio Solutions"]
B --> F["Xcode Projects"]
C --> G["Native Build Tool (make, ninja, MSBuild, xcodebuild)"]
D --> G
E --> G
F --> G
G --> H["Executable / Shared Library / Static Library"]&lt;/div>
&lt;p>Dengan menempatkan CMake di tengah seperti ini, pengembang dapat mengelola proyek C++ tanpa perlu memperhatikan perbedaan kecil pada perintah untuk setiap OS.&lt;/p>
&lt;h2 id="2-dasar-modern-cmake-dari-variabel-ke-target">2. Dasar Modern CMake: Dari Variabel ke Target
&lt;/h2>&lt;p>Sintaks CMake 3.0 ke atas disebut &amp;ldquo;Modern CMake&amp;rdquo;, yang filosofi desainnya secara mendasar berbeda dari yang sebelumnya (Legacy CMake). Pada Legacy CMake, pendekatan utamanya adalah dengan menimpa variabel global per direktori (misalnya menggunakan &lt;code>include_directories()&lt;/code> atau &lt;code>link_libraries()&lt;/code>), tetapi hal ini sering menimbulkan efek samping yang serius di mana pengaturan dapat memengaruhi modul lain secara tidak sengaja.&lt;/p>
&lt;p>Pada Modern CMake, semuanya diperlakukan sebagai &lt;strong>Target&lt;/strong> dan &lt;strong>Properti (Property)&lt;/strong>. Ini mirip dengan hubungan antara kelas dan variabel anggota dalam pemrograman berorientasi objek.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Target&lt;/strong>: File yang dapat dieksekusi (Executable) atau pustaka (Library).&lt;/li>
&lt;li>&lt;strong>Properti&lt;/strong>: File sumber, direktori penyertaan (include), opsi kompilasi, pustaka lain yang akan ditautkan, dll. yang diperlukan untuk membangun target tersebut.&lt;/li>
&lt;/ul>
&lt;p>Dengan merangkum (mengenkapsulasi) pengaturan hanya pada target tertentu, dimungkinkan untuk membuat definisi build yang aman tanpa kerusakan bahkan pada proyek skala besar.&lt;/p>
&lt;h3 id="cmakeliststxt-minimal">&lt;code>CMakeLists.txt&lt;/code> Minimal
&lt;/h3>&lt;p>Pertama-tama, mari kita lihat &lt;code>CMakeLists.txt&lt;/code> yang paling mendasar.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Menentukan versi minimum CMake yang dibutuhkan
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">cmake_minimum_required&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">VERSION&lt;/span> &lt;span class="s">3.20&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Menentukan nama proyek dan bahasa yang digunakan
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">project&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyAwesomeApp&lt;/span> &lt;span class="s">VERSION&lt;/span> &lt;span class="s">1.0.0&lt;/span> &lt;span class="s">LANGUAGES&lt;/span> &lt;span class="s">CXX&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Meminta standar C++ (C++20)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">CMAKE_CXX_STANDARD&lt;/span> &lt;span class="s">20&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">CMAKE_CXX_STANDARD_REQUIRED&lt;/span> &lt;span class="s">ON&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">CMAKE_CXX_EXTENSIONS&lt;/span> &lt;span class="s">OFF&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c"># Menonaktifkan ekstensi khusus kompiler
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Definisi target yang dapat dieksekusi
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_executable&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyAwesomeApp&lt;/span> &lt;span class="s">main.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Hanya dengan beberapa baris ini, pengaturan build untuk file yang dapat dieksekusi portabel yang membutuhkan C++20 dan menonaktifkan ekstensi kompiler telah selesai.&lt;/p>
&lt;h2 id="3-ketergantungan-dan-lingkup-public--private--interface">3. Ketergantungan dan Lingkup: PUBLIC / PRIVATE / INTERFACE
&lt;/h2>&lt;p>Hal yang paling penting dan juga paling sulit untuk dikuasai dalam Modern CMake adalah konsep 3 pengubah akses (lingkup) yang digunakan dalam &lt;code>target_include_directories&lt;/code> atau &lt;code>target_link_libraries&lt;/code>, yaitu &lt;strong>&lt;code>PUBLIC&lt;/code>, &lt;code>PRIVATE&lt;/code>, &lt;code>INTERFACE&lt;/code>&lt;/strong>.&lt;/p>
&lt;p>Pengubah ini mengontrol properti target (seperti jalur penyertaan dan dependensi pustaka), yakni apakah properti tersebut &amp;ldquo;diperlukan untuk membangun dirinya sendiri?&amp;rdquo; dan &amp;ldquo;apakah itu diteruskan ke target lain yang bergantung padanya?&amp;rdquo;.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>&lt;code>PRIVATE&lt;/code>&lt;/strong>: Hanya diperlukan untuk membangun target itu sendiri. &lt;strong>Tidak&lt;/strong> diteruskan ke target yang bergantung padanya.&lt;/li>
&lt;li>&lt;strong>&lt;code>INTERFACE&lt;/code>&lt;/strong>: Tidak diperlukan untuk membangun target itu sendiri, tetapi &lt;strong>diteruskan&lt;/strong> ke target yang bergantung padanya (biasanya digunakan pada pustaka header-only).&lt;/li>
&lt;li>&lt;strong>&lt;code>PUBLIC&lt;/code>&lt;/strong>: Diperlukan untuk membangun target itu sendiri, dan juga &lt;strong>diteruskan&lt;/strong> ke target yang bergantung padanya (&lt;code>PRIVATE&lt;/code> + &lt;code>INTERFACE&lt;/code>).&lt;/li>
&lt;/ol>
&lt;p>Mari kita visualisasikan penyebaran dependensi (Propagasi Usage Requirements) melalui diagram berikut.&lt;/p>
&lt;div class="mermaid">graph TD
subgraph "Libraries"
MathLib["MathLib (Static Library)"]
NetworkLib["NetworkLib (Shared Library)"]
HeaderLib["HeaderLib (Header Only)"]
end
subgraph "Application"
App["Main Application"]
end
App -- "target_link_libraries(App PRIVATE MathLib)" --> MathLib
App -- "target_link_libraries(App PUBLIC NetworkLib)" --> NetworkLib
NetworkLib -- "target_link_libraries(NetworkLib INTERFACE HeaderLib)" --> HeaderLib
note1["App bergantung pada implementasi MathLib, tapi tidak menunjukkannya ke luar"]
note2["NetworkLib mengekspos antarmuka HeaderLib"]&lt;/div>
&lt;h3 id="contoh-penggunaan-lingkup-secara-konkret">Contoh Penggunaan Lingkup Secara Konkret
&lt;/h3>&lt;p>Misalkan sebuah pustaka &lt;code>MyLib&lt;/code> menggunakan &lt;code>nlohmann/json&lt;/code> sebagai implementasi internal, dan di dalam file header publiknya &lt;code>MyLib.hpp&lt;/code>, ia tidak menyertakan (include) &lt;code>nlohmann/json&lt;/code>. Dalam hal ini, pihak yang menggunakan &lt;code>MyLib&lt;/code> (aplikasi) tidak perlu mengetahui keberadaan pustaka JSON tersebut.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Definisi pustaka
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_library&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyLib&lt;/span> &lt;span class="s">src/MyLib.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Menentukan direktori penyertaan untuk proyek sendiri
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Direktori include diperlukan juga oleh pengguna MyLib sehingga disetel ke PUBLIC
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Direktori src hanya digunakan dalam implementasi MyLib sehingga disetel ke PRIVATE
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">target_include_directories&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyLib&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">PUBLIC&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">INSTALL_INTERFACE:include&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">PRIVATE&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">${&lt;/span>&lt;span class="nv">CMAKE_CURRENT_SOURCE_DIR&lt;/span>&lt;span class="o">}&lt;/span>&lt;span class="s">/src&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Pustaka json hanya digunakan dalam implementasi internal, jadi tautkan dengan PRIVATE
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">target_link_libraries&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyLib&lt;/span> &lt;span class="s">PRIVATE&lt;/span> &lt;span class="s">nlohmann_json::nlohmann_json&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Sebaliknya, jika di dalam &lt;code>MyLib.hpp&lt;/code> kita menulis &lt;code>#include &amp;lt;nlohmann/json.hpp&amp;gt;&lt;/code>, maka pihak yang menggunakan &lt;code>MyLib&lt;/code> juga harus mengetahui jalur header JSON agar tidak terjadi kesalahan kompilasi. Oleh karena itu, penautan (link) harus dilakukan secara &lt;code>PUBLIC&lt;/code>. Dengan mengatur lingkup ini secara tepat, kita dapat mengurangi waktu build dan mencegah kebocoran dependensi yang tidak perlu.&lt;/p>
&lt;h2 id="4-build-di-luar-sumber-out-of-source-build">4. Build di Luar Sumber (Out-of-source Build)
&lt;/h2>&lt;p>Praktik terbaik yang harus selalu diikuti saat menggunakan CMake adalah &lt;strong>Build di Luar Sumber (Out-of-source Build)&lt;/strong>.
Ini adalah metode di mana tidak ada hasil build (seperti file objek atau file eksekusi) yang dikeluarkan ke direktori tempat kode sumber berada (source tree), melainkan dipisahkan dan dibangun di direktori khusus lain (biasanya &lt;code>build/&lt;/code>).&lt;/p>
&lt;div class="mermaid">graph TD
Root["Project Root (Git Repository)"]
Root --> Src["src/"]
Root --> Inc["include/"]
Root --> CMake["CMakeLists.txt"]
Root -. "Buat dir build" .-> Build["build/ (Out-of-source)"]
Build --> Obj["CMakeFiles/ (Object files, caches)"]
Build --> Bin["Binaries (MyApp.exe)"]
Build --> Gen["Generated Makefile / build.ninja"]&lt;/div>
&lt;p>Dengan struktur ini, jika kita ingin mereset lingkungan build, kita cukup menghapus seluruh direktori &lt;code>build&lt;/code>, dan karena source tree tidak kotor, pengelolaan Git juga menjadi lebih mudah (cukup dengan menambahkan &lt;code>build/&lt;/code> ke &lt;code>.gitignore&lt;/code>).&lt;/p>
&lt;h3 id="prosedur-eksekusi-build">Prosedur Eksekusi Build
&lt;/h3>&lt;p>Pada Modern CMake, build dapat dieksekusi dengan perintah umum yang independen dari OS maupun alat build.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 1. Konfigurasi dan generasi (melakukan pengaturan sekaligus membuat direktori build)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmake -S . -B build
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># 2. Build aktual (kompilasi dan penautan)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmake --build build --config Release
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1"># (Opsional) Gunakan opsi -j untuk build dengan multithread&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">cmake --build build --config Release -j &lt;span class="m">8&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Di sini &lt;code>cmake -S . -B build&lt;/code> berarti &amp;ldquo;gunakan direktori saat ini (&lt;code>.&lt;/code>) sebagai direktori sumber, dan atur &lt;code>build&lt;/code> sebagai direktori build&amp;rdquo;.&lt;/p>
&lt;h2 id="5-metode-memasukkan-pustaka-pihak-ketiga">5. Metode Memasukkan Pustaka Pihak Ketiga
&lt;/h2>&lt;p>Dalam pengembangan C++, memasukkan pustaka eksternal (pustaka pihak ketiga) selalu menjadi rintangan tersendiri. Namun saat ini, tiga pendekatan berikut umumnya menjadi standar.&lt;/p>
&lt;h3 id="51-find_package-mencari-pustaka-yang-telah-terpasang-di-sistem">5.1. find_package (Mencari Pustaka yang Telah Terpasang di Sistem)
&lt;/h3>&lt;p>Ini adalah metode paling tradisional untuk menemukan dan menautkan pustaka yang sudah diinstal di sistem (contoh: OpenSSL atau Zlib).&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">find_package&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">ZLIB&lt;/span> &lt;span class="s">REQUIRED&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">if&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">ZLIB_FOUND&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span> &lt;span class="nb">target_link_libraries&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyAwesomeApp&lt;/span> &lt;span class="s">PRIVATE&lt;/span> &lt;span class="s">ZLIB::ZLIB&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">endif&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="52-fetchcontent-mengunduh-dari-sumber-dan-memasukkannya">5.2. FetchContent (Mengunduh dari Sumber dan Memasukkannya)
&lt;/h3>&lt;p>Ini adalah modul yang diperkenalkan pada CMake 3.11 dan menjadi lebih canggih sejak 3.14. Ia mengunduh kode sumber secara langsung dari repositori Git eksternal atau URL saat waktu build, dan membangunnya bersama-sama sebagai bagian dari proyek. Karena dependensi dapat dikelola secara terpusat, reproduktibilitas lintas platformnya sangat tinggi.&lt;/p>
&lt;p>Berikut adalah contoh untuk memasukkan GoogleTest menggunakan FetchContent.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">include&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">FetchContent&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">FetchContent_Declare&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">googletest&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">GIT_REPOSITORY&lt;/span> &lt;span class="s">https://github.com/google/googletest.git&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">GIT_TAG&lt;/span> &lt;span class="s">v1.14.0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Membawa pustaka ke dalam proyek
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">FetchContent_MakeAvailable&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">googletest&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Membuat file eksekusi untuk pengujian dan menautkannya
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_executable&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyTests&lt;/span> &lt;span class="s">test/main.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">target_link_libraries&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyTests&lt;/span> &lt;span class="s">PRIVATE&lt;/span> &lt;span class="s">gtest_main&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="53-integrasi-dengan-vcpkg">5.3. Integrasi dengan vcpkg
&lt;/h3>&lt;p>Dengan menggunakan &lt;strong>vcpkg&lt;/strong>, manajer paket untuk C++ yang dipimpin oleh Microsoft, ribuan pustaka dapat dimasukkan dengan mudah. vcpkg dirancang untuk terintegrasi secara mulus dengan CMake.&lt;/p>
&lt;p>Saat menjalankan CMake, cukup dengan menentukan file toolchain dari vcpkg, &lt;code>find_package&lt;/code> akan secara otomatis mencari pustaka di dalam vcpkg.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE&lt;span class="o">=&lt;/span>/path/to/vcpkg/scripts/buildsystems/vcpkg.cmake
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Selain itu, dengan menempatkan &lt;code>vcpkg.json&lt;/code> (mode manifest) di root proyek, pengelolaan versi dari pustaka-pustaka yang dibutuhkan dapat diotomatisasi sepenuhnya.&lt;/p>
&lt;h2 id="6-flag-kompiler-untuk-dukungan-lintas-platform">6. Flag Kompiler untuk Dukungan Lintas Platform
&lt;/h2>&lt;p>Untuk dapat berhasil melakukan build di lingkungan Windows (MSVC), Linux (GCC/Clang), maupun macOS (Apple Clang), kita perlu mengatur flag spesifik kompiler secara tepat.&lt;/p>
&lt;p>Dengan menggunakan &lt;strong>Ekspresi Generator (Generator Expressions)&lt;/strong> dari CMake, kita dapat menulis percabangan kondisional secara deklaratif, seperti &amp;ldquo;jika kompilernya MSVC gunakan flag ini, jika tidak gunakan flag itu&amp;rdquo;. Ekspresi generator menggunakan sintaks &lt;code>$&amp;lt;...&amp;gt;&lt;/code> dan dievaluasi saat waktu generasi sistem build (fase Generate).&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Contoh mengaktifkan peringatan tingkat tertinggi untuk semua platform
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">target_compile_options&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyAwesomeApp&lt;/span> &lt;span class="s">PRIVATE&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Untuk MSVC
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span> &lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">$&amp;lt;CXX_COMPILER_ID:MSVC&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">:/W4&lt;/span> &lt;span class="s">/WX&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># Untuk GCC atau Clang
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span> &lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">$&amp;lt;OR:$&amp;lt;CXX_COMPILER_ID:GNU&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">,&lt;/span>&lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">CXX_COMPILER_ID:Clang&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">,&lt;/span>&lt;span class="o">$&amp;lt;&lt;/span>&lt;span class="nv">CXX_COMPILER_ID:AppleClang&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="s">&amp;gt;:-Wall&lt;/span> &lt;span class="s">-Wextra&lt;/span> &lt;span class="s">-Wpedantic&lt;/span> &lt;span class="s">-Werror&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Dengan metode ini, kita dapat mencegah file &lt;code>CMakeLists.txt&lt;/code> menjadi sulit dibaca karena terlalu banyak percabangan kondisional seperti &lt;code>if(MSVC)&lt;/code>, serta memungkinkan pengaturan yang fleksibel untuk setiap target.&lt;/p>
&lt;h2 id="7-membangun-lingkungan-pengujian-ctest">7. Membangun Lingkungan Pengujian (CTest)
&lt;/h2>&lt;p>Dalam penjaminan mutu pada lingkungan lintas platform, penerapan pengujian otomatis adalah suatu keharusan. CMake sudah dilengkapi dengan test runner standar bernama &lt;strong>CTest&lt;/strong>.&lt;/p>
&lt;p>Berikut adalah langkah-langkah untuk mengintegrasikan GoogleTest, yang dimasukkan menggunakan &lt;code>FetchContent&lt;/code> sebelumnya, dengan CTest.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;span class="lnt">9
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Mengaktifkan fitur pengujian (ditulis sekali saja di CMakeLists.txt pada root)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">enable_testing&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">add_executable&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyMathTests&lt;/span> &lt;span class="s">test/math_test.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">target_link_libraries&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyMathTests&lt;/span> &lt;span class="s">PRIVATE&lt;/span> &lt;span class="s">gtest_main&lt;/span> &lt;span class="s">MyLib&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Mendaftarkan sebagai tes ke dalam CTest
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">include&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">GoogleTest&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">gtest_discover_tests&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyMathTests&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Setelah build, hanya dengan menjalankan perintah &lt;code>ctest&lt;/code> di dalam direktori build, semua tes akan dieksekusi dan hasilnya akan dilaporkan.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cd&lt;/span> build
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">ctest --output-on-failure -C Release
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="8-teori-sistem-build-dan-model-matematis">8. Teori Sistem Build dan Model Matematis
&lt;/h2>&lt;p>Mari ubah perspektif sejenak dan pertimbangkan efisiensi sistem build serta kompilasi paralel pada proyek berskala besar menggunakan model matematis.&lt;/p>
&lt;p>Pengurangan waktu build (waktu kompilasi) adalah tantangan abadi dalam pengembangan C++. Waktu build dapat dipersingkat dengan memecah kode sumber dan melakukan kompilasi secara paralel. Peningkatan kecepatan (Speedup) akibat paralelisasi ini dimodelkan oleh &lt;strong>Hukum Amdahl (Amdahl&amp;rsquo;s Law)&lt;/strong>.&lt;/p>
&lt;p>Jika porsi program yang dapat diparalelkan adalah $P$, porsi yang harus dieksekusi secara berurutan (tidak dapat diparalelkan) adalah $1-P$, dan jumlah prosesor yang digunakan adalah $N$, maka rasio peningkatan kecepatan maksimal secara teoretis $S(N)$ dinyatakan dengan persamaan berikut.&lt;/p>
$$ S(N) = \frac{1}{(1 - P) + \frac{P}{N}} $$
&lt;p>Pada proses build C++, &amp;ldquo;kompilasi dari setiap file &lt;code>.cpp&lt;/code> menjadi &lt;code>.o&lt;/code> atau &lt;code>.obj&lt;/code>&amp;rdquo; bersifat independen dan dapat diparalelkan (bagian $P$), namun &amp;ldquo;proses penggabungan akhir oleh penaut (Linker)&amp;rdquo; pada dasarnya dilakukan secara berurutan (bagian $1-P$).&lt;/p>
&lt;p>Oleh karena itu, sebanyak apa pun inti CPU ($N \to \infty$) yang disiapkan, selama kemacetan proses tautan (link time) masih ada, rasio kecepatan maksimum asimtotiknya adalah terhadap rumus berikut:&lt;/p>
$$ \lim_{N \to \infty} S(N) = \frac{1}{1 - P} $$
&lt;p>Yang disiratkan dari persamaan ini adalah &amp;ldquo;sekadar menambah inti CPU memiliki batasan dalam mempercepat waktu build&amp;rdquo;. Pada Modern CMake, penggunaan &lt;code>PRIVATE&lt;/code> dan &lt;code>INTERFACE&lt;/code> secara tepat serta meminimalkan dependensi file header (seperti pemanfaatan deklarasi maju/forward declaration) dapat meningkatkan proporsi $P$ dan mengurangi target yang harus dikompilasi ulang selama build bertahap (incremental build), yang mana secara praktis merupakan strategi paling efektif untuk mempercepat build.&lt;/p>
&lt;p>Selain itu, untuk mempercepat waktu tautan (link time), sangat penting untuk beralih dari pustaka statis (Static Library) ke pustaka bersama / DLL (Shared Library), atau mengadopsi linker cepat seperti LLD / Mold.&lt;/p>
&lt;p>Di CMake, Anda dapat dengan mudah menentukan linker sebagai berikut.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Pengaturan untuk menggunakan linker lld di lingkungan Clang/GCC
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">if&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">UNIX&lt;/span> &lt;span class="s">AND&lt;/span> &lt;span class="s">NOT&lt;/span> &lt;span class="s">APPLE&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span> &lt;span class="nb">target_link_options&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">MyAwesomeApp&lt;/span> &lt;span class="s">PRIVATE&lt;/span> &lt;span class="s2">&amp;#34;-fuse-ld=lld&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">endif&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="9-contoh-praktis-struktur-direktori-yang-kompleks">9. Contoh Praktis Struktur Direktori yang Kompleks
&lt;/h2>&lt;p>Dalam pengembangan aplikasi yang sebenarnya, struktur direktorinya akan terdiri dari berbagai modul yang digabungkan. Terakhir, berikut adalah struktur direktori proyek skala menengah yang ideal dan hubungan antara &lt;code>CMakeLists.txt&lt;/code> induk dan anak.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">ProjectRoot/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── CMakeLists.txt (Root: Definisi keseluruhan proyek)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── vcpkg.json (Definisi pustaka dependensi)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── external/ (Modul eksternal)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── include/ (Header publik)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └── myapp/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">├── src/ (Kode sumber dan definisi build internal)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├── CMakeLists.txt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├── main.cpp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├── math/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ ├── CMakeLists.txt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ ├── Vector3.hpp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ │ └── Vector3.cpp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └── network/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ ├── CMakeLists.txt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">│ └── NetworkManager.cpp
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">└── tests/ (Kode pengujian)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> ├── CMakeLists.txt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> └── math_test.cpp
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>File &lt;code>CMakeLists.txt&lt;/code> pada root hanya berisi pengaturan lingkungan dan definisi opsi keseluruhan, lalu menambahkan subdirektori menggunakan &lt;code>add_subdirectory()&lt;/code>.&lt;/p>
&lt;p>&lt;strong>Root &lt;code>CMakeLists.txt&lt;/code>&lt;/strong>:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="nb">cmake_minimum_required&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">VERSION&lt;/span> &lt;span class="s">3.20&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">project&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">ComplexApp&lt;/span> &lt;span class="s">LANGUAGES&lt;/span> &lt;span class="s">CXX&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Pengaturan global
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">CMAKE_CXX_STANDARD&lt;/span> &lt;span class="s">20&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">set&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">CMAKE_CXX_STANDARD_REQUIRED&lt;/span> &lt;span class="s">ON&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Mengaktifkan pengujian
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">enable_testing&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Menambahkan subdirektori
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_subdirectory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">src&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">add_subdirectory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">tests&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;strong>&lt;code>src/CMakeLists.txt&lt;/code>&lt;/strong>:&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># Menambahkan setiap modul
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_subdirectory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">math&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">add_subdirectory&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">network&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># File eksekusi akhir
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">add_executable&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">ComplexApp&lt;/span> &lt;span class="s">main.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># Penautan modul
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">target_link_libraries&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">ComplexApp&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">PRIVATE&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">MathLib&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="s">NetworkLib&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Dengan membagi &lt;code>CMakeLists.txt&lt;/code> untuk setiap direktori dengan cara ini dan mendefinisikannya sebagai dependensi antar target, reusabilitas modul menjadi lebih tinggi, dan paralelisme build pun meningkat. Inilah nilai sesungguhnya dari &amp;ldquo;lingkungan build termodularisasi&amp;rdquo; yang diusung oleh Modern CMake.&lt;/p>
&lt;h2 id="10-kesimpulan">10. Kesimpulan
&lt;/h2>&lt;p>Kami telah menjelaskan langkah-langkah untuk membangun lingkungan build C++ lintas platform menggunakan CMake.
Mari kita ulas poin-poin utamanya.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Pemahaman Sistem Meta-Build&lt;/strong>: CMake adalah alat yang menghasilkan skrip build.&lt;/li>
&lt;li>&lt;strong>Penerapan Penuh Modern CMake&lt;/strong>: Hindari penggunaan variabel; enkapsulasi konfigurasi secara &lt;strong>berorientasi target&lt;/strong> menggunakan perintah seperti &lt;code>add_executable&lt;/code>, &lt;code>target_link_libraries&lt;/code>, dan &lt;code>target_include_directories&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Pengaturan Lingkup yang Tepat&lt;/strong>: Gunakan &lt;code>PUBLIC&lt;/code>, &lt;code>PRIVATE&lt;/code>, dan &lt;code>INTERFACE&lt;/code> secara tepat untuk mengontrol penyebaran dependensi.&lt;/li>
&lt;li>&lt;strong>Penerapan Penuh Out-of-source Build&lt;/strong>: Lakukan build di dalam direktori &lt;code>build/&lt;/code> dan hindari mengotori source tree.&lt;/li>
&lt;li>&lt;strong>Integrasi Pihak Ketiga&lt;/strong>: Manfaatkan &lt;code>FetchContent&lt;/code> atau &lt;code>vcpkg&lt;/code> untuk mengotomatisasi penyelesaian dependensi pustaka.&lt;/li>
&lt;li>&lt;strong>Pemanfaatan Ekspresi Generator&lt;/strong>: Menyerap perbedaan flag tiap kompiler secara elegan.&lt;/li>
&lt;li>&lt;strong>Pendekatan Matematis&lt;/strong>: Perhatikan Hukum Amdahl, kurangi dependensi untuk meningkatkan efisiensi kompilasi paralel.&lt;/li>
&lt;/ol>
&lt;p>Meski awalnya mungkin terasa sulit, namun setelah Anda menguasai konsep target dan properti, sekompleks dan sebesar apa pun proyek C++ yang ditangani, Anda akan dapat menjaga lingkungan build yang tertata rapi. Silakan jadikan artikel ini sebagai referensi dan cobalah membangun lingkungan pengembangan C++ dengan sintaks Modern CMake terbaru.&lt;/p></description></item></channel></rss>