Sampai Chapter lalu, semua target yang kita bangun CMake dibuat dari source yang kita tulis sendiri. Proyek nyata tidak bekerja begitu: hampir selalu ada library pihak ketiga yang kita butuhkan — untuk parsing JSON, kompresi, pengujian, atau format teks — dan kita tidak menulisnya ulang. CMake menyediakan tiga jalur resmi untuk menarik dependensi dari luar: add_subdirectory untuk source yang ikut hidup di dalam proyek, find_package untuk library yang sudah terpasang di sistem, dan FetchContent yang mengunduh source saat configure. Pada Chapter ini kita bedah ketiganya, dan satu program aplikasi kecil akan membuktikan bahwa source pemakai library tidak perlu berubah meski jalur penyediaannya berganti.
Tiga Jalur Menarik Dependensi #
Ketiga perintah berakhir di tempat yang sama — target library yang bisa di-link lewat target_link_libraries — tetapi sumber library-nya berbeda:
| Perintah | Sumber library | Kapan dipakai |
|---|---|---|
add_subdirectory | Folder source di dalam proyek | Source di-vendor atau di-pin sebagai git submodule |
find_package | Instalasi di sistem | Library sudah terpasang lewat manajer paket OS atau installer |
FetchContent | Repositori jarak jauh | Kita ingin CMake mengunduh dan membangunnya sendiri saat configure |
Semua jalur bekerja pada fase configure — ketika CMake membaca CMakeLists.txt — sehingga setelah fase itu selesai, CMake tidak lagi peduli library berasal dari mana; yang ada hanya daftar target. Keseragaman inilah yang membuat aplikasi kita bisa tetap diam.
add_subdirectory: Source di Dalam Proyek #
Jalur paling sederhana: taruh source library di dalam pohon proyek — folder libs/ atau external/ — yang punya CMakeLists.txt sendiri, lalu sertakan:
add_subdirectory(libs/geometri)
target_link_libraries(kalkulator PRIVATE geometri)add_subdirectory memasuki folder itu dan memproses CMakeLists.txt miliknya, sehingga target geometri yang dideklarasikan di sana ikut masuk ke build graph proyek kita. Dari titik itu, geometri diperlakukan persis seperti library internal pada Chapter CMake Targets. Cara ini membuat build kita self-contained: tidak ada prasyarat instalasi, dan versi library terkunci bersama proyek. Biayanya, repositori kita membawa source orang lain — itulah sebabnya strategi ini (dan cara mengelola pembaruannya lewat git submodule) kita bahas sebagai satu strategi utuh pada Chapter Dependency Management.
find_package: Library yang Terpasang di Sistem #
Bila library sudah terpasang — lewat apt, brew, vcpkg, atau installer lain — jalur yang benar adalah find_package:
find_package(fmt CONFIG REQUIRED)
target_link_libraries(kalkulator PRIVATE fmt::fmt)Saat configure, CMake menyisir lokasi-lokasi instalasi — termasuk folder pada variabel CMAKE_PREFIX_PATH dan prefix standar sistem — mencari file konfigurasi bernama fmtConfig.cmake (atau fmt-config.cmake) yang disertakan library itu. File inilah yang mendeklarasikan imported target fmt::fmt: target virtual yang sudah membawa informasi header, file library, dan dependensinya, sehingga satu baris target_link_libraries cukup untuk menyusun flag -I dan -l yang benar. Kata REQUIRED berarti bila paket tidak ditemukan, configure berhenti dengan pesan jelas — lebih baik daripada error undefined reference yang jauh di akhir build.
FetchContent: Mengunduh saat Configure #
Jalur ketiga menggabungkan keduanya: source tinggal di repositori jarak jauh, dan CMake yang mengunduhnya:
include(FetchContent)
FetchContent_Declare(
geometri
GIT_REPOSITORY https://example.com/geometri.git
GIT_TAG v1.2.0
)
FetchContent_MakeAvailable(geometri)Saat configure, FetchContent_MakeAvailable mengunduh repositori ke folder build/_deps/, lalu — persis seperti add_subdirectory — memasukkan CMakeLists.txt-nya ke build graph kita. Parameter GIT_TAG mengunci versi: commit atau tag itulah yang diambil, sehingga build tetap bisa direproduksi meski upstream bergerak. Perhatikan konsekuensinya: fase configure kini butuh jaringan, dan build pertama lebih lambat karena kompilasi dependensi ikut dikerjakan. Untuk library yang besar atau sering dipakai lintas proyek, dua jalur lain biasanya lebih hemat.
Aplikasi yang Tidak Berubah #
Kini bagian yang ingin kita buktikan. Library geometri yang sudah kita pakai sejak Chapter CMake Targets bisa disediakan lewat ketiga jalur di atas — dan source aplikasi pemakainya tidak berubah satu baris pun. Isi library-nya:
#pragma once
#include <numbers>
// Library mini geometri — header-only: semua fungsi inline di header.
inline double luasPersegi(double sisi) {
return sisi * sisi;
}
inline double luasSegitiga(double alas, double tinggi) {
return alas * tinggi / 2.0;
}
inline double luasLingkaran(double jariJari) {
return std::numbers::pi * jariJari * jariJari;
}Dan inilah aplikasinya — hanya memanggil fungsi library dan membandingkan hasilnya, tanpa tahu dari mana library itu datang. Sesuai kebiasaan chapter CMake di section ini, kita memverifikasinya langsung dengan g++ (lingkungan praktikum tidak memasang CMake, jadi blok cmake di atas kita baca sebagai ilustrasi alur):
#include <algorithm>
#include <iostream>
#include "geometri.h"
int main() {
double lingkaran = luasLingkaran(7.0);
double segitiga = luasSegitiga(14.0, 22.0);
double persegi = luasPersegi(12.0);
std::cout << "Lingkaran r=7 : " << lingkaran << "\n";
std::cout << "Segitiga 14x22 : " << segitiga << "\n";
std::cout << "Persegi 12 : " << persegi << "\n";
double terbesar = std::max({lingkaran, segitiga, persegi});
std::cout << "Terbesar : " << terbesar << "\n";
return 0;
}Output yang Dihasilkan:
Lingkaran r=7 : 153.938
Segitiga 14x22 : 154
Persegi 12 : 144
Terbesar : 154Baris #include "geometri.h" di pembanding.cpp adalah satu-satunya titik kontak dengan dunia luar: sisanya murni logika aplikasi. Ketika kelak jalur penyediaan library berganti — dari add_subdirectory ke find_package, misalnya setelah tim memutuskan memakai manajer paket — file ini tetap tidak tersentuh. Pembagian kerja inilah yang membuat CMake begitu lekat dengan ekosistem library C++: target sebagai bahasa bersama.
Memilih Jalur #
Tiga jalur itu bukan pesaing, melainkan tangga pilihan yang urutannya ditentukan keadaan:
- Library kecil, stabil, dan kodenya ingin terkunci bersama proyek →
add_subdirectory(atau submodule) — tanpa prasyarat jaringan. - Library sudah terpasang di semua mesin yang akan build →
find_package— build tercepat, tanpa kompilasi ulang. - Library hanya ada di repositori, dan kita tidak mau menyalinnya →
FetchContent— satuCMakeLists.txtmembawa semuanya.
Ketiga jalur ini mengatasi bagaimana menyertakan library, tetapi belum menjawab dari mana mendapatkan library yang terpasang di setiap mesin developer — di sinilah manajer paket masuk. Dua chapter berikutnya mengenalkan dua pemain utamanya: vcpkg dan Conan.
Referensi: find_package , FetchContent .