Using a set of source files to build libraries and executables is about the most basic thing a build system needs to do. This is relatively easy with CMake, but things get more interesting when some of the source files need to be generated as part of the build. CMake provides a range of functionality which can be used to create files, but getting build dependencies correct is an area where many developers struggle or even simply give up. It doesn’t have to be that way!
Author: Craig Scott (Page 1 of 3)
New test properties were added in CMake 3.7.0 to support test fixtures. Put simply, a fixture allows setup and cleanup tasks to be associated with a group of tests. On their own, fixtures are quite useful, but they also integrate well with the existing RESOURCE_LOCK and DEPENDS test properties to support some interesting use cases. This article explains the new fixture features and provides examples showing how they complement the existing resource and dependency functionality.
When C++11 introduced
auto, it opened up a whole range of useful techniques and improved the life of C++ developers in a variety of ways. There’s no shortage of simple examples and tutorials teaching how to start using
auto, but as is often the case, many of these well intentioned examples have left readers with an incomplete picture of how to use
auto effectively and in some cases have resulted in poor habits becoming common practice. Since
auto essentially hides away some of the details of how objects are created, there is a risk that developers don’t think as carefully about what is actually taking place. This article aims to arm the reader with information often omitted so that common pitfalls can be avoided.
Updated 1st February 2017
Working with very large C/C++ code bases will sometimes test your patience. Build times in particular can be a sore point, especially if the development team do not have a great understanding of how to minimise dependencies between source files, headers, etc. The problem gets worse if the developer frequently switches between branches of their source control system, resulting in source files often changing their contents and/or timestamps. The ccache tool aims to minimise that pain by caching compilation outputs (i.e. object files) and reusing them instead of compiling the source again if it gets a compilation request it has seen before and cached. It supports GCC or any compiler that looks like GCC (eg clang). When rebuilding a large project that ccache has mostly compiled before already, the time saving can be significant, even sometimes reducing many minutes down to seconds.
Getting ccache to work with CMake is not overly complicated, but the way to do it is not always obvious. This is especially true with Xcode builds. This article demonstrates how to set up a CMake project to use
ccache with Unix Makefiles, Ninja or Xcode generators, with Xcode receiving special attention. The techniques presented do not require any changes to the host system. Specifically, no symlinks need to be set up for ccache, making it suitable for use in CI systems, etc. where the developer may not be in control of how/where ccache is installed.
Sometimes you just want a single way to build a software project, regardless of what platform or build tool you are using. The promise of CMake is that this should be possible, but in practice, it sometimes doesn’t always seem that way. One particular area where this becomes apparent is scripted builds, especially for things like continuous integration systems, automated testing processes, etc. Since each platform typically has its own commonly used build tool and developers tend to be more familiar with that tool than with CMake, the tendency is to invoke that tool directly in scripts. Unfortunately, this means such scripts end up handling each platform’s build tool separately. But it doesn’t have to be that way. This article will address this and a few other smaller details associated with setting up a platform independent scripted CMake build.
In all but trivial CMake projects, it is common to find targets built from a large number of source files. These files may be distributed across various subdirectories, which may themselves be nested multiple levels deep. In such projects, traditional approaches usually either list all source files at the top-most level or build up the list of source files in a variable and pass that to
add_executable(), etc. With CMake 3.1, a new command
target_sources() was introduced which provides the missing piece among the various
target_... commands. While the CMake documentation succintly describes what
target_sources() does, it fails to highlight just how useful the new command is and why it promotes better CMake projects:
- It can lead to cleaner and more concise CMakeLists.txt project files.
- Dependency information can be specified closer to where the actual dependencies exist in the directory heirarchy.
- Source files gain the ability to become part of a target’s interface.
- Source files can be added to third party project targets without having to modify the third party project files.
Let’s explore your understanding of member function overloading. For a given class, how many different non-template overloads can you define for a given function where the function takes no arguments? Putting aside exception specifications (since allowing them would make the answer to this essentially infinite), let’s make this a multiple choice, pick your answer from: 1, 2, 4 or 8. I’ll even provide a clue that the return types of the functions don’t matter. For extra points, how many of the function overloads are likely to be useful?
I recently came across an interesting use of
std::move which looked something like the following:
for (auto item : items)
// Do things which may add new items to m_items
The intent of the code was that every time the member function
processItems() was called, it would perform some operation on each item held in the member variable
m_items. Each processed item should be removed from
m_items. The operation to be performed might generate new items which would be added to
m_items, so care had to be taken about how to iterate over the set of items.
To ensure robust iteration over the items to be processed, the code transfers the contents of
m_items to a local object and then iterates over that local object. Thus, if new items are created during processing, they would be added to
m_items and the container being iterated over (
items) would not be affected. All good, right? Well, probably yes, but by no means is it guaranteed.
CMake/CPack does a pretty good job of making it relatively easy to create a basic Windows installer. Sometimes, however, it trips you up when you want to do something seemingly common. One such example is creating Start Menu shortcuts for an executable where you also want to pass it some command line arguments. Surprisingly, CMake/CPack doesn’t give you a simple or generic way to do this. It provides very basic functionality via the CPACK_PACKAGE_EXECUTABLES variable in the CPack module, but that’s just a simple mapping of executable to menu shortcut name with no opportunity to provide command line arguments.
UPDATED December 2015:
Since the original article was written, gtest and gmock have been merged and moved into a single repository on Github under the name GoogleTest. I’ve updated the content here to reflect the changes and the article now also covers both gtest and gmock. I’ve also revised the general purpose implementation to make it more flexible, expanded its documentation and made it available on Github under a MIT license. I hope you find it useful.
Using gtest/gmock with CMake is awesome. Not so awesome is when you don’t have a pre-built gtest/gmock available to use. This article demonstrates a convenient way to add them with automated source download and have them build directly as part of your project using
add_subdirectory(). Unlike other common approaches, no manual information has to be provided other than the package to download. The approach is general enough to be applied to any CMake-based external project, not just gtest/gmock.