Template for reliable, cross-platform C++ project setup using cmake.

Overview


The C++ CMake Project Template

Travis Appveyor Tokei Setup Guide

cmake-init is a sophisticated copy & paste template for modern C and C++ projects. The main goals include support of all use cases around software development (programming, testing, Q&A, deployment, documentation) while being modular, flexible, and idiomatic. cmake-init is therefore a collection of cmake best-practices.

The main target platforms are typical desktop, laptop, and server platforms. Currently supported are:

  • Windows
  • macOS
  • GNU/Linux

However, other UNIX versions may work as well if they are supported by CMake.

The cmake-init template assumes you want to setup a project using

  • CMake (3.0 or above)
  • C/C++ compiler

Contents

Usage

The intended use of the template is a copy of the current version with a subsequent replacement of project names and customization of modules to your needs. This is documented within the adaption guide. Another approach is the initialization of a new CMake project where the required features are adopted from cmake-init. We propose the former workflow.

Concluding, a new project should contain the core modules and, as needed, add the maintainer and development modules as required. All modules are designed in a way that they can be excluded. The process of integration or removal of a module/feature is documented with each module.

Adaption Guide

The file ADAPT.md contains a task checklist for new projects. Your start with a copy of cmake-init and process each item from the checklist, adjusting the template to your needs.

Update

After some time working on a project, cmake-init may be updated and you want to integrate the changes. For an overview of changes we suggest to use the cmake-init Template Check module. Alternatively, you can update the required modules selectively.

Non-Goals

In order to be usable in a deterministic, idiomatic fashion, cmake-init avoids the following approaches and features:

Super-Build

Due to the current semantics of targets and CMake internals, combining multiple cmake-init projects into one super-build project is not officially supported. There are limited and restricting workarounds. Actual solution: treat each project separately and use explicit dependency management.

High Abstraction

We use low abstractions to not build a language upon CMake a user has to learn.

File Glob

Explicit source specification prevents erroneous cases when adding and removing sources from the project tree.

Module Documentation

Core Modules

CMake Initialization

As with most CMake projects, cmake-init initializes the CMake environment. This includes the minimum required CMake version,

# CMake version
cmake_minimum_required(VERSION 3.0 FATAL_ERROR)

required policies,

# Set policies
set_policy(CMP0054 NEW) # ENABLE CMP0054: Only interpret if() arguments as variables or keywords when unquoted.
set_policy(CMP0042 NEW) # ENABLE CMP0042: MACOSX_RPATH is enabled by default.
set_policy(CMP0063 NEW) # ENABLE CMP0063: Honor visibility properties for all target types.

adaption of the cmake module path,

# Include cmake modules
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

and an include of default modules that are typically required for each project.

include(GenerateExportHeader)
include(WriteCompilerDetectionHeader)

CMake Backward Compatibility

As some modules as WriteCompilerDetectionHeader may not be available, cmake-init suggests to use fallbacks and availability detection.

Using this example, the module include

include(WriteCompilerDetectionHeader)

is replaced by

set(WriterCompilerDetectionHeaderFound NOTFOUND)
# This module is only available with CMake >=3.1, so check whether it could be found
# BUT in CMake 3.1 this module doesn't recognize AppleClang as compiler, so just use it as of CMake 3.2
if (${CMAKE_VERSION} VERSION_GREATER "3.2")
    include(WriteCompilerDetectionHeader OPTIONAL RESULT_VARIABLE WriterCompilerDetectionHeaderFound)
endif()

and the result can be later used with

if (WriterCompilerDetectionHeaderFound)
  # ...
endif ()

Another issue with older CMake versions is the unavailability of then-unpublished language standards (e.g., C++11 and CMake 3.0). For those versions, the compile options has to be extended manually.

For new projects, we suggest to require at least CMake 3.2 and to therefore adjust the minimum required version:

cmake_minimum_required(VERSION 3.0 FATAL_ERROR)

Project Meta Information

The declaration of project-wide information--that are used, e.g., within documentation, testing, and deployment--, is combined within the project meta information section in the main CMakeLists.txt.

") set(META_VERSION "${META_VERSION_MAJOR}.${META_VERSION_MINOR}.${META_VERSION_PATCH}") set(META_NAME_VERSION "${META_PROJECT_NAME} v${META_VERSION} (${META_VERSION_REVISION})") set(META_CMAKE_INIT_SHA " ") string(MAKE_C_IDENTIFIER ${META_PROJECT_NAME} META_PROJECT_ID) string(TOUPPER ${META_PROJECT_ID} META_PROJECT_ID)">
#
# Project description and (meta) information
#

# Meta information about the project
set(META_PROJECT_NAME        "template")
set(META_PROJECT_DESCRIPTION "CMake Project Template")
set(META_AUTHOR_ORGANIZATION "CG Internals GmbH")
set(META_AUTHOR_DOMAIN       "https://github.com/cginternals/cmake-init/")
set(META_AUTHOR_MAINTAINER   "[email protected]")
set(META_VERSION_MAJOR       "2")
set(META_VERSION_MINOR       "0")
set(META_VERSION_PATCH       "0")
set(META_VERSION_REVISION    "
    
     "
    )
set(META_VERSION             "${META_VERSION_MAJOR}.${META_VERSION_MINOR}.${META_VERSION_PATCH}")
set(META_NAME_VERSION        "${META_PROJECT_NAME} v${META_VERSION} (${META_VERSION_REVISION})")
set(META_CMAKE_INIT_SHA      "
    
     "
    )

string(MAKE_C_IDENTIFIER ${META_PROJECT_NAME} META_PROJECT_ID)
string(TOUPPER ${META_PROJECT_ID} META_PROJECT_ID)

cmake-init supports the projects name, description, organization, domain, and maintainer email as well as detailed version information. For the version, we suggest to use semantic versioning. Depending on your version control system, you may want to integrate the current revision of the software as well: see Version Control System Integration. If you use the cmake-init Template Check module, the cmake-init SHA is declared within this section, too.

Last, cmake-init derives a project ID that complies with the naming schemes of C to be used within auto-generated and derived source code content (e.g., macro identifiers).

Project Meta Information Code Generation

The result of this module is the generation of a C header file that propagates the project meta information to your C and C++ projects. For this, the CMake file configuration feature is used on the version.h.in header template.

#define @META_PROJECT_ID@_PROJECT_NAME        "@META_PROJECT_NAME@"
#define @META_PROJECT_ID@_PROJECT_DESCRIPTION "@META_PROJECT_DESCRIPTION@"

#define @META_PROJECT_ID@_AUTHOR_ORGANIZATION "@META_AUTHOR_ORGANIZATION@"
#define @META_PROJECT_ID@_AUTHOR_DOMAIN       "@META_AUTHOR_DOMAIN@"
#define @META_PROJECT_ID@_AUTHOR_MAINTAINER   "@META_AUTHOR_MAINTAINER@"

#define @META_PROJECT_ID@_VERSION_MAJOR       "@META_VERSION_MAJOR@"
#define @META_PROJECT_ID@_VERSION_MINOR       "@META_VERSION_MINOR@"
#define @META_PROJECT_ID@_VERSION_PATCH       "@META_VERSION_PATCH@"
#define @META_PROJECT_ID@_VERSION_REVISION    "@META_VERSION_REVISION@"

#define @META_PROJECT_ID@_VERSION             "@META_VERSION@"
#define @META_PROJECT_ID@_NAME_VERSION        "@META_NAME_VERSION@"

The template file is configured with the project meta information and the result is stored within the build directory. Beware that this header is stored in a path derived from your project name. You should adopt this as required.

# Generate version-header
configure_file(version.h.in ${CMAKE_CURRENT_BINARY_DIR}/include/${META_PROJECT_NAME}/${META_PROJECT_NAME}-version.h)

We suggest to deploy this header disregarding its internal or even public use.

#
# Deployment
#

# Deploy generated headers
install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include/${META_PROJECT_NAME} DESTINATION include COMPONENT dev)

Project Build Options

Maintainer Modules

cmake-init Template Check

This module allows to check the actuality of the used cmake-init template for own projects. This module is usable when the following is integrated into the CMakeLists.txt.

# Add cmake-init template check cmake targets
add_check_template_target(
   )
  

Here, the contains the git hash of the used cmake-init template. Further, the files cmake/HealthCheck.cmake and cmake/CheckTemplate.cmake are required.

The hash is usually configured using

") # Add cmake-init template check cmake targets add_check_template_target( )">
# Meta information about the project
set(META_CMAKE_INIT_SHA      "
     
      "
     )

# Add cmake-init template check cmake targets
add_check_template_target(
     )
    

Correctly configures, this module adds a cmake build target named check-template that compares the passed with the current master commit hash of this repository and provides a link for a diff view.

Development Modules

Version Control System Integration

# Get git revision
get_git_head_revision(GIT_REFSPEC GIT_SHA1)
string(SUBSTRING "${GIT_SHA1}" 0 12 GIT_REV)
if(NOT GIT_SHA1)
    set(GIT_REV "0")
endif()

Build Targets

Documentation

Tests

Linter

Continuous Integration

Deployment

Packaging

Run-time Assets

Comments
  • Replace in-source googletest with external googletest setup

    Replace in-source googletest with external googletest setup

    This PR removes the in-source googletest release and relies on an external source tree of googletest. The project would then be integrated into the own cmake build tree for testing.

    On Ubuntu systems, the sources can be installed using

    apt install googletest
    

    which is available since Ubuntu 18.04. As general solution, the environment variable googletest_DIR is used to search for the sources.

    Open issues / questions:

    • Provide an easy way to download the latest googletest sources (a git submodule?).
    opened by scheibel 6
  • CMake Warning: Policy CMP0054 is not set

    CMake Warning: Policy CMP0054 is not set

    Output using CMake 3.6.1.:

    Lib baselib
    Lib fiblib
    Example fibcmd
    Example fibgui
    CMake Warning (dev) at cmake/CompileOptions.cmake:52 (if):
      Policy CMP0054 is not set: Only interpret if() arguments as variables or
      keywords when unquoted.  Run "cmake --help-policy CMP0054" for policy
      details.  Use the cmake_policy command to set the policy and suppress this
      warning.
    
      Quoted variables like "MSVC" will no longer be dereferenced when the policy
      is set to NEW.  Since the policy is not set the OLD behavior will be used.
    Call Stack (most recent call first):
      source/tests/CMakeLists.txt:17 (include)
    This warning is for project developers.  Use -Wno-dev to suppress it.
    
    CMake Warning (dev) at cmake/CompileOptions.cmake:67 (if):
      Policy CMP0054 is not set: Only interpret if() arguments as variables or
      keywords when unquoted.  Run "cmake --help-policy CMP0054" for policy
      details.  Use the cmake_policy command to set the policy and suppress this
      warning.
    
      Quoted variables like "MSVC" will no longer be dereferenced when the policy
      is set to NEW.  Since the policy is not set the OLD behavior will be used.
    Call Stack (most recent call first):
      source/tests/CMakeLists.txt:17 (include)
    This warning is for project developers.  Use -Wno-dev to suppress it.
    
    CMake Warning (dev) at cmake/CompileOptions.cmake:94 (if):
      Policy CMP0054 is not set: Only interpret if() arguments as variables or
      keywords when unquoted.  Run "cmake --help-policy CMP0054" for policy
      details.  Use the cmake_policy command to set the policy and suppress this
      warning.
    
      Quoted variables like "MSVC" will no longer be dereferenced when the policy
      is set to NEW.  Since the policy is not set the OLD behavior will be used.
    Call Stack (most recent call first):
      source/tests/CMakeLists.txt:17 (include)
    This warning is for project developers.  Use -Wno-dev to suppress it.
    
    CMake Warning (dev) at cmake/CompileOptions.cmake:144 (if):
      Policy CMP0054 is not set: Only interpret if() arguments as variables or
      keywords when unquoted.  Run "cmake --help-policy CMP0054" for policy
      details.  Use the cmake_policy command to set the policy and suppress this
      warning.
    
      Quoted variables like "MSVC" will no longer be dereferenced when the policy
      is set to NEW.  Since the policy is not set the OLD behavior will be used.
    Call Stack (most recent call first):
      source/tests/CMakeLists.txt:17 (include)
    This warning is for project developers.  Use -Wno-dev to suppress it.
    
    Test fiblib-test
    Configuring done
    
    opened by j-o 6
  • Remove unnecessary files from googletest and googlemock

    Remove unnecessary files from googletest and googlemock

    Currently, the googletest and googlemock test suites bloat up a cmake-init project setup. We should remove all unnecessary files (e.g., documentation).

    requires decision 
    opened by scheibel 4
  • Bug Report: Separator Issue in  .localconfig/default

    Bug Report: Separator Issue in .localconfig/default

    in file .localconfig/default

    export CMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH}:D:/cmake-init-master/thirdparty/qt5"
    

    this does not work in windows got error running ./configure debug


    I change separator from : to ;

    export CMAKE_PREFIX_PATH="${CMAKE_PREFIX_PATH};D:/cmake-init-master/thirdparty/qt5"
    

    It works !

    opened by Kiddinglife 3
  • which items in which files should be modified when creating a new project?

    which items in which files should be modified when creating a new project?

    Can you specify what changes need to be made to cater for my own project? eg. change the name of template-config.cmake to xxx-config.cmake I believe there are more items than template-config.cmake to be changed. Am I right?

    thanks.

    opened by Kiddinglife 3
  • Add clang platform file for linux

    Add clang platform file for linux

    This is required to let the clang compiler use it's own header files instead of the gcc ones. Exemplary problem case: https://github.com/hpicgs/glbinding/issues/86

    Main caveat: you have to install libc++-dev so that the libc++ headers are available.

    opened by scheibel 3
  • Platform MSVC: /GL flag slows down debug build

    Platform MSVC: /GL flag slows down debug build

    The /GL compiler flag (whole program optimization) is enabled in debug and release build. This also enables link time code generation (/LTCG linker flag) in debug build, slowing down the build process. Here an example, the build time of libzeug (without examples) on a testing machine:

    • 1:56 with /GL enabled
    • 1:06 without

    This flag could be disabled using cmake generators, somehow like that:

    set(WIN32_COMPILE_FLAGS
        /commonflags
        $<$<CONFIG:Debug>: /debugflags... >
        $<$<CONFIG:Release>: /releaseflags... >)
    

    I think you don't need link time optimization in debug build, fast developing and testing is more important there. Anyway, the template should provide a possibility to set compiler flags per build type.

    opened by kateyy 3
  • Add explicit visibility for class and function templates (closes #56)

    Add explicit visibility for class and function templates (closes #56)

    The current symbol visibility is implemented as follows:

    • Symbols are hidden by default (default on Windows; enabled on Linux and macOS with -fvisibility=hidden)
    • Symbols of the public API of a library are tagged using an _API macro
      • for MSVC this translates to dllexport and dllimport declarations with respect to the current compilation state
      • for GCC and clang this macro declares default visibility

    Templates are not part of public interface as MSVC can't handle dllexport and dllimport on non-compiled symbols. Thus, we don't define visibility on templates and inline functions on Linux and macOS either and they are hidden by our default setting.

    To solve the visibility problem between the compilers MSVC, GCC and clang (considering the platforms Windows, Linux and macOS), I propose the following additional visibility behavior:

    • Differentiate between normal class and function visibility and template visibility
    • Add a specific _TEMPLATE_API macro that resolves to default visibility on GCC and clang but to nothing on MSVC
    opened by scheibel 2
  • Set CXX_VISIBILITY_PRESET to

    Set CXX_VISIBILITY_PRESET to "default" for AppleClang

    AppleClang (and clang?) handles RTTI for template instantiations a little different than MSVC and GCC: With visibility "hidden", a template instantiation in library A is a different type than the exact same template instantiation in library B that links against A. That means, that dynamic_casts between those types fail with AppleClang, but not with MSVC or GCC. With visibility "default", it works.

    An example is the gloperate::Loader<T>. During component registration, e.g., gloperate::Loader<Texture> is instantiated within the gloperate-qt-loaders plugin (soon to be gloperate-qt). Loader objects created by the ResourceManager have this type. When an application then calls ResourceManager::load<Texture>, gloperate::Loader<Texture> is instantiated again within the application. As both are different types according to AppleClangs RTTI, the dynamic_cast used to find a loader of the correct type always fails.

    A "clean" solution might be to explicitly export all those template instantiations; however, (I think) @scheibel and I both tried it and could not get it to work. Until someone actually manages that, I propose to set the cmake CXX_VISIBILITY_PRESET to "default" for AppleClang, as this is a very subtle bug that is hard to find.

    Does anybody know, whether this affects clang as well?

    opened by j-o 2
  • Fix list_extract function

    Fix list_extract function

    Since function creates a new variable scope, results must be propagated to the parent scope. See http://www.cmake.org/cmake/help/v3.0/command/set.html and http://www.cmake.org/cmake/help/v3.0/command/list.html

    opened by j-o 2
  • Enable multi-test setup

    Enable multi-test setup

    This PR consists of two small changes to optimize testing with cmake and gmock / gtest. First, after the sudirectory include it is tested if the appropriate target exists, so that the cmake script doesn't crash and the subdirectory script has the possibility to omit test target creation (e.g., because dependencies aren't available). Second, the output xml file for the test results must be different for all included tests so that the next executed test case doesn't overwrite the previous results.

    opened by scheibel 2
  • Drop GenerateExportHeader and WriteCompilerDetectionHeader

    Drop GenerateExportHeader and WriteCompilerDetectionHeader

    GenerateExportHeader doesn't do anything special that can't already be known before building the project (i.e. a regular, static header file has no disadvantages over it), and it creates issues in MultiArch environments, as the generated export header is compiler dependant (related to #35). See https://github.com/zyantific/zycore-c/pull/41 for an example.

    WriteCompilerDetectionHeader already generates issues in cmake-init, as it isn't available in CMake versions older than 3.2; at the same time, the module got removed in CMake 3.20.

    opened by Tachi107 0
  • Require CMake 3.5

    Require CMake 3.5

    As cmake-init requires policy CMP0063, it already effectively requires CMake 3.3. The oldest CMake version available in "mainstream" distributions is CMake 3.5, shipped with Ubuntu 16.04 (almost 7 years old, LTS support ended in 2021, in Extended security maintenance until 2026).

    Unless there's a reason to require an older CMake version, I don't see why not to upgrade.

    opened by Tachi107 0
  • Use target_link_options to pass linker options

    Use target_link_options to pass linker options

    As of CMake 3.13, the previously missing function target_link_options was introduced. I suggest to use this instead of target_link_libraries. The current implementation does not allow passing linker options for MSVC.

    Details: Options (and linker options, too) start with a front slash for MSVC (e.g., /LTCG). As we use target_link_libraries to pass this option to the linker, CMake assumes library names to link against and gracefully converts our Unix-encoded path separator to Windows-encoded path separators, resulting in \LTCG being passed to the linker.

    opened by scheibel 0
  • Option to generate cppcheck reports as xml file

    Option to generate cppcheck reports as xml file

    It would be nice to have an option to generate ccpcheck reports as an xml file. When calling cppcheck, using the --xml --output-file=<output_file> arguments forces cppcheck to output its report to the given file.

    opened by osechet 2
Owner
CG Internals
Computer Graphics Internals - Research, Engineering, Auditing, and Consulting
CG Internals
A CMake starter template using CPM

Cmake Starter About A lightweight Cmake project meant for a binary application (not a shared library), tests with catch2 are configured, CPM is the pa

Matt Williams 1 Jul 14, 2022
A template C++ repository, using CMake and Catch

C++ Project Template This is a template project for C++. It uses CMake to build and Catch for unit tests. It is integrated with Travis CI, and builds

Joshua Peterson 49 Oct 23, 2022
An OS-agnostic C++ library template in plain CMake.

?? How to export C++ library This repository provides an OS-agnostic C++ library template with plain CMake files with the following features: distribu

Robotology 302 Dec 17, 2022
A small c++ template with modern CMake

C++/CMake modern boilerplate This is a template for new projects, gives a good CMake base and a few dependencies you most likely want in your project.

Clément Grégoire 276 Jan 3, 2023
A minimal CMake template for Qt 5 & 6 projects

Minimal CMake Template for Qt 6 Projects This project is updated for Qt 6. Visit qt5 branch if you are looking for the Qt 5 template. This is a minima

Vincent Lee 180 Sep 21, 2022
CMake checks cache helper modules – for fast CI CMake builds!

cmake-checks-cache Cross platform CMake projects do platform introspection by the means of "Check" macros. Have a look at CMake's How To Write Platfor

Cristian Adam 65 Dec 6, 2022
CMake scripts for painless usage of SuiteSparse+METIS from Visual Studio and the rest of Windows/Linux/OSX IDEs supported by CMake

CMake scripts for painless usage of Tim Davis' SuiteSparse (CHOLMOD,UMFPACK,AMD,LDL,SPQR,...) and METIS from Visual Studio and the rest of Windows/Lin

Jose Luis Blanco-Claraco 395 Dec 24, 2022
cmake-font-lock - Advanced, type aware, highlight support for CMake

cmake-font-lock - Advanced, type aware, highlight support for CMake

Anders Lindgren 39 Oct 2, 2022
cmake-avr - a cmake toolchain for AVR projects

cmake-avr - a cmake toolchain for AVR projects Testing the example provided The toolchain was created and tested within the following environment: Lin

Matthias Kleemann 163 Dec 5, 2022
Make CMake less painful when trying to write Modern Flexible CMake

Izzy's eXtension Modules IXM is a CMake library for writing Modern flexible CMake. This means: Reducing the amount of CMake written Selecting reasonab

IXM 107 Sep 1, 2022
CMake module to enable code coverage easily and generate coverage reports with CMake targets.

CMake-codecov CMake module to enable code coverage easily and generate coverage reports with CMake targets. Include into your project To use Findcodec

HPC 82 Nov 30, 2022
unmaintained - CMake module to activate certain C++ standard, feature checks and appropriate automated workarounds - basically an improved version of cmake-compile-features

Compatibility This library provides an advanced target_compile_features() and write_compiler_detection_header(). The problem with those is that they a

Jonathan Müller 74 Dec 26, 2022
[CMake] [BSD-2] CMake module to find ICU

FindICU.cmake A CMake module to find International Components for Unicode (ICU) Library Note that CMake, since its version 3.7.0, includes a FindICU m

julp 29 Nov 2, 2022
Project to enable using CMake from a Maven build.

CMake-Maven-Project Introduction A Maven project for the CMake build system. It can be used by including it as a plugin within your Maven project's po

null 60 Nov 14, 2022
CMake project for BL602 RISC-V processor

bl602_cmake_base CMake project for BL602 RISC-V processor How to build NOTE : This project uses a pre-compiled version of the Buffalo SDK (bl_iot_sdk)

null 9 Jan 6, 2022
Enhanced CMake Project Manager plugin for Qt Creator

CMakeProjectManager2 Alternative CMake support for Qt Creator. Main differents from original CMakeProject plugin: Project file list readed from file s

Alexander Drozdov 71 Nov 20, 2022
A program that automatically generates CMake and Meson configuration files for your Vala project

Autovala is a program and a library designed to help in the creation of projects with Vala and CMake. It also has support for Genie.

Sergio Costas 108 Oct 15, 2022
Installation example for a C++ project (Windows) with Cmake.

CMakeInstallExample Installation example for a C++ project (Windows) with Cmake. Contents This project demonstrates how to use cmake with cpack to gen

Paul T 30 Jan 3, 2023
Example project which demonstrates various CMake features.

CMake example Example project which demonstrates various CMake features. CDash testing dashboard (probably empty but you can submit your test result t

Radovan Bast 142 Nov 4, 2022