Giao diện
📦 Package Management Essential
Dependency Hell là vấn đề lớn nhất của C++ ecosystem. Conan và Vcpkg là giải pháp.
Tại sao cần Package Manager?
Cách "cổ điển" quản lý dependencies
# "Solutions" phổ biến nhưng SAI
project/
├── external/
│ ├── boost-1.74/ # Copy thủ công 50MB source
│ ├── fmt/ # git clone
│ └── openssl/ # ???
└── CMakeLists.txt❌ ANTI-PATTERNS
| Cách làm | Vấn đề |
|---|---|
| Copy source vào repo | Bloated repo, không update được |
git submodule | Conflict hell, recursive init |
| Download .zip thủ công | Không versioning, "works on my machine" |
| System package manager | Khác versions giữa Ubuntu/macOS/Windows |
Cách đúng: Centralized Package Manager
┌─────────────────────────────────────────────────────────────────────────┐
│ PACKAGE MANAGER WORKFLOW │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ 1. DECLARE │
│ ──────────── │
│ conanfile.txt / vcpkg.json │
│ ├── fmt/9.1.0 │
│ ├── spdlog/1.11.0 │
│ └── boost/1.81.0 │
│ │
│ 2. INSTALL │
│ ──────────── │
│ conan install . / vcpkg install │
│ → Download prebuilt binaries (hoặc build from source) │
│ → Cache globally (~/.conan2 / vcpkg root) │
│ │
│ 3. INTEGRATE │
│ ──────────── │
│ find_package(fmt REQUIRED) │
│ target_link_libraries(app PRIVATE fmt::fmt) │
│ │
│ ✅ Version locked │
│ ✅ Cross-platform │
│ ✅ Reproducible builds │
│ │
└─────────────────────────────────────────────────────────────────────────┘Conan vs Vcpkg — So sánh
| Aspect | Conan | Vcpkg |
|---|---|---|
| Creator | JFrog | Microsoft |
| Philosophy | Decentralized (như npm) | Centralized (1 registry) |
| Configuration | Python (conanfile.py) hoặc Text | JSON (vcpkg.json) |
| Binary Caching | Built-in, powerful | Có, khó setup hơn |
| CMake Integration | CMakeToolchain, CMakeDeps | Toolchain file |
| Learning Curve | Medium | Easy |
| Best For | Large projects, custom builds | Quick start, Microsoft stack |
🎯 PENALGO Recommendation
- Beginners/Microsoft stack: Vcpkg
- Advanced/Cross-platform: Conan
Cả hai đều production-ready. Chọn 1 và stick with it.
Conan — The Pythonic Way
Installation
powershell
# Via pip (recommended)
pip install conan
# Verify
conan --version # Conan version 2.xProject Setup với Conan
project/
├── CMakeLists.txt
├── conanfile.txt # Dependency declaration
└── src/
└── main.cppconanfile.txt
ini
[requires]
fmt/10.1.1
spdlog/1.12.0
nlohmann_json/3.11.2
[generators]
CMakeDeps
CMakeToolchain
[layout]
cmake_layoutCMakeLists.txt (với Conan)
cmake
cmake_minimum_required(VERSION 3.20)
project(MyApp LANGUAGES CXX)
# find_package hoạt động nhờ CMakeDeps generator
find_package(fmt REQUIRED)
find_package(spdlog REQUIRED)
find_package(nlohmann_json REQUIRED)
add_executable(app src/main.cpp)
target_link_libraries(app PRIVATE
fmt::fmt
spdlog::spdlog
nlohmann_json::nlohmann_json
)
target_compile_features(app PRIVATE cxx_std_20)Build Workflow
powershell
# 1. Install dependencies
conan install . --output-folder=build --build=missing
# 2. Configure CMake (sử dụng toolchain từ Conan)
cmake -B build -DCMAKE_TOOLCHAIN_FILE=build/conan_toolchain.cmake
# 3. Build
cmake --build buildGiải thích Workflow
┌─────────────────────────────────────────────────────────────────────────┐
│ CONAN WORKFLOW BREAKDOWN │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ conan install . --output-folder=build --build=missing │
│ ───────────────────────────────────────────────────── │
│ │
│ 1. Đọc conanfile.txt │
│ 2. Resolve dependency graph (fmt depends on nothing, │
│ spdlog depends on fmt, etc.) │
│ 3. Download prebuilt binaries từ Conan Center │
│ (hoặc build from source nếu --build=missing) │
│ 4. Generate: │
│ - conan_toolchain.cmake (compiler settings) │
│ - fmt-config.cmake, spdlog-config.cmake, ... │
│ │
│ cmake --preset conan-default │
│ ───────────────────────────── │
│ │
│ CMake tìm packages qua generated *-config.cmake files │
│ find_package(fmt) → loads build/fmt-config.cmake │
│ │
└─────────────────────────────────────────────────────────────────────────┘Vcpkg — The Microsoft Way
Installation
powershell
# Clone vcpkg
git clone https://github.com/microsoft/vcpkg.git
cd vcpkg
# Bootstrap (Windows)
.\bootstrap-vcpkg.bat
# Bootstrap (Linux/macOS)
./bootstrap-vcpkg.sh
# Add to PATH
$env:PATH += ";$PWD"Project Setup với Vcpkg (Manifest Mode)
project/
├── CMakeLists.txt
├── vcpkg.json # Manifest file
├── vcpkg-configuration.json # (optional) registry config
└── src/
└── main.cppvcpkg.json
json
{
"name": "my-app",
"version": "1.0.0",
"dependencies": [
"fmt",
"spdlog",
"nlohmann-json"
],
"builtin-baseline": "2024.01.12"
}CMakeLists.txt (với Vcpkg)
cmake
cmake_minimum_required(VERSION 3.20)
project(MyApp LANGUAGES CXX)
find_package(fmt CONFIG REQUIRED)
find_package(spdlog CONFIG REQUIRED)
find_package(nlohmann_json CONFIG REQUIRED)
add_executable(app src/main.cpp)
target_link_libraries(app PRIVATE
fmt::fmt
spdlog::spdlog
nlohmann_json::nlohmann_json
)
target_compile_features(app PRIVATE cxx_std_20)Build Workflow
powershell
# Configure với vcpkg toolchain
cmake -B build -DCMAKE_TOOLCHAIN_FILE=[vcpkg-root]/scripts/buildsystems/vcpkg.cmake
# Build
cmake --build build💡 VCPKG_ROOT Environment Variable
powershell
# Set permanently
[Environment]::SetEnvironmentVariable("VCPKG_ROOT", "C:\vcpkg", "User")
# Then use
cmake -B build -DCMAKE_TOOLCHAIN_FILE=$env:VCPKG_ROOT/scripts/buildsystems/vcpkg.cmakePractical Lab: fmt Library
Goal
Setup project sử dụng fmt library qua package manager.
main.cpp
cpp
// src/main.cpp
#include <fmt/core.h>
#include <fmt/color.h>
#include <vector>
int main() {
// Basic formatting
fmt::print("Hello, {}!\n", "World");
// Number formatting
fmt::print("Pi = {:.4f}\n", 3.14159265);
// Colored output
fmt::print(fg(fmt::color::green), "Success: {}\n", "Build completed");
// Container formatting (fmt 10+)
std::vector<int> nums = {1, 2, 3, 4, 5};
fmt::print("Numbers: {}\n", nums);
return 0;
}Using Conan
ini
# conanfile.txt
[requires]
fmt/10.1.1
[generators]
CMakeDeps
CMakeToolchainpowershell
conan install . --output-folder=build --build=missing
cmake -B build -DCMAKE_TOOLCHAIN_FILE=build/conan_toolchain.cmake
cmake --build build
./build/appUsing Vcpkg
json
// vcpkg.json
{
"name": "fmt-demo",
"dependencies": ["fmt"]
}powershell
cmake -B build -DCMAKE_TOOLCHAIN_FILE=$env:VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake
cmake --build build
./build/app.exeConan Profile — Cross-Platform Builds
ini
# ~/.conan2/profiles/linux-gcc12
[settings]
os=Linux
compiler=gcc
compiler.version=12
compiler.libcxx=libstdc++11
build_type=Release
arch=x86_64
[conf]
tools.cmake.cmaketoolchain:generator=Ninjaini
# ~/.conan2/profiles/windows-msvc
[settings]
os=Windows
compiler=msvc
compiler.version=193 # VS 2022
build_type=Release
arch=x86_64powershell
# Build for specific profile
conan install . -pr:b=default -pr:h=linux-gcc12Version Constraints
Conan
ini
# conanfile.txt
[requires]
fmt/[>=10.0 <11.0] # SemVer range
spdlog/1.12.0 # Exact version
boost/[~1.80] # ~= allows patch updates (1.80.x)Vcpkg
json
{
"dependencies": [
{
"name": "fmt",
"version>=": "10.0.0"
}
],
"overrides": [
{
"name": "fmt",
"version": "10.1.1"
}
]
}Private/Enterprise Registry
Conan
powershell
# Add private remote
conan remote add mycompany https://conan.mycompany.com
conan remote login mycompany username
# Priority order
conan remote listVcpkg
json
// vcpkg-configuration.json
{
"registries": [
{
"kind": "git",
"repository": "https://github.com/mycompany/vcpkg-registry",
"baseline": "abc123...",
"packages": ["internal-lib-*"]
}
]
}Best Practices
┌─────────────────────────────────────────────────────────────────────────┐
│ PACKAGE MANAGEMENT BEST PRACTICES │
├─────────────────────────────────────────────────────────────────────────┤
│ │
│ ✅ DO │
│ ───── │
│ • Lock versions trong manifest (reproducibility) │
│ • Use manifest mode, không classic mode │
│ • Cache binaries trong CI (conan cache, vcpkg binary caching) │
│ • Test với multiple compiler versions │
│ • Document required dependencies trong README │
│ │
│ ❌ DON'T │
│ ─────── │
│ • Mix package managers (Conan + Vcpkg = disaster) │
│ • Commit build artifacts hoặc installed packages │
│ • Use system packages cho portability-critical deps │
│ • Ignore transitive dependency conflicts │
│ • Hardcode paths trong CMakeLists.txt │
│ │
└─────────────────────────────────────────────────────────────────────────┘Library Compatibility Guarantee
| Library | Versioning | Compatibility |
|---|---|---|
| fmt | SemVer | Breaking changes in major versions |
| spdlog | SemVer | API stable across minor versions |
| Boost | Own scheme | Mostly backwards compatible |
| nlohmann_json | SemVer | Very stable API |
⚠️ BOOST WARNING
Boost là dependency nặng (~500MB). Chỉ thêm khi thực sự cần. Prefer standalone alternatives:
boost::optional→std::optional(C++17)boost::filesystem→std::filesystem(C++17)boost::asio→ vẫn cần, chưa có std alternative