C++
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Object-Oriented C++
-
Section 4: Memory Management
-
Section 5: Templates and Generic Programming
-
Section 6: The Standard Template Library
-
Section 7: Modern C++ Features
-
Section 8: Error Handling
-
Section 9: Multithreading
-
Section 10: Operator Overloading and Type Conversion
-
Section 11: Advanced Topics
-
Section 12: Tooling and Build Systems
-
Section 13: Design Patterns in C++
-
Section 14: Interfacing with C and Systems Programming
-
Section 15: Networking and IPC Basics
-
Section 16: Graphics and Game Programming Basics
-
Section 17: The Boost Libraries
-
Section 18: Data Structures and Algorithms in C++
-
Section 19: Practical Projects
-
Section 20: More Concurrency Patterns
-
Section 21: More OOP and Design Practice
-
Section 22: File I/O and Streams
-
Section 23: More Standard Library
-
Section 24: Practice Exercises
-
Section 25: Interview and Algorithm Practice
-
Section 26: Compiler and Language Internals
-
Section 27: GUI and Application Frameworks Overview
-
Section 28: Testing and Quality Practices
-
Section 29: Numerics Library
-
Section 30: Concepts Library (C++20)
-
Section 31: Ranges Library (C++20) In Depth
-
Section 32: More Utility Library
127: Managing Dependencies with vcpkg or Conan
I remember the first time I tried to bring a third-party library into a professional project. I just downloaded the source code for a JSON parser, tossed it into a folder called /third_party, and manually added the include paths to my build script. At the time, it felt like the most direct way to get the job done. No fancy tools, no abstraction—just the code I needed, right there in my directory. It worked perfectly on my machine, and for about a week, I thought I'd cracked the code on efficiency.
The "It Works on My Machine" Wall
The problem with the manual approach—whether you're vendoring code directly into your repo or relying on apt-get install to put libraries in /usr/local/lib—is that you aren't actually managing dependencies; you're just documenting a coincidence. The moment I pushed that code to a teammate, everything exploded. They had a slightly different version of the compiler, a different OS patch level, and they didn't have the same system-level libraries I'd installed six months prior. We spent an entire afternoon debugging "missing header" errors instead of actually writing features.
When you rely on system-wide installations, you're playing a dangerous game of version roulette. What happens when Project A needs OpenSSL 1.1 but Project B requires OpenSSL 3.0? You can't easily have both installed globally without creating a linking nightmare. I've seen developers spend days fighting with LD_LIBRARY_PATH just to get a binary to run, and frankly, it's a waste of your talent.
Moving to a Manifest-Based World
The professional way to handle this is to treat your dependencies as a declared list, not a manual chore. This is where vcpkg and Conan come in. Instead of "installing" things in the traditional sense, you create a manifest file—like vcpkg.json or a conanfile.txt—that explicitly states: "This project requires fmt version 10.1.1 and nlohmann-json version 3.11.2."
When a new developer clones your repo, they don't have to go on a scavenger hunt for libraries. They run a single command, and the package manager handles the downloading, patching, and compiling of those libraries specifically for their current compiler and architecture. It turns a four-hour onboarding process into a five-minute automated script. I prefer this because it decouples the library's existence from the operating system; the library belongs to the project, not the machine.
The Trade-off: Tooling Overhead vs. Sanity
Now, I'll be honest with you: adding a package manager introduces a new layer of complexity. You have to learn how to integrate the tool with your CMake configuration, and occasionally, the package manager itself might have a bug or a missing version of a niche library. You're trading a bit of initial setup time for a massive increase in long-term stability.
If you're deciding between the two major players, here is how I usually look at it:
- vcpkg feels more integrated with the Microsoft ecosystem (though it's cross-platform) and generally plays very nicely with CMake via a "toolchain file." It's often easier to get started with if you want something that "just works" with Visual Studio.
- Conan is more of a powerhouse. It's designed for complex enterprise environments where you might need to host your own private binaries (a "Conan server") to avoid recompiling the same heavy library on every single build agent in your CI/CD pipeline.
Regardless of which one you pick, the goal is the same: your build should be reproducible. If I can check out your code on a clean Linux VM and have it compile without me manually installing a single -dev package, you've won.
📋 Practical Task
Integrating fmt and nlohmann_json via vcpkg
Your goal is to move a project from "manual header inclusion" to a managed dependency system. You have a small utility that parses a configuration file and prints a formatted status report, but currently, it only compiles if the user has manually installed fmt and nlohmann_json to their system paths.
The Requirements:
- Create a
vcpkg.jsonmanifest file in your project root that declares dependencies forfmtandnlohmann-json. - Modify your
CMakeLists.txtto usefind_package()for both libraries instead of relying on hardcoded include paths. - Link the libraries to your executable using
target_link_libraries(). - Successfully compile the project by passing the vcpkg toolchain file to CMake (e.g.,
-DCMAKE_TOOLCHAIN_FILE=[vcpkg root]/scripts/buildsystems/vcpkg.cmake).
Verification: The program should successfully compile and run, using nlohmann::json to parse a string and fmt::print to output the result to the console, without any libraries being installed globally on your operating system.
There are no comments for now.