C++Now 2017: Daniel Pfeifer “Effective CMake"

CppNow · 193K views · 2017 · 1:27:02

Open on YouTube

C, C++, Rust, Go & systems languagesTesting, debugging & developer toolsSoftware architecture & designtalk

Why Stack Overflow recommends it

Stack Overflow users link it whenever someone is writing or fixing CMake files, as the go-to explanation of modern target-based CMake and why to avoid directory-level commands like include_directories.

Recommended by 16 people across 15 different months, 2017 to 2024.

What it is

A C++Now 2017 conference talk by Daniel Pfeifer on best practices for CMake, CTest and CPack. It covers target-based builds, managing dependencies, exporting libraries for clients, cross-compiling, testing in an emulator, and code coverage and analysis.

What people said

Strong rec Florian Wolters · 2017-10 · Stack Overflow · on “How to get CMake to pass either std=c++14/c++1y or c++17/c++1z based on GCC version?”

@einpoklum I should have used the terms *Build Specification* and *Usage Requirements* as used in the official documentation [LINK] . Craig Scott already explained it correctly. Another great explaination can be found in the talk Effective CMake [this video] by Daniel Pfeifer. I highly recommend watching the linked video.

Strong rec paler123 · 2018-08 · Stack Overflow · on “Adding a link library only for objects compiled from a certain language?”

Well, this solves the original problem, e.g. you can link only C++ targets as you asked for. The idea to not operate on directory level (`link_libraries`, `include_directories`, etc.) is not mine, but is e.g. proposed by Daniel Pfeifer in this awesome talk [this video] . I don't have enough CMake expertise / experience to defend this on my own, but from what I've done with CMake so far, this guidelines certainly help to keep things simple.

Strong rec Arda Aytekin · 2019-06 · Stack Overflow · on “CMakeLists.txt setup for Google Test”

I am not sure if you have one and a half hours in your life to watch the great talk [this video] by Daniel Pfeifer, but if you do, I think that talk already covers what you need. Moreover, because you are new at SO, you might also consider reading on [ask] a question with a [mcve].

Strong rec icebp · 2021-04 · Stack Overflow · on “Hierarchical CMake project that also works when building an "inner" (non-root) project”

You may need to rework some of your CMakeLists.txt files. I would recommend watching Daniel Pfeifer's Effective CMake talk at CPPcon [this video] (slides available here [LINK] ). The gist of it is that all of your projects should provide everything they need in order to be build or compiled, in essence build requirements and usage requirements. To achieve this in a maintainable and scalable way you have to move away from variables and setting global options ( add_compile_options , include_directories , etc) and instead focus on targets ( target_compile_options , target_include_directories , etc). So, in your case proj-1/CMakeLists.txt will provide one target (let's call it proj::proj1 ) that sets

Strong rec adam.hendry · 2021-11 · Stack Overflow · on “Why do we need cmake?”

The short answer is that you don't, but it would probably be difficult to build the project without it. CMake does not build code, but is instead a build file generator . It was developed by KitWare (during the ITK project around 2000) to make building code across multiple platforms "simpler". It's not an easy language to use (which Kitware openly admits), but it unifies several things that Windows, Mac, and Linux do differently when building code. On Linux, autoconf is typically used to make build files, which are then compiled by gcc/g++ (and/or clang) On Windows, you would typically use the Visual Studio IDE and create what they call a "Solution" that is then compiled by msvc (the Microso

Strong rec adentinger · 2024-01 · Stack Overflow · on “Making linker errors more helpful through specificity (C/C++)”

If both yourself and the users of your library use CMake (which is a common case nowadays), then a less hacky and more modern technique is to ship CMake target properties alongside installations of your library. These properties include which libraries your library depends on (transitively). For your specific case of -lm , you can manually specify this linker flag as a PUBLIC property (meaning you need -lm to build your library, and whoever uses your library will also need -lm ). In general tough, in modern CMake you can easily have libraries depend on other libraries, because libraries can ship dependency/property information alongside them, or if they don't you can create a Find<Library>.c

Recommends Florian · 2018-01 · Stack Overflow · on “cmake: add_subdirectory() vs include()”

The most commonly used rule is "One CMakeLists.txt per target". So your option No. 1. To achieve this your project structure may have to adapt, if "each source file from the subfolders creates a separate executable". And the root CMakeLists.txt is your starting point and contains the project() command. It's important to note that CMake will mirror your add_subdirectory() and CMakeLists.txt directory structure in its generated build environment CMake will create a new variable scope with each add_subdirectory() call ( the big difference to using include() command [LINK] ) What you should avoid is having to reference source files out of other subdirectories with something like ../some_other_di

Recommends kenba · 2018-03 · Stack Overflow · on “how to include boost headers in own header-only library”

I think that you can, but you need to be more specific in defining your boost dependencies. For example, the CMakeLists.txt file here [LINK] depends upon boost::system for boost::asio . The dependency is defined as follows: find_package(Boost REQUIRED COMPONENTS system) if(Boost_FOUND) target_include_directories(${PROJECT_NAME} PRIVATE ${Boost_INCLUDE_DIRS}) # Boost::asio is header only but it requires Boost::system target_link_libraries(${PROJECT_NAME} INTERFACE Boost::system) . . . endif(Boost_FOUND) In your case, the target is Boost::boost for header-only dependencies, see FindBoost [LINK] . So the relevant part becomes: find_package(Boost 1.66 REQUIRED COMPONENTS boost) IF (Boost_FOUND)

Recommends Rodolfo Picoreti · 2018-04 · Stack Overflow · on “cmake the following imported targets are referenced, but are missing”

After watching C++Now 2017: Daniel Pfeifer “Effective CMake" [this video] I now realized what was missing in my configuration. As mentioned by @Tsyvarev the problem was about libaConfig.cmake. When exporting a library with dependencies you should export mylibrary Targets.cmake , like so: install( EXPORT libaTargets FILE libaTargets.cmake NAMESPACE is:: DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/liba ) And then manually (a bit disappointed here I have to say) write a mylibrary Config.cmake with all the dependencies like so: include(CMakeFindDependencyMacro) find_dependency(libb) find_dependency(OpenCV) find_dependency(Threads) include("${CMAKE_CURRENT_LIST_DIR}/libaTargets.cmake")

Recommends johnb003 · 2018-06 · Stack Overflow · on “CMake and finding other projects and their dependencies”

Alexander Shukaev's got a great start, but there are a number of things that could be done better: Don't use include_directories. At the very least, use target_include_directories . However, you probably don't even need to do that if you use the imported targets. Use the imported targets. Example for Boost: find_package(Boost 1.56 REQUIRED COMPONENTS date_time filesystem iostreams) add_executable(foo foo.cc) target_link_libraries(foo PRIVATE Boost::date_time Boost::filesystem Boost::iostreams ) This takes care of the include directories, libraries, etc. If you used Boost in your headers in B, then instead of PRIVATE, use PUBLIC, and these dependencies would be transitively added to whatever