Skip to content

📦 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àmVấn đề
Copy source vào repoBloated repo, không update được
git submoduleConflict hell, recursive init
Download .zip thủ côngKhông versioning, "works on my machine"
System package managerKhá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

AspectConanVcpkg
CreatorJFrogMicrosoft
PhilosophyDecentralized (như npm)Centralized (1 registry)
ConfigurationPython (conanfile.py) hoặc TextJSON (vcpkg.json)
Binary CachingBuilt-in, powerfulCó, khó setup hơn
CMake IntegrationCMakeToolchain, CMakeDepsToolchain file
Learning CurveMediumEasy
Best ForLarge projects, custom buildsQuick 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.x

Project Setup với Conan

project/
├── CMakeLists.txt
├── conanfile.txt        # Dependency declaration
└── src/
    └── main.cpp

conanfile.txt

ini
[requires]
fmt/10.1.1
spdlog/1.12.0
nlohmann_json/3.11.2

[generators]
CMakeDeps
CMakeToolchain

[layout]
cmake_layout

CMakeLists.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 build

Giả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.cpp

vcpkg.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.cmake

Practical 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
CMakeToolchain
powershell
conan install . --output-folder=build --build=missing
cmake -B build -DCMAKE_TOOLCHAIN_FILE=build/conan_toolchain.cmake
cmake --build build
./build/app

Using 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.exe

Conan 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=Ninja
ini
# ~/.conan2/profiles/windows-msvc
[settings]
os=Windows
compiler=msvc
compiler.version=193  # VS 2022
build_type=Release
arch=x86_64
powershell
# Build for specific profile
conan install . -pr:b=default -pr:h=linux-gcc12

Version 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 list

Vcpkg

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

LibraryVersioningCompatibility
fmtSemVerBreaking changes in major versions
spdlogSemVerAPI stable across minor versions
BoostOwn schemeMostly backwards compatible
nlohmann_jsonSemVerVery stable API

⚠️ BOOST WARNING

Boost là dependency nặng (~500MB). Chỉ thêm khi thực sự cần. Prefer standalone alternatives:

  • boost::optionalstd::optional (C++17)
  • boost::filesystemstd::filesystem (C++17)
  • boost::asio → vẫn cần, chưa có std alternative

Bước tiếp theo

Đã có dependency management, giờ tối ưu tốc độ build:

Ninja & CCache → — HPN Tunnel: Giảm build time từ phút xuống giây