CMake Tutorial for C++: CMakeLists.txt, Targets,
이 글의 핵심
Learn CMake for C++ projects: CMakeLists.txt, add_executable, add_library, target_link_libraries, find_package, out-of-source builds, VS Code CMake Tools, and common link errors.
[C++ Hands-On Guide #4] CMake Introduction
Cross-language build tools: compare with Go modules (getting started, Rust/Cargo (intro, and Node/npm (modules.
After reading: You can write a minimal CMakeLists.txt, add executables/libraries, link targets, and call find_package for common dependencies.
When projects grow, typing long g++ ... lines for dozens of files breaks down. CMake is a build-system generator: you describe what to build in CMakeLists.txt, and CMake emits Makefiles, Ninja files, or IDE projects for each platform.
// 실행 예제 flowchart LR A[CMakeLists.txt] --> B[cmake configure] B --> C[Makefile / .sln / Ninja] C --> D[Build] D --> E[Binaries & libraries]
Previous: #3 VS Code — editor, tasks, debugging.
Requirements: CMake 3.10+, g++/Clang or MSVC. Linux/macOS: cmake + a compiler toolchain. Windows: Visual Studio or Build Tools + CMake recommended.
Table of contents
- Manual build pain scenarios
- Why CMake
- Install & concepts
- First CMakeLists.txt
- Multi-file project
- External libraries
- VS Code integration
- Troubleshooting
- Build performance
- Production patterns
1. Manual build pain
A three-person team starts with main.cpp, then adds utils.cpp, parser.cpp, … Every new file means editing a giant command line. Windows vs macOS scripts diverge (build.bat vs build.sh). Changing one .cpp may force full rebuilds if your script always compiles everything. CMake tracks dependencies and enables incremental builds.
g++ -std=c++17 -I./include src/main.cpp src/utils.cpp src/parser.cpp \
src/database.cpp src/network.cpp -L./lib -lsqlite3 -lpthread -o myapp
flowchart TB
subgraph manual[Manual g++]
M1[Add file] --> M2[Edit command]
M2 --> M3[Full recompile]
M3 --> M4[Per-OS scripts]
end
subgraph cm[CMake]
C1[Edit CMakeLists.txt] --> C2[cmake --build]
C2 --> C3[Incremental compile]
C3 --> C4[One config, all OSes]
end
2. Why CMake?
Manual commands don’t scale: -std, -I, -L, -l, different MSVC cl flags on Windows, no reliable incremental builds, and no automatic header dependency tracking.
CMake generates native build files, tracks dependencies, integrates with find_package, and works with VS Code, Visual Studio, CLion, etc.
sequenceDiagram
participant Dev as Developer
participant CMake as CMake
participant Gen as Generator
participant Build as Build tool
Dev->>CMake: cmake ..
CMake->>CMake: Parse CMakeLists.txt
CMake->>CMake: Detect toolchain
CMake->>Gen: Emit Ninja/Make/VS
Dev->>Build: cmake --build .
Build->>Dev: Artifacts
3. Install & core concepts
choco install cmake # Windows (Chocolatey)
brew install cmake # macOS
sudo apt install cmake # Debian/Ubuntu
cmake --version
Terms
- CMakeLists.txt — what to build.
- Build directory — e.g.
build/, separate from sources (out-of-source build). - Generator — Ninja, Make, Visual Studio, …
- Target — an executable or a library. | | Unix Makefiles | Ninja | |---|----------------|-------| | Speed | OK | Faster parallel builds | | Configure | slower | faster | | Common use | defaults | CI, large trees |
cmake -G Ninja ..
cmake --build .
4. First CMakeLists.txt
main.cpp
// g++ -std=c++20 main.cpp -o hello && ./hello
#include <iostream>
int main() {
std::cout << "Hello, CMake!" << std::endl;
return 0;
}
CMakeLists.txt
// 실행 예제
cmake_minimum_required(VERSION 3.15)
project(HelloCMake VERSION 1.0)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_executable(hello main.cpp)
Build
# 실행 예제
mkdir build && cd build
cmake ..
cmake --build .
./hello
Debug vs Release (single-config generators):
cmake -DCMAKE_BUILD_TYPE=Debug ..
cmake -DCMAKE_BUILD_TYPE=Release ..
5. Multi-file project (calculator-style)
Layout:
calculator/
├── CMakeLists.txt
├── main.cpp
├── src/operations.cpp
├── src/utils.cpp
├── include/operations.h
└── include/utils.h
CMakeLists.txt (library + executable)
// 실행 예제
cmake_minimum_required(VERSION 3.15)
project(Calculator VERSION 1.0)
set(CMAKE_CXX_STANDARD 20)
add_library(calculator_lib STATIC
src/operations.cpp
src/utils.cpp
)
target_include_directories(calculator_lib PUBLIC include)
add_executable(calculator main.cpp)
target_link_libraries(calculator PRIVATE calculator_lib)
# 실행 예제
mkdir build && cd build
cmake ..
cmake --build .
./calculator 10 + 5
// 실행 예제
flowchart TB
subgraph sources
main[main.cpp]
ops[operations.cpp]
util[utils.cpp]
end
subgraph headers
oh[operations.h]
uh[utils.h]
end
subgraph artifacts
lib[calculator_lib]
exe[calculator]
end
ops --> oh
util --> uh
ops --> lib
util --> lib
main --> exe
lib --> exe
Minimal copy-paste project: add_library(calc STATIC src/calc.cpp), target_include_directories(calc PUBLIC include), add_executable(calc_app main.cpp), target_link_libraries(calc_app PRIVATE calc).
6. External libraries — find_package
Example: nlohmann/json (adjust install command per OS).
find_package(nlohmann_json 3.11.0 REQUIRED)
add_executable(json_app main.cpp)
target_link_libraries(json_app PRIVATE nlohmann_json::nlohmann_json)
Discovery order (simplified): CMAKE_PREFIX_PATH, system paths, vcpkg/Conan toolchains, Find*.cmake / *Config.cmake.
7. VS Code
- Install CMake Tools.
- CMake: Select a Kit → CMake: Configure → build (F7).
- Optional
.vscode/settings.json:
{
"cmake.configureOnOpen": true,
"cmake.buildDirectory": "${workspaceFolder}/build",
"cmake.generator": "Ninja"
}
Enable CMAKE_EXPORT_COMPILE_COMMANDS for IntelliSense with compile commands.
8. Common errors
| Issue | Fix |
|---|---|
cmake: command not found | Install CMake; fix PATH |
| Version too old | brew upgrade cmake / snap install cmake |
Could NOT find package ... | Install dev package; set CMAKE_PREFIX_PATH; vcpkg toolchain |
| Header not found | target_include_directories |
undefined reference | target_link_libraries with correct imported target |
| Stale cache | Delete build/ and reconfigure |
flowchart TD
A[undefined reference] --> B{Your code or third party?}
B -->|Yours| C[add_library + link target]
B -->|Third party| D[find_package + imported target]
9. Build performance
cmake --build . -j$(nproc) # Linux
cmake --build . -j$(sysctl -n hw.ncpu) # macOS
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release ..
Optional: ccache, PCH (target_precompile_headers), parallel jobs.
10. Production patterns
- Modular trees with
add_subdirectory. - Use PRIVATE/PUBLIC/INTERFACE intentionally on
target_link_libraries. - CI: Ninja + ccache, pinned CMake & compiler versions.
- Shipping libraries:
install()rules +Config.cmakefor consumers.
See also
- CMake advanced
- Package managers
- Environment setup (01)
Keywords
CMake tutorial, CMakeLists.txt, add_executable, find_package, cross-platform C++, VS Code CMake, Ninja, out-of-source build.
Closing workflow
mkdir build && cd build
cmake ..
cmake --build .
./myapp
Next: Compilation process (#5)
Previous: VS Code setup (#3)
References
자주 묻는 질문 (FAQ)
Q. 이 내용을 실무에서 언제 쓰나요?
A. Learn CMake for C++ projects: CMakeLists.txt, add_executable, add_library, target_link_libraries, find_package, out-of-s… 실무에서는 위 본문의 예제와 선택 가이드를 참고해 적용하면 됩니다.
Q. 선행으로 읽으면 좋은 글은?
A. 각 글 하단의 이전 글 또는 관련 글 링크를 따라가면 순서대로 배울 수 있습니다. C++ 시리즈 목차에서 전체 흐름을 확인할 수 있습니다.
Q. 더 깊이 공부하려면?
A. cppreference와 해당 라이브러리 공식 문서를 참고하세요. 글 말미의 참고 자료 링크도 활용하면 좋습니다.
같이 보면 좋은 글 (내부 링크)
이 주제와 연결되는 다른 글입니다.
- [LNK2019 Unresolved External Symbol in C++: Five Causes and](/en/blog/cpp-error-01-lnk2019-unresolved-external/
- [Advanced CMake for C++: Multi-Target Projects, External](/en/blog/cpp-series-17-1-cmake-advanced/
- [Go in 2 Weeks #01](/en/blog/go-series-01-philosophy-syntax/
- [Getting Started with Rust | Memory-Safe Systems Programming](/en/blog/rust-series-01-intro/
- [Node.js Module System: CommonJS and ES Modules Explained](/en/blog/nodejs-series-02-modules/
이 글에서 다루는 키워드 (관련 검색어)
C++, CMake, CMakeLists.txt, Build automation, Cross-platform, find_package 등으로 검색하시면 이 글이 도움이 됩니다.