





















































Hi ,
Welcome to a brand new issue of ProgrammingPro.
In today’sExpert Insight, we bring you an excerpt from the recently published book, Minimal CMake, which explains how to simplify project onboarding using ExternalProject_Add
to automate dependency management, reducing manual setup and improving build efficiency by consolidating multiple steps into a single command.
News Highlights: Python 3.14’s interpreter boosts performance by 30%; VS Code 1.97 makes Copilot an “out-of-the-box” feature with predictive edits; JetBrains AI Assistant adds local LLM support; Go 1.24 introduces generic type aliases and runtime improvements.
My top 5 picks from today’s learning resources:
But there’s more, so dive right in.
Stay Awesome!
Divya Anne Selvaraj
Editor-in-Chief
PS:We're conducting market research to better understand the evolving landscape of software engineering and architecture – including how professionals like you learn, grow and adapt to the impact of AI.
We think your insights would be incredibly valuable, and would love to hear what you have to say in aquick 1:1 conversationwith our team.
What's in it for you?
✅ Abrief 20–30 minute conversationat a time that’s convenient for you
✅ An opportunity toshare your experiences and shape the future of learning
✅A free credit to redeem any eBook of your choicefrom our library as a thank-you
How to Participate:
Schedule a quick call at your convenience using the link provided after the form:
https://forms.office.com/e/Bqc7gaDCKq
Looking forward to speaking with you soon!
Thank you,
Team Packt.
go vet
, and more.using
keyword can simplify test isolation by automatically managing resources like test databases and mock servers.satisfies
operator: Explains how the operator enforces type constraints without altering inferred types, its syntax, and practical use cases for validating object properties.rill
concurrency toolkit to improve performance.acts_as_paranoid
for data retention and a structured audit log system.Here’s an excerpt from “Chapter 8: Using Super Builds to Simplify Onboarding" in the book, Minimal CMake, by Tom Hulton-Harrop, published in January 2025.
In the previous chapter, we stuck largely to manual CMake build and install commands (along with a bit of help from CMake presets) to increase our familiarity with CMake, and to work at a slightly lower level of abstraction to understand what CMake is doing behind
the scenes. Now that we’re a bit morecomfortable with these concepts, it’s time to remove the tedium of navigating to each individual library folder and running the familiar CMake commandsthat follow:
cmake --preset <preset-name>
cmake --build <build-folder> --target install
We can start updating our project to take advantage of the more useful features that CMake provides. To start with, we’re going to update our existing third-partyCMakeLists.txt
file to bring in not only SDL 2 and bgfx but also the libraries we created and depend on. This will remove the need for us to manually install them and allow us to run a single pair of CMake commands (configure and build/install) to retrieve all the dependencies we need for ourGame ofLifeapplication.
Let’s start by looking atch8/part-1/third-party/CMakeLists.txt
. The file is largely the same as before, only underneath our existingExternalProject_Add
commands, we’ve added references to our libraries foundinch8/part-1/lib
.
Here is an example of themc-array
library:
ExternalProject_Add(
mc-array
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../lib/array
BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/mc-array-build/${build_type_dir}
INSTALL_DIR ${CMAKE_CURRENT_SOURCE_DIR}/install
CMAKE_ARGS ${build_type_arg} -DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
CMAKE_CACHE_ARGS -DCMAKE_DEBUG_POSTFIX:STRING=d)
The command should look remarkably similar to those we covered inChapter 6,Installing Dependencies and ExternalProject_Add. The only real difference is the reference toSOURCE_DIR
. Given the slightly unconventional layout of this book’s repository, we can reference the source folder directly, as the library source code is stored in thesame repository:
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../lib/array
It would normally be the case that we’d refer to an external library using aURL
orGIT_REPOSITORY
link. If we did, for some reason, want to refer to an older version of one of the libraries at a specific moment in the Git history of our project, we could usethis approach:
ExternalProject_Add(
mc-array
GIT_REPOSITORY https://github.com/PacktPublishing/Minimal-CMake.git
GIT_TAG 18535c9d140e828895c57dbb39b97a3307f846ab
SOURCE_SUBDIR ch8/part-1/lib/array
...
We did the same thing inChapter 3,Using FetchContent with External Dependencies, when usingFetchContent
. The preceding command will clone the entire repository into the build folder of our third-partyCMakeList.txt
file, and then treat thech8/part-1/lib/array
directory as the root of the repository (at least as far asExternalProject_Add
is concerned). It’s not often needed but can be useful if a repository holds more than oneCMake project.
While we’re making changes tothird-party/CMakeLists.txt
, we’ll also make one small improvement to how we handle our bgfx dependency. When bgfx was first introduced inChapter 6,Installing Dependencies and ExternalProject_Add(seech6/part-4
), we wound up needing to clone the repository twice, once for the static version of the library (needed to build the tools), and again for the shared version of the library that our application linked against. The good news is there’s a handy technique we can apply to download the library once. The following is an extract of the changes with thedifferences highlighted:
ExternalProject_Add(
bgfxt
GIT_REPOSITORY https://github.com/bkaradzic/bgfx.cmake.git
GIT_TAG v1.127.8710-464
...
ExternalProject_Get_Property(bgfxt SOURCE_DIR)
ExternalProject_Add(
bgfx
URL "file://${SOURCE_DIR}"
DEPENDS bgfxt
...
The firstExternalProject_Add
call is the same as before; we let it know the repository and specificGIT_TAG
to download. However, in the second version, instead of repeating those lines, we first callExternalProject_Get_Property
, passing thebgfxt
target and theSOURCE_DIR
property.SOURCE_DIR
will be populated with the location of thebgfxt
source code once it’s downloaded, and in the second command, we point thebgfx
target to reference that source code location. As the code is identical and it’s just how we’re building it that’s different, this saves a bit of time and network bandwidth downloading the same files allover again.
You might have noticed that we’re usingURL "file://${SOURCE_DIR}"
as opposed toSOURCE_DIR ${SOURCE_DIR}
. This is because if we tried to useSOURCE_DIR
, theExternalProject_Add
command would fail at configure time becauseSOURCE_DIR
is expected to already be present when we configure. As this isn’t the case with our dependency (the source forbgfxt
will only be downloaded and made available at build time), we can use theURL
option with a local file path shown byfile://
, which will cause the file path to instead be resolved atbuild time.
With the addition of the three newExternalProject_Add
calls referencing our libraries, when building our project, we only need to visit two directories, as opposed to the earlier five. We can navigate toch8/part-1/third-party
and run the followingCMake commands:
cmake -B build -G "Ninja Multi-Config"
cmake --build build --config Release
This will download, build, and install all our dependencies at once. We then only need to navigate toch8/part-1/app
and runthe following:
cmake --preset multi-ninja
cmake --build build/multi-ninja --config Release
This will build and link our application. We’ve also tidied up ourCMakePresets.json
file to haveCMAKE_PREFIX_PATH
only refer to${sourceDir}/../third-party/install
, as opposed to the numerous install folders we had for each of our internal dependencies in thelast chapter.
Finally, to launch the application, we first need to compile our shaders and then launch the application from our application rootdirectory (ch8/part-1/app
):
./compile-shader-<platform>.sh/bat
./build/multi-ninja/Release/minimal-cmake_game-of-life_window
This is a substantial improvement from before, but we can do better. The main build is still split across two stages (dependencies and application), and we still have the annoying issue of needing to remember to compile the shaders (an easy step to overlook). We want to achieve the holy grail of one command to bootstrap everything. Let’s start by seeing how we can solve the first problem by reducing our build steps from two to one...
Minimal CMakewas published in January 2025. Packt library subscribers can continue reading the entire book for free or you can buy the book here!
That’s all for today.
We have an entire range of newsletters with focused content for tech pros. Subscribe to the ones you find the most usefulhere.
If your company is interested in reaching an audience of developers, software engineers, and tech decision makers, you may want toadvertise with us.
If you have any suggestions or feedback, or would like us to find you a learning resource on a particular subject, just respond to this email!