How to build cmake project

How to build cmake project

cmake(1)В¶

SynopsisВ¶

DescriptionВ¶

The cmake executable is the command-line interface of the cross-platform buildsystem generator CMake. The above Synopsis lists various actions the tool can perform as described in sections below.

To build a software project with CMake, Generate a Project Buildsystem. Optionally use cmake to Build a Project, Install a Project or just run the corresponding build tool (e.g. make ) directly. cmake can also be used to View Help.

The other actions are meant for use by software developers writing scripts in the CMake language to support their builds.

For more information on CMake at large, see also the links at the end of this manual.

Introduction to CMake BuildsystemsВ¶

To generate a buildsystem with CMake, the following must be selected:

The top-level directory in which buildsystem files and build output artifacts (e.g. executables and libraries) are to be stored. CMake will write a CMakeCache.txt file to identify the directory as a build tree and store persistent information such as buildsystem configuration options.

To maintain a pristine source tree, perform an out-of-source build by using a separate dedicated build tree. An in-source build in which the build tree is placed in the same directory as the source tree is also supported, but discouraged.

Generate a Project BuildsystemВ¶

Run CMake with one of the following command signatures to specify the source and build trees and generate a buildsystem:

Uses the current working directory as the build tree, and

as the source tree. The specified path may be absolute or relative to the current working directory. The source tree must contain a CMakeLists.txt file and must not contain a CMakeCache.txt file because the latter identifies an existing build tree. For example:

as the build tree, and loads the path to the source tree from its CMakeCache.txt file, which must have already been generated by a previous run of CMake. The specified path may be absolute or relative to the current working directory. For example:

as the build tree and

as the source tree. The specified paths may be absolute or relative to the current working directory. The source tree must contain a CMakeLists.txt file. The build tree will be created automatically if it does not already exist. For example:

In all cases the may be zero or more of the Options below.

How to build cmake project. Смотреть фото How to build cmake project. Смотреть картинку How to build cmake project. Картинка про How to build cmake project. Фото How to build cmake projectPreshing on Programming

CMake is a versatile tool that helps you build C/C++ projects on just about any platform you can think of. It’s used by many popular open source projects including LLVM, Qt, KDE and Blender.

As an example, I’ve prepared a CMake-based project that uses SDL2 and OpenGL to render a spinning 3D logo. You can build it on Windows, MacOS or Linux.

How to build cmake project. Смотреть фото How to build cmake project. Смотреть картинку How to build cmake project. Картинка про How to build cmake project. Фото How to build cmake project How to build cmake project. Смотреть фото How to build cmake project. Смотреть картинку How to build cmake project. Картинка про How to build cmake project. Фото How to build cmake project

The information here applies to any CMake-based project, so feel free to skip ahead to any section. However, I recommend reading the first two sections first.

If you don’t have CMake yet, there are installers and binary distributions on the CMake website. In Unix-like environments, including Linux, it’s usually available through the system package manager. You can also install it through MacPorts, Homebrew, Cygwin or MSYS2.

The Source and Binary Folders

How to build cmake project. Смотреть фото How to build cmake project. Смотреть картинку How to build cmake project. Картинка про How to build cmake project. Фото How to build cmake project

By keeping the binary folder separate from the source, you can delete the binary folder at any time to get back to a clean slate. You can even create several binary folders, side-by-side, that use different build systems or configuration options.

The Configure and Generate Steps

As you’ll see in the following sections, there are several ways to run CMake. No matter how you run it, it performs two steps: the configure step and the generate step.

How to build cmake project. Смотреть фото How to build cmake project. Смотреть картинку How to build cmake project. Картинка про How to build cmake project. Фото How to build cmake project

The CMakeLists.txt script is executed during the configure step. This script is responsible for defining targets. Each target represents an executable, library, or some other output of the build pipeline.

If the configure step succeeds – meaning CMakeLists.txt completed without errors – CMake will generate a build pipeline using the targets defined by the script. The type of build pipeline generated depends on the type of generator used, as explained in the following sections.

How to build cmake project. Смотреть фото How to build cmake project. Смотреть картинку How to build cmake project. Картинка про How to build cmake project. Фото How to build cmake project

In a more sophisticated project, the configure step might also test the availability of system functions (as a traditional Unix configure script would), or define a special “install” target (to help create a distributable package). If you re-run CMake on the same binary folder, many of the slow steps are skipped during subsequent runs, thanks to the cache.

Running CMake from the Command Line

How to build cmake project. Смотреть фото How to build cmake project. Смотреть картинку How to build cmake project. Картинка про How to build cmake project. Фото How to build cmake project

How to build cmake project. Смотреть фото How to build cmake project. Смотреть картинку How to build cmake project. Картинка про How to build cmake project. Фото How to build cmake project

Running cmake-gui

I prefer the command line, but CMake also has a GUI. The GUI offers an interactive way to set cache variables. Again, make sure to install your project’s required dependencies first.

How to build cmake project. Смотреть фото How to build cmake project. Смотреть картинку How to build cmake project. Картинка про How to build cmake project. Фото How to build cmake project

If the binary folder doesn’t exist, CMake will prompt you to create it. It will then ask you to select a generator.

How to build cmake project. Смотреть фото How to build cmake project. Смотреть картинку How to build cmake project. Картинка про How to build cmake project. Фото How to build cmake project

How to build cmake project. Смотреть фото How to build cmake project. Смотреть картинку How to build cmake project. Картинка про How to build cmake project. Фото How to build cmake project

The idea is that if you change a cache variable, then click Configure, new cache variables might appear as a result of your change. The red highlights are meant to help you see any new variables, customize them, then click Configure again. In practice, changing a value doesn’t introduce new cache variables very often. It depends how the project’s CMakeLists.txt script was written.

Once you’ve customized the cache variables to your liking, click Generate. This will generate the build pipeline in the binary folder. You can then use it to build your project.

Running ccmake

How to build cmake project. Смотреть фото How to build cmake project. Смотреть картинку How to build cmake project. Картинка про How to build cmake project. Фото How to build cmake project

Building with Unix Makefiles

Personally, I also find CMake’s default Release configuration useless because it doesn’t generate any debug information. If you’ve ever opened a crash dump or fixed a bug in Release, you’ll appreciate the availability of debug information, even in an optimized build. That’s why, in my other CMake projects, I usually delete the Release configuration from CMakeLists.txt and use RelWithDebInfo instead.

Building with Visual Studio

How to build cmake project. Смотреть фото How to build cmake project. Смотреть картинку How to build cmake project. Картинка про How to build cmake project. Фото How to build cmake project

Like any Visual Studio solution, you can change build type at any time from the Solution Configuration drop-down list. The CMakeDemo sample uses CMake’s default set of build types, shown below. Again, I find the default Release configuration rather useless as it doesn’t produce any debug information. In my other CMake projects, I usually delete the Release configuration from CMakeLists.txt and use RelWithDebInfo instead.

How to build cmake project. Смотреть фото How to build cmake project. Смотреть картинку How to build cmake project. Картинка про How to build cmake project. Фото How to build cmake project

Built-In CMake Support in Visual Studio 2017

Building with Xcode

Specify the Xcode generator from the CMake command line. Again, assuming that the source folder is the parent:

How to build cmake project. Смотреть фото How to build cmake project. Смотреть картинку How to build cmake project. Картинка про How to build cmake project. Фото How to build cmake project

After that, click “Edit Scheme…” from the same drop-down list, then choose a build configuration under Run → Info. Again, I don’t recommend CMake’s default Release configuration, as the lack of debug information limits its usefulness.

How to build cmake project. Смотреть фото How to build cmake project. Смотреть картинку How to build cmake project. Картинка про How to build cmake project. Фото How to build cmake project

Finally, build from the Product → Build menu (or the ⌘B shortcut), run using Product → Run (or ⌘R), or click the big play button in the toolbar.

It’s possible to make CMake generate an Xcode project that builds a MacOS bundle or framework, but I didn’t demonstrate that in the CMakeDemo project.

Building with Qt Creator

Qt Creator provides built-in support for CMake using the Makefile or Ninja generator under the hood. I tested the following steps in Qt Creator 3.5.1.

In Qt Creator, go to File → Open File or Project… and choose CMakeLists.txt from the source folder you want to build.

How to build cmake project. Смотреть фото How to build cmake project. Смотреть картинку How to build cmake project. Картинка про How to build cmake project. Фото How to build cmake project

Qt Creator will prompt you for the location of the binary folder, calling it the “build directory”. By default, it suggests a path adjacent to the source folder. You can change this location if you want.

How to build cmake project. Смотреть фото How to build cmake project. Смотреть картинку How to build cmake project. Картинка про How to build cmake project. Фото How to build cmake project

When prompted to run CMake, make sure to define the CMAKE_BUILD_TYPE variable since the Makefile generator is single-configuration. You can also specify project-specific variables here, such as CMakeDemo’s DEMO_ENABLE_MULTISAMPLE option.

How to build cmake project. Смотреть фото How to build cmake project. Смотреть картинку How to build cmake project. Картинка про How to build cmake project. Фото How to build cmake project

After that, you can build and run the project from Qt Creator’s menus or using the Shift+Ctrl+B or F5 shortcuts.

If you want to re-run CMake, for example to change the build type from Debug to RelWithDebInfo, navigate to Projects → Build & Run → Build, then click “Run CMake”.

How to build cmake project. Смотреть фото How to build cmake project. Смотреть картинку How to build cmake project. Картинка про How to build cmake project. Фото How to build cmake project

The CMakeDemo project contains a single executable target, but if your project contains multiple executable targets, you can tell Qt Creator which one to run by navigating to Projects → Build & Run → Run and changing the “Run configuration” to something else. The drop-down list is automatically populated with a list of executable targets created by the build pipeline.

How to build cmake project. Смотреть фото How to build cmake project. Смотреть картинку How to build cmake project. Картинка про How to build cmake project. Фото How to build cmake project

Other CMake Features

I really appreciate how CMake helps integrate all kinds of C/C++ components and build them in all kinds of environments. It’s not without its flaws, but once you’re proficient with it, the open source world is your oyster, even when integrating non-CMake projects. My next post will be a crash course in CMake’s scripting language.

How to build cmake project. Смотреть фото How to build cmake project. Смотреть картинку How to build cmake project. Картинка про How to build cmake project. Фото How to build cmake projectIf you wish to become a power user, and don’t mind forking over a few bucks, the authors’ book Mastering CMake offers a big leap forward. Their article in The Architecture of Open Source Applications is also an interesting read.

Check out Plywood, a cross-platform, open source C++ framework:

Recent Posts

Getting StartedВ¶

Getting and Installing CMake on Your ComputerВ¶

Before using CMake, you will need to install or build the CMake binaries on your system. On many systems, you may find that CMake is already installed or is available for installation with the standard package manager tool for the system. Cygwin, Debian, FreeBSD, OS X MacPorts, Mac OS X Fink, and many others all have CMake distributions.

If your system does not have a CMake package, you can find CMake precompiled for many common architectures on the CMake Download page. Select the desired release and follow the download instructions. CMake may be installed to any directory, so root privileges are not required for installation.

If you do not find precompiled binaries for your system, then you can build CMake from source. To build CMake, you will need a modern C++ compiler and the source distribution from the CMake Download page or Kitware’s GitLab instance. To build CMake, follow the instructions in Readme.txt at the top of the source tree.

Directory StructureВ¶

There are two main directories CMake uses when building a project: the source directory and the binary directory. The source directory is where the source code for the project is located. This is also where the CMakeLists files will be found. The binary directory is sometimes referred to as the build directory and is where CMake will put the resulting object files, libraries, and executables. CMake will not write any files to the source directory, only to the binary directory.

Out-of-source builds, where the source and binary directories are different, are strongly encouraged. In-source builds where the source and binary directories are the same are supported but should be avoided if possible. Out-of-source builds make it very easy to maintain a clean source tree and allow quick removal of all of the files generated by a build. Having the build tree differ from the source tree also makes it easy to support having multiple builds of a single source tree. This is useful when you want to have multiple builds with different options but just one copy of the source code.

Basic CMake UsageВ¶

CMake takes one or more CMakeLists files as input and produces project files or Makefiles for use with a wide variety of native development tools.

The typical CMake process is as follows:

The project is defined in one or more CMakeLists files

CMake configures and generates the project

Users build project with their favorite native development tool

Each step of the process is described in detail in the following sections.

CMakeLists FilesВ¶

The CMakeLists files (actually CMakeLists.txt but it is common to leave off the extension) are plain text files that contain the project description in CMake’s Language. The cmake-language is expressed as a series of comments, commands and variables. You might wonder why CMake decided to have its own language instead of using an existing one such as Python, Java, or Tcl. The main reason is that CMake developers did not want to make CMake require an additional tool to run. By requiring one of these other languages, all users of CMake would be required to have that language installed, and potentially a specific version of that language. This is on top of the language extensions that would be required to do some of the CMake work, for both performance and capability reasons.

Hello World for CMakeВ¶

To begin, let us consider the simplest possible CMakeLists file. To compile an executable from one source file, the CMakeLists file would contain three lines:

The next line of any top level CMakeLists file should be the project command. This command sets the name of the project and may specify other options such as language or version.

For each directory in a project where the CMakeLists.txt file invokes the project command, CMake generates a top-level Makefile or IDE project file. The project will contain all targets that are in the CMakeLists.txt file and any subdirectories, as specified by the add_subdirectory command. If the EXCLUDE_FROM_ALL option is used in the add_subdirectory command, the generated project will not appear in the top-level Makefile or IDE project file; this is useful for generating sub-projects that do not make sense as part of the main build process. Consider that a project with a number of examples could use this feature to generate the build files for each example with one run of CMake, but not have the examples built as part of the normal build process.

Finally, use the add_executable command to add an executable to the project using the given source file.

The next sections will describe how to configure and build the project using the CMake GUI and command line interfaces.

Configure and GenerateВ¶

After a CMakeLists file has been created, CMake processes the text file and creates entries in a cache file. Users may edit the CMakeLists file or specify cache values with the CMake gui or ccmake and re-configure. Next, CMake uses the cache entries to generate a project in the user’s desired build system (e.g. Makefile or Visual Studio solution).

Running the CMake GUIВ¶

CMake includes a Qt-based user interface that can be used on most platforms, including UNIX, Mac OS X, and Windows. The cmake-gui is included in the CMake source code, but you will need an installation of Qt on your system in order to build it.

How to build cmake project. Смотреть фото How to build cmake project. Смотреть картинку How to build cmake project. Картинка про How to build cmake project. Фото How to build cmake project

Figure 1: Qt based CMake GUI В¶

On Windows, the executable is named cmake-gui.exe and it should be in your Start menu under Program Files. There may also be a shortcut on your desktop, or if you built CMake from the source, it will be in the build directory. For UNIX and Mac users, the executable is named cmake-gui and it can be found where you installed the CMake executables. A GUI will appear similar to what is shown in Figure 1. The top two fields are the source code and binary directories. They allow you to specify where the source code is located for what you want to compile, and where the resulting binaries should be placed. You should set these two values first. If the binary directory you specify does not exist, it will be created for you. If the binary directory has been configured by CMake before, it will then automatically set the source tree.

Running the ccmake Curses InterfaceВ¶

How to build cmake project. Смотреть фото How to build cmake project. Смотреть картинку How to build cmake project. Картинка про How to build cmake project. Фото How to build cmake project

Figure 2: ccmake running on UNIX В¶

Brief instructions are displayed in the bottom of the window. If you hit the “c” key, it will configure the project. You should always configure after changing values in the cache. To change values, use the arrow keys to select cache entries, and hit the enter key to edit them. Boolean values will toggle with the enter key. Once you have set all the values as you like, you can hit the “g” key to generate the Makefiles and exit. You can also hit “h” for help, “q” to quit, and “t” to toggle the viewing of advanced cache entries.

Running CMake from the Command LineВ¶

Specifying the Compiler to CMakeВ¶

On some systems, you may have more than one compiler to choose from or your compiler may be in a non-standard place. In these cases, you will need to specify to CMake where your desired compiler is located. There are three ways to specify this: the generator can specify the compiler; an environment variable can be set; or a cache entry can be set. Some generators are tied to a specific compiler; for example, the Visual Studio 19 generator always uses the Microsoft Visual Studio 19 compiler. For Makefile-based generators, CMake will try a list of usual compilers until it finds a working one.

The flags for the compiler and the linker can also be changed by setting environment variables. Setting LDFLAGS will initialize the cache values for link flags, while CXXFLAGS and CFLAGS will initialize CMAKE_CXX_FLAGS and CMAKE_C_FLAGS respectively.

Build ConfigurationsВ¶

Build configurations allow a project to be built in different ways for debug, optimized, or any other special set of flags. CMake supports, by default, Debug, Release, MinSizeRel, and RelWithDebInfo configurations. Debug has the basic debug flags turned on. Release has the basic optimizations turned on. MinSizeRel has flags that produce the smallest object code, but not necessarily the fastest code. RelWithDebInfo builds an optimized build with debug information as well.

CMake handles the configurations in slightly different ways depending on the generator being used. The conventions of the native build system are followed when possible. This means that configurations impact the build in different ways when using Makefiles versus using Visual Studio project files.

The Visual Studio IDE supports the notion of Build Configurations. A default project in Visual Studio usually has Debug and Release configurations. From the IDE you can select build Debug, and the files will be built with Debug flags. The IDE puts all of the binary files into directories with the name of the active configuration. This brings about an extra complexity for projects that build programs that need to be run as part of the build process from custom commands. See the CMAKE_CFG_INTDIR variable and the custom commands section for more information about how to handle this issue. The variable CMAKE_CONFIGURATION_TYPES is used to tell CMake which configurations to put in the workspace.

With Makefile-based generators, only one configuration can be active at the time CMake is run, and it is specified with the CMAKE_BUILD_TYPE variable. If the variable is empty then no flags are added to the build. If the variable is set to the name of a configuration, then the appropriate variables and rules (such as CMAKE_CXX_FLAGS_ ) are added to the compile lines. Makefiles do not use special configuration subdirectories for object files. To build both debug and release trees, the user is expected to create multiple build directories using the out-of-source build feature of CMake, and set the CMAKE_BUILD_TYPE to the desired selection for each build. For example:

Building Your ProjectВ¶

After you have run CMake, your project will be ready to be built. If your target generator is based on Makefiles then you can build your project by changing the directory to your binary tree and typing make (or gmake or nmake as appropriate). If you generated files for an IDE such as Visual Studio, you can start your IDE, load the project files into it, and build as you normally would.

That is all there is to installing and running CMake for simple projects. In the following chapters, we will consider CMake in more detail and explain how to use it on more complex software projects.

Step 1: A Basic Starting PointВ¶

The most basic project is an executable built from source code files. For simple projects, a three line CMakeLists.txt file is all that is required. This will be the starting point for our tutorial. Create a CMakeLists.txt file in the Step1 directory that looks like:

Note that this example uses lower case commands in the CMakeLists.txt file. Upper, lower, and mixed case commands are supported by CMake. The source code for tutorial.cxx is provided in the Step1 directory and can be used to compute the square root of a number.

Build and RunВ¶

For example, from the command line we could navigate to the Help/guide/tutorial directory of the CMake source code tree and create a build directory:

Next, navigate to the build directory and run CMake to configure the project and generate a native build system:

Then call that build system to actually compile/link the project:

Finally, try to use the newly built Tutorial with these commands:

Adding a Version Number and Configured Header FileВ¶

The first feature we will add is to provide our executable and project with a version number. While we could do this exclusively in the source code, using CMakeLists.txt provides more flexibility.

First, modify the CMakeLists.txt file to use the project() command to set the project name and version number.

Then, configure a header file to pass the version number to the source code:

Since the configured file will be written into the binary tree, we must add that directory to the list of paths to search for include files. Add the following lines to the end of the CMakeLists.txt file:

Using your favorite editor, create TutorialConfig.h.in in the source directory with the following contents:

When CMake configures this header file the values for @Tutorial_VERSION_MAJOR@ and @Tutorial_VERSION_MINOR@ will be replaced.

Finally, let’s print out the executable name and version number by updating tutorial.cxx as follows:

Specify the C++ StandardВ¶

RebuildВ¶

Let’s build our project again. We already created a build directory and ran CMake, so we can skip to the build step:

Now we can try to use the newly built Tutorial with same commands as before:

Check that the version number is now reported when running the executable without any arguments.

CMake TutorialВ¶

IntroductionВ¶

The CMake tutorial provides a step-by-step guide that covers common build system issues that CMake helps address. Seeing how various topics all work together in an example project can be very helpful. The tutorial documentation and source code for examples can be found in the Help/guide/tutorial directory of the CMake source code tree. Each step has its own subdirectory containing code that may be used as a starting point. The tutorial examples are progressive so that each step provides the complete solution for the previous step.

A Basic Starting Point (Step 1)В¶

The most basic project is an executable built from source code files. For simple projects, a three line CMakeLists.txt file is all that is required. This will be the starting point for our tutorial. Create a CMakeLists.txt file in the Step1 directory that looks like:

Note that this example uses lower case commands in the CMakeLists.txt file. Upper, lower, and mixed case commands are supported by CMake. The source code for tutorial.cxx is provided in the Step1 directory and can be used to compute the square root of a number.

Adding a Version Number and Configured Header FileВ¶

The first feature we will add is to provide our executable and project with a version number. While we could do this exclusively in the source code, using CMakeLists.txt provides more flexibility.

First, modify the CMakeLists.txt file to use the project command to set the project name and version number.

Then, configure a header file to pass the version number to the source code:

Since the configured file will be written into the binary tree, we must add that directory to the list of paths to search for include files. Add the following lines to the end of the CMakeLists.txt file:

Using your favorite editor, create TutorialConfig.h.in in the source directory with the following contents:

When CMake configures this header file the values for @Tutorial_VERSION_MAJOR@ and @Tutorial_VERSION_MINOR@ will be replaced.

Finally, let’s print out the executable name and version number by updating tutorial.cxx as follows:

Specify the C++ StandardВ¶

Build and TestВ¶

Run the cmake executable or the cmake-gui to configure the project and then build it with your chosen build tool.

For example, from the command line we could navigate to the Help/guide/tutorial directory of the CMake source code tree and create a build directory:

Next, navigate to the build directory and run CMake to configure the project and generate a native build system:

Then call that build system to actually compile/link the project:

Finally, try to use the newly built Tutorial with these commands:

Adding a Library (Step 2)В¶

Now we will add a library to our project. This library will contain our own implementation for computing the square root of a number. The executable can then use this library instead of the standard square root function provided by the compiler.

Add the following one line CMakeLists.txt file to the MathFunctions directory:

To make use of the new library we will add an add_subdirectory call in the top-level CMakeLists.txt file so that the library will get built. We add the new library to the executable, and add MathFunctions as an include directory so that the mysqrt.h header file can be found. The last few lines of the top-level CMakeLists.txt file should now look like:

Now let us make the MathFunctions library optional. While for the tutorial there really isn’t any need to do so, for larger projects this is a common occurrence. The first step is to add an option to the top-level CMakeLists.txt file.

This option will be displayed in the cmake-gui and ccmake with a default value of ON that can be changed by the user. This setting will be stored in the cache so that the user does not need to set the value each time they run CMake on a build directory.

The next change is to make building and linking the MathFunctions library conditional. To do this we change the end of the top-level CMakeLists.txt file to look like the following:

Note the use of the variable EXTRA_LIBS to collect up any optional libraries to later be linked into the executable. The variable EXTRA_INCLUDES is used similarly for optional header files. This is a classic approach when dealing with many optional components, we will cover the modern approach in the next step.

Then, in the same file, make USE_MYMATH control which square root function is used:

Since the source code now requires USE_MYMATH we can add it to TutorialConfig.h.in with the following line:

Run the cmake executable or the cmake-gui to configure the project and then build it with your chosen build tool. Then run the built Tutorial executable.

Rebuild and run the tutorial again.

Which function gives better results, sqrt or mysqrt?

Adding Usage Requirements for Library (Step 3)В¶

Usage requirements allow for far better control over a library or executable’s link and include line while also giving more control over the transitive property of targets inside CMake. The primary commands that leverage usage requirements are:

Let’s refactor our code from Adding a Library (Step 2) to use the modern CMake approach of usage requirements. We first state that anybody linking to MathFunctions needs to include the current source directory, while MathFunctions itself doesn’t. So this can become an INTERFACE usage requirement.

Remember INTERFACE means things that consumers require but the producer doesn’t. Add the following lines to the end of MathFunctions/CMakeLists.txt :

Installing and Testing (Step 4)В¶

Now we can start adding install rules and testing support to our project.

Install RulesВ¶

The install rules are fairly simple: for MathFunctions we want to install the library and header file and for the application we want to install the executable and configured header.

So to the end of MathFunctions/CMakeLists.txt we add:

And to the end of the top-level CMakeLists.txt we add:

That is all that is needed to create a basic local install of the tutorial.

Now run the cmake executable or the cmake-gui to configure the project and then build it with your chosen build tool.

Navigate to the install directory and verify that the installed Tutorial runs.

Testing SupportВ¶

Next let’s test our application. At the end of the top-level CMakeLists.txt file we can enable testing and then add a number of basic tests to verify that the application is working correctly.

The first test simply verifies that the application runs, does not segfault or otherwise crash, and has a zero return value. This is the basic form of a CTest test.

The next test makes use of the PASS_REGULAR_EXPRESSION test property to verify that the output of the test contains certain strings. In this case, verifying that the usage message is printed when an incorrect number of arguments are provided.

Adding System Introspection (Step 5)В¶

Let us consider adding some code to our project that depends on features the target platform may not have. For this example, we will add some code that depends on whether or not the target platform has the log and exp functions. Of course almost every platform has these functions but for this tutorial assume that they are not common.

If available, use target_compile_definitions to specify HAVE_LOG and HAVE_EXP as PRIVATE compile definitions.

If log and exp are available on the system, then we will use them to compute the square root in the mysqrt function. Add the following code to the mysqrt function in MathFunctions/mysqrt.cxx (don’t forget the #endif before returning the result!):

Run the cmake executable or the cmake-gui to configure the project and then build it with your chosen build tool and run the Tutorial executable.

Which function gives better results now, sqrt or mysqrt?

Adding a Custom Command and Generated File (Step 6)В¶

Suppose, for the purpose of this tutorial, we decide that we never want to use the platform log and exp functions and instead would like to generate a table of precomputed values to use in the mysqrt function. In this section, we will create the table as part of the build process, and then compile that table into our application.

In the MathFunctions subdirectory, a new source file named MakeTable.cxx has been provided to generate the table.

After reviewing the file, we can see that the table is produced as valid C++ code and that the output filename is passed in as an argument.

The next step is to add the appropriate commands to the MathFunctions/CMakeLists.txt file to build the MakeTable executable and then run it as part of the build process. A few commands are needed to accomplish this.

Then we add a custom command that specifies how to produce Table.h by running MakeTable.

Run the cmake executable or the cmake-gui to configure the project and then build it with your chosen build tool.

Run the Tutorial executable and verify that it is using the table.

Building an Installer (Step 7)В¶

Finally we include the CPack module which will use these variables and some other properties of the current system to setup an installer.

The next step is to build the project in the usual manner and then run the cpack executable. To build a binary distribution, from the binary directory run:

To create a source distribution you would type:

Alternatively, run make package or right click the Package target and Build Project from an IDE.

Run the installer found in the binary directory. Then run the installed executable and verify that it works.

Adding Support for a Dashboard (Step 8)В¶

We will also need to create a CTestConfig.cmake file in the top-level directory where we can specify the name of the project and where to submit the dashboard.

The ctest executable will read in this file when it runs. To create a simple dashboard you can run the cmake executable or the cmake-gui to configure the project, but do not build it yet. Instead, change directory to the binary tree, and then run:

Remember, for multi-config generators (e.g. Visual Studio), the configuration type must be specified:

Or, from an IDE, build the Experimental target.

The ctest executable will build and test the project and submit the results to Kitware’s public dashboard: https://my.cdash.org/index.php?project=CMakeTutorial.

Mixing Static and Shared (Step 9)В¶

The first step is to update the starting section of the top-level CMakeLists.txt to look like:

Now that we have made MathFunctions always be used, we will need to update the logic of that library. So, in MathFunctions/CMakeLists.txt we need to create a SqrtLibrary that will conditionally be built and installed when USE_MYMATH is enabled. Now, since this is a tutorial, we are going to explicitly require that SqrtLibrary is built statically.

The end result is that MathFunctions/CMakeLists.txt should look like:

Next, update MathFunctions/mysqrt.cxx to use the mathfunctions and detail namespaces:

Always include MathFunctions.h

Always use mathfunctions::sqrt

Don’t include cmath

Finally, update MathFunctions/MathFunctions.h to use dll export defines:

At this point, if you build everything, you may notice that linking fails as we are combining a static library without position independent code with a library that has position independent code. The solution to this is to explicitly set the POSITION_INDEPENDENT_CODE target property of SqrtLibrary to be True no matter the build type.

Exercise: We modified MathFunctions.h to use dll export defines. Using CMake documentation can you find a helper module to simplify this?

Adding Generator Expressions (Step 10)В¶

Generator expressions are evaluated during build system generation to produce information specific to each build configuration.

Generator expressions may be used to enable conditional linking, conditional definitions used when compiling, conditional include directories and more. The conditions may be based on the build configuration, target properties, platform information or any other queryable information.

There are different types of generator expressions including Logical, Informational, and Output expressions.

So the following code:

Would be replaced with:

Next we add the desired compiler warning flags that we want for our project. As warning flags vary based on the compiler we use the COMPILE_LANG_AND_ID generator expression to control which flags to apply given a language and a set of compiler ids as seen below:

Looking at this we see that the warning flags are encapsulated inside a BUILD_INTERFACE condition. This is done so that consumers of our installed project will not inherit our warning flags.

Adding Export Configuration (Step 11)В¶

During Installing and Testing (Step 4) of the tutorial we added the ability for CMake to install the library and headers of the project. During Building an Installer (Step 7) we added the ability to package up this information so it could be distributed to other people.

The next step is to add the necessary information so that other CMake projects can use our project, be it from a build directory, a local install or when packaged.

Now that we have MathFunctions being exported, we also need to explicitly install the generated MathFunctionsTargets.cmake file. This is done by adding the following to the bottom of the top-level CMakeLists.txt :

At this point you should try and run CMake. If everything is setup properly you will see that CMake will generate an error that looks like:

What CMake is trying to say is that during generating the export information it will export a path that is intrinsically tied to the current machine and will not be valid on other machines. The solution to this is to update the MathFunctions target_include_directories to understand that it needs different INTERFACE locations when being used from within the build directory and from an install / package. This means converting the target_include_directories call for MathFunctions to look like:

Once this has been updated, we can re-run CMake and verify that it doesn’t warn anymore.

At this point, we have CMake properly packaging the target information that is required but we will still need to generate a MathFunctionsConfig.cmake so that the CMake find_package command can find our project. So let’s go ahead and add a new file to the top-level of the project called Config.cmake.in with the following contents:

Then, to properly configure and install that file, add the following to the bottom of the top-level CMakeLists.txt :

At this point, we have generated a relocatable CMake Configuration for our project that can be used after the project has been installed or packaged. If we want our project to also be used from a build directory we only have to add the following to the bottom of the top level CMakeLists.txt :

Packaging Debug and Release (Step 12)В¶

Note: This example is valid for single-configuration generators and will not work for multi-configuration generators (e.g. Visual Studio).

By default, CMake’s model is that a build directory only contains a single configuration, be it Debug, Release, MinSizeRel, or RelWithDebInfo. It is possible, however, to setup CPack to bundle multiple build directories and construct a package that contains multiple configurations of the same project.

First, we want to ensure that the debug and release builds use different names for the executables and libraries that will be installed. Let’s use d as the postfix for the debug executable and libraries.

Set CMAKE_DEBUG_POSTFIX near the beginning of the top-level CMakeLists.txt file:

And the DEBUG_POSTFIX property on the tutorial executable:

From the Step12 directory, create debug and release subbdirectories. The layout will look like:

Now we need to setup debug and release builds. We can use CMAKE_BUILD_TYPE to set the configuration type:

Next, use the CPACK_INSTALL_CMAKE_PROJECTS variable to specify which projects to install. In this case, we want to install both debug and release.

From the Step12 directory, run cpack specifying our custom configuration file with the config option:

Источники информации:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *