Discover millions of ebooks, audiobooks, and so much more with a free trial

From $11.99/month after trial. Cancel anytime.

Modern CMake for C++: Discover a better approach to building, testing, and packaging your software
Modern CMake for C++: Discover a better approach to building, testing, and packaging your software
Modern CMake for C++: Discover a better approach to building, testing, and packaging your software
Ebook833 pages6 hours

Modern CMake for C++: Discover a better approach to building, testing, and packaging your software

Rating: 4.5 out of 5 stars

4.5/5

()

Read preview

About this ebook

Creating top-notch software is an extremely difficult undertaking. Developers researching the subject have difficulty determining which advice is up to date and which approaches have already been replaced by easier, better practices. At the same time, most online resources offer limited explanation, while also lacking the proper context and structure.
This book offers a simpler, more comprehensive, experience as it treats the subject of building C++ solutions holistically. Modern CMake for C++ is an end-to-end guide to the automatization of complex tasks, including building, testing, and packaging. You'll not only learn how to use the CMake language in CMake projects, but also discover what makes them maintainable, elegant, and clean. The book also focuses on the structure of source directories, building targets, and packages. As you progress, you’ll learn how to compile and link executables and libraries, how those processes work, and how to optimize builds in CMake for the best results. You'll understand how to use external dependencies in your project – third-party libraries, testing frameworks, program analysis tools, and documentation generators. Finally, you'll get to grips with exporting, installing, and packaging for internal and external purposes.
By the end of this book, you’ll be able to use CMake confidently on a professional level.

LanguageEnglish
Release dateFeb 28, 2022
ISBN9781801071659
Modern CMake for C++: Discover a better approach to building, testing, and packaging your software

Related to Modern CMake for C++

Related ebooks

Software Development & Engineering For You

View More

Related articles

Reviews for Modern CMake for C++

Rating: 4.5 out of 5 stars
4.5/5

1 rating0 reviews

What did you think?

Tap to rate

Review must be at least 10 words

    Book preview

    Modern CMake for C++ - Rafał Świdziński

    Cover.png

    BIRMINGHAM—MUMBAI

    Modern CMake for C++

    Copyright © 2022 Packt Publishing

    All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.

    Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book.

    Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.

    Associate Group Product Manager: Richa Tripathi

    Publishing Product Manager: Rohit Rajkumar

    Senior Editor: Mark Dsouza

    Content Development Editor: Divya Vijayan

    Technical Editor: Joseph Aloocaran

    Copy Editor: Safis Editing

    Project Coordinator: Rashika Ba

    Proofreader: Safis Editing

    Indexer: Tejal Daruwale Soni

    Production Designer: Jyoti Chauhan

    Marketing Coordinator: Elizabeth Varghese

    First published: February 2022

    Production reference: 3131022

    Published by Packt Publishing Ltd.

    Livery Place

    35 Livery Street

    Birmingham

    B3 2PB, UK.

    ISBN 978-1-80107-005-8

    www.packt.com

    To my family: my parents, Bożena and Bogdan, my sisters, Ewelina and Justyna, and my wife, Katarzyna, for their ongoing support and advice.

    – Rafał Świdziński

    Contributors

    About the author

    Rafał Świdziński works as a staff engineer at Google. With over 10 years of professional experience as a full stack developer, he has been able to experiment with a vast multitude of programming languages and technologies. During this time, he has been building software under his own company and for corporations including Cisco Meraki, Amazon, and Ericsson.

    Originally from Łódź, Poland, he now lives in London, UK, from where he runs a YouTube channel, Smok, discussing topics related to software development. He tackles technical problems, including real-life and work-related challenges encountered by many people in the field. Throughout his work, he explains the technical concepts in detail and demystifies the art and science behind the role of software engineer. His primary focus is on high-quality code and the craftsmanship of programming.

    About the reviewers

    Sergio Guidi Tabosa Pessoa is a software engineer with more than 30 years of experience in software development and maintenance, from complex enterprise software projects to modern mobile applications. In the early days, he worked primarily with the Microsoft stack, but soon discovered the power of the UNIX and Linux operating systems. Even though he has worked with many languages over the years, C and C++ remain his favorite languages for their power and speed.

    He has a bachelor's degree in computer science and an MBA in IT management and is always hungry to learn new technologies, break code, and learn from his mistakes. He currently lives in Brazil with his wife, two Yorkshire Terriers, and two cockatiels.

    First and foremost, I would like to thank all the people involved in this project, including the author for crafting such a great piece of work, and Packt Publishing for giving me this opportunity. I also would like to thank my beautiful wife, Lucia, as well as Touché and Lion, for their patience and for allowing me the time needed to help with this book.

    Holding an engineering degree from ENSEEIHT and a Ph.D. in computer science from UVSQ in France, Eric Noulard has been writing and compiling source code in a variety of languages for 20 years. A user of CMake since 2006, he has also been an active contributor to the project for several years. During his career, Eric has worked for private companies and government agencies. He is now employed by Antidot, a software vendor responsible for developing and marketing high-end information retrieval technology and solutions.

    Mohammed Alqumairi is a software engineer at Cisco Meraki with experience in developing critical and performant backend services using a variety of languages and frameworks, with a particular focus on modern C++, CMake, and the Poco libraries. Mohammed graduated with honors from City, University of London, with a B.Sc. in Computer Science.

    Table of Contents

    Preface

    Section 1: Introducing CMake

    Chapter 1: First Steps with CMake

    Technical requirements

    Understanding the basics

    What is CMake?

    How does it work?

    Installing CMake on different platforms

    Docker

    Windows

    Linux

    macOS

    Building from the source

    Mastering the command line

    CMake

    CTest

    CPack

    The CMake GUI

    CCMake

    Navigating the project files

    The source tree

    The build tree

    Listfiles

    CMakeLists.txt

    CMakeCache.txt

    The Config-files for packages

    The cmake_install.cmake, CTestTestfile.cmake, and CPackConfig.cmake files

    CMakePresets.json and CMakeUserPresets.json

    Ignoring files in Git

    Discovering scripts and modules

    Scripts

    Utility modules

    Find-modules

    Summary

    Further reading

    Chapter 2: The CMake Language

    Technical requirements

    The basics of the CMake Language syntax

    Comments

    Command invocations

    Command arguments

    Working with variables

    Variable references

    Using the environment variables

    Using the cache variables

    How to correctly use the variable scope in CMake

    Using lists

    Understanding control structures in CMake

    Conditional blocks

    Loops

    Command definitions

    Useful commands

    The message() command

    The include() command

    The include_guard() command

    The file() command

    The execute_process() command

    Summary

    Further reading

    Chapter 3: Setting Up Your First CMake Project

    Technical requirements

    Basic directives and commands

    Specifying the minimum CMake version – cmake_minimum_required()

    Defining languages and metadata – project()

    Partitioning your project

    Scoped subdirectories

    Nested projects

    External projects

    Thinking about the project structure

    Scoping the environment

    Discovering the operating system

    Cross-compilation – what are host and target systems?

    Abbreviated variables

    Host system information

    Does the platform have 32-bit or 64-bit architecture?

    What is the endianness of the system?

    Configuring the toolchain

    Setting the C++ standard

    Insisting on standard support

    Vendor-specific extensions

    Interprocedural optimization

    Checking for supported compiler features

    Compiling a test file

    Disabling in-source builds

    Summary

    Further reading

    Section 2: Building With CMake

    Chapter 4: Working with Targets

    Technical requirements

    The concept of a target

    Dependency graph

    Visualizing dependencies

    Target properties

    What are transitive usage requirements?

    Dealing with conflicting propagated properties

    Meet the pseudo targets

    Build targets

    Writing custom commands

    Using a custom command as a generator

    Using a custom command as a target hook

    Understanding generator expressions

    General syntax

    Types of evaluation

    Examples to try out

    Summary

    Further reading

    Chapter 5: Compiling C++ Sources with CMake

    Technical requirements

    The basics of compilation

    How compilation works

    Initial configuration

    Managing sources for targets

    Preprocessor configuration

    Providing paths to included files

    Preprocessor definitions

    Configuring the headers

    Configuring the optimizer

    General level

    Function inlining

    Loop unrolling

    Loop vectorization

    Managing the process of compilation

    Reducing compilation time

    Finding mistakes

    Summary

    Further reading

    Chapter 6: Linking with CMake

    Technical requirements

    Getting the basics of linking right

    Building different library types

    Static libraries

    Shared libraries

    Shared modules

    Position-independent code

    Solving problems with the One Definition Rule

    Dynamically linked duplicated symbols

    Use namespaces – don't count on a linker

    The order of linking and unresolved symbols

    Separating main() for testing

    Summary

    Further reading

    Chapter 7: Managing Dependencies with CMake

    Technical requirements

    How to find installed packages

    Discovering legacy packages with FindPkgConfig

    Writing your own find-modules

    Working with Git repositories

    Providing external libraries through Git submodules

    Git-cloning dependencies for projects that don't use Git

    Using ExternalProject and FetchContent modules

    ExternalProject

    FetchContent

    Summary

    Further reading

    Section 3: Automating With CMake

    Chapter 8: Testing Frameworks

    Technical requirements

    Why are automated tests worth the trouble?

    Using CTest to standardize testing in CMake

    Build-and-test mode

    Test mode

    Creating the most basic unit test for CTest

    Structuring our projects for testing

    Unit-testing frameworks

    Catch2

    GTest

    GMock

    Generating test coverage reports

    Avoiding the SEGFAULT gotcha

    Summary

    Further reading

    Chapter 9: Program Analysis Tools

    Technical requirements

    Enforcing the formatting

    Using static checkers

    Clang-Tidy

    Cpplint

    Cppcheck

    include-what-you-use

    Link what you use

    Dynamic analysis with Valgrind

    Memcheck

    Memcheck-Cover

    Summary

    Further reading

    Chapter 10: Generating Documentation

    Technical requirements

    Adding Doxygen to your project

    Generating documentation with a modern look

    Summary

    Further reading

    Other documentation generation utilities

    Chapter 11: Installing and Packaging

    Technical requirements

    Exporting without installation

    Installing projects on the system

    Installing logical targets

    Low-level installation

    Invoking scripts during installation

    Creating reusable packages

    Understanding the issues with relocatable targets

    Installing target export files

    Writing basic config-files

    Creating advanced config-files

    Generating package version files

    Defining components

    How to use components in find_package()

    How to use components in the install() command

    Packaging with CPack

    Summary

    Further reading

    Chapter 12: Creating Your Professional Project

    Technical requirements

    Planning our work

    Project layout

    Object libraries

    Shared libraries versus static libraries

    Project file structure

    Building and managing dependencies

    Building the Calc library

    Building the Calc Console executable

    Testing and program analysis

    Preparing the coverage module

    Preparing the Memcheck module

    Applying testing scenarios

    Adding static analysis tools

    Installing and packaging

    Installation of the library

    Installation of the executable

    Packaging with CPack

    Providing the documentation

    Automatic documentation generation

    Not-as-technical documents of professional project

    Summary

    Further reading

    Appendix: Miscellaneous Commands

    The string() command

    Search and replace

    Manipulation

    Comparison

    Hashing

    Generation

    JSON

    The list() command

    Reading

    Searching

    Modification

    Ordering

    The file() command

    Reading

    Writing

    Filesystem

    Path conversion

    Transfer

    Locking

    Archiving

    The math() command

    Why subscribe?

    Other Books You May Enjoy

    Preface

    Creating top-notch software isn't an easy task. Developers researching this subject online frequently have problems determining which advice is up to date and which approaches have already been superseded by fresher, better practices. At the same time, most resources explain this process chaotically, without the proper background, context, and structure.

    Modern CMake for C++ is an end-to-end guide offering a simpler experience, as it treats building C++ solutions in a comprehensive manner. It teaches you how to use CMake in your CMake projects, and also shows you what makes them maintainable, elegant, and clean. It guides you through the automation of complex tasks appearing in many projects, including building, testing, and packaging.

    The book instructs you on how to form the source directories, as well as build targets and packages. As you progress, you will learn how to compile and link executables and libraries, how these processes work in detail, and how to optimize all steps to achieve the best results. You'll also understand how to add external dependencies to the project: third-party libraries, testing frameworks, program analysis tools, and documentation generators. Finally, you'll explore how to export, install, and package your solution for internal and external purposes.

    After completing this book, you'll be able to use CMake confidently on a professional level.

    Who this book is for

    Learning the C++ language often isn't enough to prepare you for delivering projects to the highest standards. If you're interested in becoming a professional build engineer, a better software developer, or simply want to become proficient with CMake, if you'd like to understand how projects come together and why, if you're transitioning from a different build environment, or if you're interested in learning modern CMake from the ground up, then this book is for you.

    What this book covers

    Chapter 1, First Steps with CMake, covers how to install and use CMake's command line, along with what files make up the project.

    Chapter 2, The CMake Language, provides key code information: comments, command invocations and arguments, variables, lists, and control structures.

    Chapter 3, Setting Up Your First CMake Project, introduces the basic configuration of a project, the required CMake version, project metadata, and file structure, as well as the toolchain setup.

    Chapter 4, Working with Targets, introduces the logical build targets that produce artifacts for executables and libraries.

    Chapter 5, Compiling C++ Sources with CMake, explains how the details of compilation process works and how it can be controlled in a CMake project.

    Chapter 6, Linking with CMake, provides general information on linking, static, and shared libraries. This chapter also explains how to structure a project so that it can be tested.

    Chapter 7, Managing Dependencies with CMake, explains the dependency management methods available in modern CMake.

    Chapter 8, Testing Frameworks, describes how to add the most popular testing frameworks to your project, as well as how to use the CTest utility available in the CMake toolset.

    Chapter 9, Program Analysis Tools, covers how to perform automatic formatting, as well as static and dynamic analyses, in your project.

    Chapter 10, Generating Documentation, explains how to use Doxygen to generate manuals for users straight from the C++ source code.

    Chapter 11, Installing and Packaging, shows how to prepare your project to be used in other projects or installed on the system. We'll also see an explanation of the CPack utility.

    Chapter 12, Creating Your Professional Project, sets out how to put together all the knowledge you have acquired hitherto in to a fully formed project.

    Appendix: Miscellaneous Commands, provides a quick reference of the most popular commands: string(), list(), file(), and math().

    To get the most out of this book

    Basic familiarity with C++ and Unix-like systems is assumed throughout the book. Although this isn't a strict requirement, it will prove helpful in fully understanding the examples given in this book.

    This book targets CMake 3.20, but most of the techniques described should work from CMake 3.15 (features that were added after are usually highlighted).

    All examples have been tested on Debian with the following packages installed:

    clang-format clang-tidy cppcheck doxygen g++ gawk git graphviz lcov libpqxx-dev libprotobuf-dev make pkg-config protobuf-compiler tree valgrind vim wget

    To experience the same environment, it is recommended to use the Docker images, as explained in Chapter 1.

    If you are using the digital version of this book, we advise you to type the code yourself or access the code from the book's GitHub repository (a link is available in the next section). Doing so will help you avoid any potential errors related to the copying and pasting of code.

    Download the example code files

    You can download the example code files for this book from GitHub at https://github.com/PacktPublishing/Modern-CMake-for-Cpp. If there's an update to the code, it will be updated in the GitHub repository.

    We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!

    Download the color images

    We also provide a PDF file that has color images of the screenshots and diagrams used in this book. You can download it here: https://static.packt-cdn.com/downloads/9781801070058_ColorImages.pdf.

    Conventions used

    There are a number of text conventions used throughout this book.

    Code in text: Indicates code words in the text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles. Here is an example: Select Debug, Release, MinSizeRel, or RelWithDebInfo and specify it as follows.

    A block of code is set as follows:

    cmake_minimum_required(VERSION 3.20)

    project(Hello)

    add_executable(Hello hello.cpp)

    When we wish to draw your attention to a particular part of a code block, the relevant lines or items are set in bold:

    cmake_minimum_required(VERSION 3.20)

    project(app)

    message(Top level CMakeLists.txt)

    add_subdirectory(api)

    Any command-line input or output is written as follows:

    cmake --build

    --parallel []

    cmake --build

    -j []

    Bold: Indicates a new term, an important word, or words that you see on screen. For instance, words in menus or dialog boxes appear in bold. Here is an example: If all else fails and we need to use the big guns there is always trace mode.

    Tips or Important Notes

    Appear like this.

    Get in touch

    Feedback from our readers is always welcome.

    General feedback: If you have questions about any aspect of this book, email us at [email protected] and mention the book title in the subject of your message.

    Errata: Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you have found a mistake in this book, we would be grateful if you would report this to us. Please visit www.packtpub.com/support/errata and fill in the form.

    Piracy: If you come across any illegal copies of our works in any form on the internet, we would be grateful if you would provide us with the location address or website name. Please contact us at [email protected] with a link to the material.

    If you are interested in becoming an author: If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, please visit authors.packtpub.com.

    Share Your Thoughts

    Once you've read Modern CMake for C++, we'd love to hear your thoughts! Please click here to go straight to the Amazon review page for this book and share your feedback.

    Your review is important to us and the tech community and will help us make sure we're delivering excellent quality content.

    Download a free PDF copy of this book

    Thanks for purchasing this book!

    Do you like to read on the go but are unable to carry your print books everywhere?

    Is your eBook purchase not compatible with the device of your choice?

    Don’t worry, now with every Packt book you get a DRM-free PDF version of that book at no cost.

    Read anywhere, any place, on any device. Search, copy, and paste code from your favorite technical books directly into your application.

    The perks don’t stop there, you can get exclusive access to discounts, newsletters, and great free content in your inbox daily

    Follow these simple steps to get the benefits:

    Scan the QR code or visit the link below

    https://packt.link/free-ebook/9781801070058

    Submit your proof of purchase

    That’s it! We’ll send your free PDF and other benefits to your email directly

    Section 1: Introducing CMake

    Getting the basics right is critical to understanding the more advanced subjects and avoiding silly mistakes. This is where the majority of CMake users get in trouble: without a proper foundation, it's difficult to achieve the right outcome. No wonder. It's tempting to skip the introductory material and jump right in where the action is and get things done quickly. We address both points in this section by explaining the core topics of CMake and by hacking together a few lines of code to show what the simplest project looks like.

    To build an appropriate mental context, we'll explain what CMake is exactly and how it does its job, along with what the command line is like. We'll talk about the different build stages and learn the language used to generate build systems. We'll also discuss CMake projects: what files they contain, how to approach their directory structure, and we'll explore their primary configuration.

    This section comprises the following chapters:

    Chapter 1, First Steps with CMake

    Chapter 2, The CMake Language

    Chapter 3, Setting Up Your First CMake Project

    Chapter 1: First Steps with CMake

    There is something magical about turning source code into a working application. It is not only the effect itself, that is, a working mechanism that we devise and bring to life, but the very process or act of exercising the idea into existence.

    As programmers, we work in the following loop: design, code, and test. We invent changes, we phrase them in a language that the compiler understands, and we check whether they work as intended. To create a proper, high-quality application from our source code, we need to meticulously execute repetitive, error-prone tasks: invoking the correct commands, checking the syntax, linking binary files, running tests, reporting issues, and more.

    It takes great effort to remember each step every single time. Instead, we want to stay focused on the actual coding and delegate everything else to automated tooling. Ideally, this process would start with a single button, right after we have changed our code. It would be smart, fast, extensible, and work in the same way across different OSs and environments. It would be supported by multiple Integrated Development Environments (IDEs) but also by Continuous Integration (CI) pipelines that test our software after a change is submitted to a shared repository.

    CMake is the answer to many such needs; however, it requires a bit of work to configure and use correctly. This is not because CMake is unnecessarily complex but because the subject that we're dealing with here is. Don't worry. We'll undergo this whole learning process very methodically; before you know it, you will have become a building guru.

    I know you're eager to rush off to start writing your own CMake projects, and I applaud your attitude. Since your projects will be primarily for users (yourself included), it's important for you to understand that perspective as well.

    So, let's start with just that: becoming a CMake power user. We'll go through a few basics: what this tool is, how it works in principle, and how to install it. Then, we'll do a deep dive on the command line and modes of operation. Finally, we'll wrap up with the purposes of different files in a project, and we'll explain how to use CMake without creating a project at all.

    In this chapter, we're going to cover the following main topics:

    Understanding the basics

    Installing CMake on different platforms

    Mastering the command line

    Navigating the project files

    Discovering scripts and modules

    Technical requirements

    You can find the code files that are present in this chapter on GitHub at https://github.com/PacktPublishing/Modern-CMake-for-Cpp/tree/main/examples/chapter01.

    To build examples provided in this book always use recommended commands:

    cmake -B -S

    cmake --build

    Be sure to replace placeholders and with appropriate paths. As a reminder: build tree is the path to target/output directory, source tree is the path at which your source code is located.

    Understanding the basics

    The compilation of C++ source code appears to be a fairly straightforward process. Let's take a small program, such as a classic hello.cpp application, as follows:

    chapter-01/01-hello/hello.cpp

    #include

    int main() {

      std::cout << Hello World! << std::endl;

      return 0;

    }

    Now, all we need to do to get an executable is to run a single command. We call the compiler with the filename as an argument:

    $ g++ hello.cpp -o a.out

    Our code is correct, so the compiler will silently produce an executable binary file that our machine can understand. We can run it by calling its name:

    $ ./a.out

    Hello World!

    $

    However, as our projects grow, you will quickly understand that keeping everything in a single file is simply not possible. Clean code practices recommend that files should be kept small and in well-organized structures. The manual compilation of every file can be a tiresome and fragile process. There must be a better way.

    What is CMake?

    Let's say we automate building by writing a script that goes through our project tree and compiles everything. To avoid any unnecessary compilations, our script will detect whether the source has been modified since the last time we ran it (the script). Now, we'd like a convenient way to manage arguments that are passed to the compiler for each file – preferably, we'd like to do that based on configurable criteria. Additionally, our script should know how to link all of the compiled files in a binary or, even better, build whole solutions that can be reused and incorporated as modules in bigger projects.

    The more features we will add the higher the chance that we will get to a full-fledged solution. Building software is a very versatile process and can span multiple different aspects:

    Compiling executables and libraries

    Managing dependencies

    Testing

    Installing

    Packaging

    Producing documentation

    Testing some more

    It would take a very long time to come up with a truly modular and powerful C++ building application that is fit for every purpose. And it did. Bill Hoffman at Kitware implemented the first versions of CMake over 20 years ago. As you might have already guessed, it was very successful. It now has a lot of features and support from the community. Today, CMake is being actively developed and has become the industry standard for C and C++ programmers.

    The problem of building code in an automated way is much older than CMake, so naturally, there are plenty of options out there: Make, Autotools, SCons, Ninja, Premake, and more. But why does CMake have the upper hand?

    There are a couple of things about CMake that I find (granted, subjectively) important:

    It stays focused on supporting modern compilers and toolchains.

    CMake is truly cross-platform – it supports building for Windows, Linux, macOS, and Cygwin.

    It generates project files for popular IDEs: Microsoft Visual Studio, Xcode, and Eclipse CDT. Additionally, it is a project model for others such as CLion.

    CMake operates on just the right level of abstraction – it allows you to group files in reusable targets and projects.

    There are tons of projects that are built with CMake and offer an easy way to include them in your project.

    CMake views testing, packaging, and installing as an inherent part of the build process.

    Old, unused features get deprecated to keep CMake lean.

    CMake provides a unified, streamlined experience across the board. It doesn't matter if you're building your software in an IDE or directly from the command line; what's really important is it takes care of post-build stages as well. Your Continous Integration/Continous Deployment (CI/CD) pipeline can easily use the same CMake configuration and build projects using a single standard even if all of the preceding environments differ.

    How does it work?

    You might be under the impression that CMake is a tool that reads source code on one end and produces binaries on the other – while that's true in principle, it's not the full picture.

    CMake can't build anything on its own – it relies on other tools in the system to perform the actual compilation, linking, and other tasks. You can think of it as the orchestrator of your building process: it knows what steps need to be done, what the end goal is, and how to find the right workers and materials for the job.

    This process has three stages:

    Configuration

    Generation

    Building

    The configuration stage

    This stage is about reading project details stored in a directory, called the source tree, and preparing an output directory or build tree for the generation stage.

    CMake starts by creating an empty build tree and collecting all of the details about the environment it is working in, for example, the architecture, the available compilers, the linkers, and the archivers. Additionally, it checks whether a simple test program can be compiled correctly.

    Next, the CMakeLists.txt project configuration file is parsed and executed (yes, CMake projects are configured with CMake's coding language). This file is the bare minimum of a CMake project (source files can be added later). It tells CMake about the project structure, its targets, and its dependencies (libraries and other CMake packages). During this process, CMake stores collected information in the build tree such as system details, project configurations, logs, and temp files, which are used for the next step. Specifically, a CMakeCache.txt file is created to store more stable variables (such as paths to compilers and other tools) and save time during the next configuration.

    The generation stage

    After reading the project configuration, CMake will generate a buildsystem for the exact environment it is working in. Buildsystems are simply cut-to-size configuration files for other build tools (for example, Makefiles for GNU Make or Ninja and IDE project files for Visual Studio). During this stage, CMake can still apply some final touches to the build configuration by evaluating generator expressions.

    Note

    The generation stage is executed automatically after the configuration stage. For this reason, this book and other resources often refer to both of these stages when mentioning configuration or generation of a buildsystem. To explicitly run just the configuration stage, you can use the cmake-gui utility.

    The building stage

    To produce the final artifacts specified in our project, we have to run the appropriate build tool. This can be invoked directly, through an IDE, or using the CMake command. In turn, these build tools will execute steps to produce targets with compilers, linkers, static and dynamic analysis tools, test frameworks, reporting tools, and anything else you can think of.

    The beauty of this solution lies in the ability to produce buildsystems on demand for every platform with a single configuration (that is, the same project files):

    Figure 1.1 – The stages of CMake

    Figure 1.1 – The stages of CMake

    Do you remember our hello.cpp application from the Understanding the basics section? CMake makes it really easy for you to build it. All we need is the following CMakeLists.txt file next to our source and two simple commands, cmake -B buildtree and cmake --build buildtree, as follows:

    chapter01/01-hello/CMakeLists.txt: Hello world in the CMake language

    cmake_minimum_required(VERSION 3.20)

    project(Hello)

    add_executable(Hello hello.cpp)

    Here is the output from the Dockerized Linux system (note that we'll discuss Docker in the Installing CMake on different platforms section):

    root@5f81fe44c9bd:/root/examples/chapter01/01-hello# cmake -B buildtree.

    -- The C compiler identification is GNU 9.3.0

    -- The CXX compiler identification is GNU 9.3.0

    -- Check for working C compiler: /usr/bin/cc

    -- Check for working C compiler: /usr/bin/cc -- works

    -- Detecting C compiler ABI info

    -- Detecting C compiler ABI info - done

    -- Detecting C compile features

    -- Detecting C compile features - done

    -- Check for working CXX compiler: /usr/bin/c++

    -- Check for working CXX compiler: /usr/bin/c++ -- works

    -- Detecting CXX compiler ABI info

    -- Detecting CXX compiler ABI info - done

    -- Detecting CXX compile features

    -- Detecting CXX compile features - done

    -- Configuring done

    -- Generating done

    -- Build files have been written to: /root/examples/chapter01/01-hello/buildtree

    root@5f81fe44c9bd:/root/examples/chapter01/01-hello# cmake --build buildtree/

    Scanning dependencies of target Hello

    [ 50%] Building CXX object CMakeFiles/Hello.dir/hello.cpp.o

    [100%] Linking CXX executable Hello

    [100%] Built target Hello

    All that's left is to run it:

    root@68c249f65ce2:~# ./buildtree/Hello

    Hello World!

    Here, we have generated a buildsystem that is stored in the buildtree directory. Following this, we executed the build stage and produced a final binary that we were able to run.

    Now you know what the end result looks like, I'm sure you will be full of questions: what are the prerequisites to this process? What do these commands mean? Why do we need two of them? How do I write my own project files? Do not worry – these questions will be answered in the following sections.

    Getting Help

    This book will provide you with the most important information that is relevant to the current version of CMake (at the time of writing, this is 3.20). To provide you with

    Enjoying the preview?
    Page 1 of 1