An OS-agnostic C++ library template in plain CMake.

Overview

πŸ“š How to export C++ library

This repository provides an OS-agnostic C++ library template with plain CMake files with the following features:

Overview

πŸ’’ Complexities around C++ library

This project simplifies the process of taking a bunch of C++ classes/functions and exposing them as a CMake package so that third-party code can use it. However, the risk is that new users underestimate the actual complexity of maintaining a C++ library used by many external users!

A complete and proper training on the art and craft of C++ library maintenance is out of the scope of this project, but we feel that we should at least report some useful link to drive the curiosity and the attention of new users to topics relevant to a proper maintenence of a C++ library.

Problems typically overlooked by new C++ library developers:

πŸ… CI and badges

Awesomness Github Actions
Awesome GitHub Actions status

Go to the top

πŸŽ› Dependencies

There are no dependencies for this template. However, we make use of the following three files from the YCM project.

  1. AddInstallRPATHSupport
  2. AddUninstallTarget
  3. InstallBasicPackageFiles

These files can be found under ./cmake subdirectory and they are plain CMake code. Check them out, they make your life easier!

If you like the YCM project and it is not a problem to have it as a dependency, updating the template is as simple as follows.

  1. Install YCM
  2. Add find(YCM REQUIRED) in the main CMakeLists.txt, after the project() command.
  3. Delete/Empty the ./cmake folder.

You are now 100% good to go! πŸŽ‰

Go to the top

πŸ”¨ Build the libraries

If your shell environment supports mkdir, you can just execute the following commands:

git clone https://github.com/robotology/how-to-export-cpp-library.git
cd how-to-export-cpp-library
mkdir build && cd build
cmake ..
cmake --build .

You can also create platform specific input files for a native build system using CMake Generator.

For more detailed example, check the CGold section on Generate native tool files.

Go to the top

βœ‚οΈ Copy and customize this template

For customizing the CMake/C++ code, check the comments in the main CMakeLists.txt.

To enable Continuous Integration (CI) using Travis (Linux and macOS) and AppVeyor (Windows) follow the documentation of these services to create an account and connect them to your repository.

Once you're done with that, you can easily modify the appveyor.yml and travis.yml to account changes for your project, such as the project name from how-to-export-cpp-library (the name of the git repository) and LibTemplateCMake (the name of the CMake Project/Package) to the one of your repository/project.

Go to the top

πŸ”¬ Add a test

This snippet from test/CMakeLists.txt shows the fundamental commands to add a test:

add_executable(test_name_exec test_name_exec_source.cpp)
target_link_libraries(test_name_exec lib-template-cmake)
add_test(NAME test_name COMMAND test_name_exec)

A single test is just a simple C++ executable with an int main() function that returns 0 on success and any value different from 0 upon failure.

For more info on this topic and related CMake commands, check add_test documentation and references therein.

Go to the top

πŸ› Run the tests

If you want to run tests, compile the library enabling the BUILD_TESTING CMake option. Once you do that, test will be compiled along with the library and any other executable in the project.

To list the compiled/available tests, run ctest -N in the build directory. To run the tests, use ctest command in the build directory, while to run a single test, us ctest -R test_name. You can add -VV to get a full verbose output during tests.

For more info and options with ctest, check the ctest documentation.

Go to the top

πŸ“ Generate documentation

If the Doxygen tool is installed on your machine, the Doxygen documentation for the project can be generated using the dox target, see doc/CMakeLists.txt for details on the process of documents generation. Once generated, the doxygen documentation can be browsed at build/doc/html/index.html. If the documentation is generated, it will be installed in ${CMAKE_INSTALL_PREFIX}/share/doc/${PROJECT_NAME}/html/. The build and installation directories for the doxygen documentation can be changed using the DOXYGEN_BUILD_DIR and DOXYGEN_INSTALL_DIR CMake variables.

If you are interested on how to host your documentation using gh-pages, robotology/how-to-document-modules contains a detailed (and maintained) example on how to produce and host Doxygen documentation using GitHub gh-pages.

Go to the top

πŸ“‘ Licensing your library

The project as-is comes with two files:

  1. LICENSE
  2. LICENSE-template

The first file, LICENSE, is the one covering this very template. You have to modify/delete it. ⚠️ Don't use it straightforwardly as it includes our name, not yours!

The second file, LICENSE-template, is an MIT License template that you can use adding the year and copyright holder names in the heading. We provide template of the MIT License as it is the one used for this template, but you can choose one of the many available.

Should you not be sure what to do about it (licensing produces severe headhaces) you can use one of the following website to clear your mind:

Go to the top

πŸ’Ό Other template and examples

The Awesome CMake repository contains an interesting list of template and examples similar to this one.

Go to the top


If you feel this CMake project template was useful, consider starring the project!
We also created the following shield to provide a nice-looking link to this project (feel free to modify its look-and-feel as you please).
Otherwise, not a big deal! πŸ‘

how-to-export-cpp-library

Comments
  • CI pipeline with Github Actions

    CI pipeline with Github Actions

    I used this repository as a testbench for Github Actions. This is a first WIP multiplatform version I developed.

    From these first tests, Github Actions are amazing :) The platform is very generic and it allows sharing actions through repositories. Given its generality, we should discuss f2f how to proceed organization-wise :tada:

    cc @traversaro @pattacini @vtikha @claudiofantacci

    opened by diegoferigo 13
  • Missing `BUILD/INSTALL_${TARGET}_INCLUDEDIR` in CMakeLists.txt

    Missing `BUILD/INSTALL_${TARGET}_INCLUDEDIR` in CMakeLists.txt

    Some variable are missing before invoking install_basic_package_files() in the main CMakeLists.txt (line #70).

    In particular, just before line #70, a

    get_property(${PROJECT_NAME}_TARGETS GLOBAL PROPERTY ${PROJECT_NAME}_TARGETS)
    

    is missing to properly use the associated global variable.

    Furthermore, for install_basic_package_files() to work properly, the following 2 variables need to be declared:

    BUILD_${PROJECT_NAME}_INCLUDEDIR
    INSTALL_${PROJECT_NAME}_INCLUDEDIR
    

    I have an implementation that seems to work fine, even though it is not a clean solution in the case a user uses EXTRA_PATH_VARS_SUFFIX.

    We should briefly discuss a solution when we have some time :-)

    bug help wanted question 
    opened by claudiofantacci 12
  • Option to disable install rpath

    Option to disable install rpath

    In the template, we recommend to add a new option ENABLE_RPATH to control whether or not enable rpath on the installation binaries : https://github.com/robotology/how-to-export-cpp-library/blob/master/CMakeLists.txt#L57 .

    I noticed that now YARP deprecated the option for doing that, and instead is using the CMake existing option CMAKE_SKIP_INSTALL_RPATH to control if enabling installation rpath https://github.com/robotology/yarp/blob/eeeb98345d528ef56187b06c3712fdd66fadeb08/doc/installation/install_linux.dox#L165 . Using an already existing CMake variable seems to be a good idea. I propose to do the same here, but listing CMAKE_SKIP_INSTALL_RPATH explicitly as an option like we do with BUILD_SHARED_LIBS and BUILD_TESTING.

    enhancement 
    opened by traversaro 11
  • Any way to modify this for header only libraries ?

    Any way to modify this for header only libraries ?

    Not really header only, but just lot of header files and no target. I tried add_library(${LIBRARY_TARGET_NAME} INTERFACE)

    but I can't do

    set_target_properties(${LIBRARY_TARGET_NAME} PROPERTIES VERSION       ${${PROJECT_NAME}_VERSION}
                                                            PUBLIC_HEADER "${${LIBRARY_TARGET_NAME}_HDR}")
    

    I can't set the PUBLIC_HEADER property so none of the header files are being installed.

    question 
    opened by justinjk007 10
  • Update to the latest YCM version + some improvements

    Update to the latest YCM version + some improvements

    • Update YCM files to latest version (0.8.1)
    • Use EXPORT instead of TARGETS_PROPERTY in install_basic_package_files
    • Require CMake 3.5
    • Build position independent code and disable compiler extensions
    • Add optional dependency on YCM
    enhancement 
    opened by drdanz 9
  • Roll out new version of the project template (2018/12/15)

    Roll out new version of the project template (2018/12/15)

    With this PR we now have a refreshed, shiny and awesome CMake template for exporting Cpp libraries!

    In particular I tried to address all the entries of #33 by

    • Migrating Travis to Xenial and Xcode9.4, using addons for Homebrew (see #29).
    • Create a matching alias library with namspace prefix, as reported in Chapter 16.2 of C. Scott's Professional CMake (see #30).
    • Add header-only library template (see #31). This change had quite some implications. I found it useful to have a template just for that, as emerged from #28. This also impied the need for the project to export multiple libraries, not just one. Consequently, I had to add a variable with parent scopes to backprop to the main CMakeLists the name of the targets.
    • Polish up ✨ the README 😎 (see #35).
    • Change PATH (legacy keyword) in DIRECTORY in dox custom target (see #38).
    • Last, but not least, I tried to provide guidelines and useful links about the complexity of mantaining a C++ library (see #34).

    Let me know what you think and should you have any suggestion for improvements I'll try to address them asap! πŸ‘

    Closes #29, closes #30, closes #31, closes #32, closes #34, closes #35, closes #33, closes #38.

    enhancement documentation 
    opened by claudiofantacci 6
  • Migrate Travis to test on modern Linux distributions?

    Migrate Travis to test on modern Linux distributions?

    I recently renovated the Travis script for some robotology repos :

    • https://github.com/robotology/robotology-superbuild/pull/108
    • https://github.com/robotology/idyntree/pull/469
    • https://github.com/robotology/gazebo-fmi/pull/24

    To be honest, I mostly cargo-culted the Travis scripts from wb-toolbox and Dart, as discussed in https://github.com/robotology/robotology-superbuild/issues/96 .

    I wonder if it could make sense to migrate the Travis template provide in here to run on modern Linux distribution, as the default Trusty distribution shipped by Travis is now 4-years old and not officially supported by the robotology software.

    enhancement 
    opened by traversaro 6
  • C++ example repo created

    C++ example repo created

    Hi everybody, I have to write a self-contained library for the new algorithm for calibration of FT sensors, so to avoid rewriting everytime the same structure I tried to set up a reference repo for a typical C++ library.

    It is based on https://gitlab.robotology.eu/walkman/template-pkg that uses CMake/YCM, but with some additions (that would be out of scope for Walkman):

    • example of use of generated_export_header() cmake macro for correctly exposing symbols and build shared library easily also on Windows,
    • example of use of CTest and relative travis/appveyor scripts.

    There are still a lot of things to polish/finish, but I guess it can still be a useful reference.

    @francesco-romano @drdanz @arocchi feel free to suggest improvements, even for changes in the name of the repo/macros/source code structure. Perhaps Francesco can you add your usual rpath stuff?

    cc @lornat75

    opened by traversaro 4
  • Typo in RPATH CMake function

    Typo in RPATH CMake function

    I think here there's a typo:

    https://github.com/robotology/how-to-export-cpp-library/blob/e23e399fce102ba8f87cd5269797513000b99794/CMakeLists.txt#L108-L111

    It should be:

    add_install_rpath_support(BIN_DIRS "${CMAKE_INSTALL_FULL_BINDIR}"
                              LIB_DIRS "${CMAKE_INSTALL_FULL_LIBDIR}"
                              INSTALL_NAME_DIR "${CMAKE_INSTALL_FULL_LIBDIR}"
                              USE_LINK_PATH)
    

    cc @claudiofantacci @traversaro @drdanz

    bug 
    opened by diegoferigo 3
  • Add C to project LANGUAGES argument?

    Add C to project LANGUAGES argument?

    In https://github.com/robotology/how-to-export-cpp-library/blob/master/CMakeLists.txt#L26 we only list CXX in the LANGUAGES argument of the project call. This was done because this template is meant to show how to build a C++ library using CMake.

    However, in the past we had problems with some Find<package>.cmake scripts that required the C language to be enabled, see for example https://bitbucket.org/ignitionrobotics/ign-cmake/pull-requests/44/fix-findfreeimagecmake-compatibility-with/diff .

    Recently, we had the same problem with the FindHDF5.cmake with @pattacini and @vvasco . Given that the default setting (when LANGUAGES is not specified) is to enable both CXX and C, and classically Find<package>.cmake scripts have been written under those assumptions, I think it is a good idea to add C to the project LANGUAGES argument .

    Related bug: https://github.com/robotology/yarp/issues/548 .

    opened by traversaro 3
  •  Set default CMAKE_BUILD_TYPE

    Set default CMAKE_BUILD_TYPE

    Otherwise, the default build type will be None, with no optimization enabled. The related code in YARP is the following (from https://github.com/robotology/yarp/blob/9a395f6e41e01d8d350b6a4e5e2b2f6c6f913b74/cmake/YarpOptions.cmake#L69):

    if(NOT CMAKE_CONFIGURATION_TYPES)
      if(NOT CMAKE_BUILD_TYPE)
        # Encourage user to specify build type.
        message(STATUS "Setting build type to 'Release' as none was specified.")
        set_property(CACHE CMAKE_BUILD_TYPE PROPERTY VALUE "Release")
      endif()
    endif()
    
    opened by traversaro 3
  • Update repo to require CMake 3.16

    Update repo to require CMake 3.16

    We have been requiring the use of CMake 3.16 for robotology repos since September 2020 (see https://github.com/robotology/robotology-superbuild/issues/462). Now it could be a good time to review this repo and requiring CMake 3.16 also here, as these will drastically simplify some boilerplate.

    opened by traversaro 1
  • config: don't rely on CMAKE_CONFIGURATION_TYPES

    config: don't rely on CMAKE_CONFIGURATION_TYPES

    This can be set by a user by mistake. The global property is the trustworthy location for this information.

    Also set the standard build types as options on the build type so it is easy to switch in ccmake or cmake-gui.

    opened by mathstuf 1
  • Prefer GenerateExportHeader to EXPORT_ALL_SYMBOLS

    Prefer GenerateExportHeader to EXPORT_ALL_SYMBOLS

    In my experience, having finer control over exported symbols is much better than exporting all of them (either via the default behavior of GCC-and-friends or via WINDOWS_EXPORT_ALL_SYMBOLS). Among these benefits:

    • smaller binary size (internal template instantiation names can be hidden)
    • better inlining; if the compiler/LTO knows a symbol isn't exposed at all, it can be more aggressively inlined)
    • less chance of someone using a symbol you didn't intend to expose (more a problem in C than C++)

    Instead, GenerateExportHeader should be used to generate a header with _EXPORT macros to decorate classes, functions, and variables as being available to other libraries.

    opened by mathstuf 1
  • CMake > 3.11 and YCM dependency

    CMake > 3.11 and YCM dependency

    The current README, for what concerns the YCM dependency, recommends either vendoring the three files we require, or installing YCM externally.

    Starting from CMake 3.11, as many of you already know well, a new FetchContent module was introduced. It allows downloading and configuring external projects during the configuration phase of the project (contrarily to ExternalProject). Therefore, it is an excellent solution for dependencies like YCM.

    We should add in the README also this option. Sadly, the default CMake version on the current Ubuntu 18.04 LTS is still 3.10 though.

    For a minimal example you can refer to the following implementation:

    cc @traversaro @claudiofantacci @pattacini @drdanz

    opened by diegoferigo 10
  • Have the library `cookiecutter` friendly

    Have the library `cookiecutter` friendly

    The how-to-export-cpp-library can use the cookiecutter so that it can provide a simple command-line user experience to download and configure the CMake project template.

    enhancement help wanted 
    opened by claudiofantacci 1
Owner
Robotology
Group software repositories of the iCub eco-system (but code developed is not necessarily iCub specific!).
Robotology
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
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
Template for reliable, cross-platform C++ project setup using cmake.

The C++ CMake Project Template cmake-init is a sophisticated copy & paste template for modern C and C++ projects. The main goals include support of al

CG Internals 811 Jan 3, 2023
πŸ“¦ CMake's missing package manager. A small CMake script for setup-free, cross-platform, reproducible dependency management.

Setup-free CMake dependency management CPM.cmake is a CMake script that adds dependency management capabilities to CMake. It's built as a thin wrapper

CPM.cmake 1.6k Jan 9, 2023
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
Simple library for embedding static resources into C++ binaries using CMake

libromfs libromfs is an easy way to bundle resources directly into any C++ application and access them through a simple interface. The main advantage

WerWolv 28 Nov 30, 2022
Example library that shows best practices and proper usage of CMake by using targets

Modern CMake Sample Sample project that shows proper modern CMake usage on a dummy library and an executable that uses it. Accompanying code to my blo

Pablo Arias 601 Dec 29, 2022
Utility and common library for all polysquare cmake tools.

Polysquare CMake Tooling Utility Functions Utility and common library for all polysquare cmake tools. Status Travis CI (Ubuntu) AppVeyor (Windows) Cov

ポγƒͺεΉ³ζ–Ή POLYSQUARE 3 May 7, 2021
A template for projects using both libPeConv and MS Detours

A CMake template for projects using MS Detours along with libPeConv.

hasherezade 14 Dec 16, 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
A CMake toolchain file for iOS, macOS, watchOS & tvOS C/C++/Obj-C++ development

A CMake toolchain file for iOS, macOS, watchOS & tvOS C/C++/Obj-C++ development

Alexander Widerberg 1.4k Jan 4, 2023