# Use external libraries using FetchContent.

**URL:** https://discourse.cmake.org/t/use-external-libraries-using-fetchcontent/2710
**Category:** Usage
**Tags:** os:linux
**Created:** [February 7, 2021, 11:46am UTC](https://discourse.cmake.org/t/use-external-libraries-using-fetchcontent/2710 "2021-02-07T11:46:29Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![Tyrreus](https://discourse.cmake.org/user_avatar/discourse.cmake.org/tyrreus/32/1181_2.png) [@Tyrreus](https://discourse.cmake.org/u/Tyrreus)
#### Post date: [February 7, 2021, 11:46am UTC](https://discourse.cmake.org/t/use-external-libraries-using-fetchcontent/2710/1 "2021-02-07T11:46:29Z")

</div>

# Problem description

Hi everyone! I’m starting the new project and I would like to make it using CMake in a good way from the beginning.

I’ve found the proposition of project structure at the [modern CMake](https://cliutils.gitlab.io/modern-cmake/chapters/basics/structure.html) book and It look’s that it has sense but unfortunately I can’t found a nice example of how to make it alive.

If there is a more common or modern structure that should be used please point it out.

Based on instructions from the mentioned book I’ve created a similar but simplified (for now) directories structure.

# Proposed directories structure

I want to logically separate external libraries from the application, use separate `CMakeLists.txt` to build the external modules and I won’t use _git submodules_ because as I’ve read somewhere the `FetchContent_Declare` should be used instead.

I want to create the following directories structure:

```
.
├── CMakeLists.txt
├── external
│ └── CMakeLists.txt
└── src
    ├── CMakeLists.txt
    └── main.cpp

```

- **`external`** directory will contain external libraries (like cli11, spdlog, etc.) which should be available in the **`src`** directory.
- **`src`** directory will contain the main application.

And this is how the `CMakeLists` looks like:

1. **Root** `CMakeLists.txt`:

```auto
    cmake_minimum_required(VERSION 3.16)

    project(
      KillingRobot
      VERSION 0.1
      DESCRIPTION "A self-aware robot who kills people who don't know CMake"
    )

    add_subdirectory(external)
    add_subdirectory(src)

```

1. **external** `CMakeLists.txt`:  
(I’m not sure if the separate requirements should be in the one CMakeLists.txt file or rather split into com `.in` files included in `CMakeLists.txt`.)

```auto
    cmake_minimum_required(VERSION 3.16)

    # Download libraries used in the project.
    include(FetchContent)

    # ----------------------------------------------------------
    # A fast and simple to use logging library.
    FetchContent_Declare(
      spdlog
      GIT_REPOSITORY https://github.com/gabime/spdlog.git
      GIT_TAG v1.8.2)

    FetchContent_GetProperties(spdlog)
    if(NOT spdlog_POPULATED)
      message("Cloning spdlod")
      FetchContent_Populate(spdlog)
      add_subdirectory(
        ${spdlog_SOURCE_DIR}
        ${spdlog_BINARY_DIR})
    endif()

    # ----------------------------------------------------------
    # A command line argument parser.
    FetchContent_Declare(
        cli11
        GIT_REPOSITORY https://github.com/CLIUtils/CLI11.git
        GIT_TAG v1.9.1)

    FetchContent_GetProperties(cli11)
    if(NOT cli11_POPULATED)
      message("Cloning CLI11")
      FetchContent_Populate(cli11)
      add_subdirectory(
        ${cli11_SOURCE_DIR}
        ${cli11_BINARY_DIR})
    endif()

```

1. **src** `CMakeLists.txt`:

```auto
    cmake_minimum_required(VERSION 3.16)

    add_executable(${CMAKE_PROJECT_NAME} main.cpp)

```

And below how the `main.cpp` file looks like:

```auto
    #include "spdlog/spdlog.h"
    #include "CLI/App.hpp"
    #include <string>

    int main(int argc, char *argv[]) {
      CLI::App app{"App description"};
      std::string filename = "default";
      app.add_option("-f,--file", filename, "A help string");
      CLI11_PARSE(app, argc, argv);

      spdlog::info("Filename: {0}", filename);
    }

```

# Choosen libraries

In the described example I’m using two libraries intentionally because the `spdlog` is a library where including a header file is enough for building but in the case of cli11, the built library should be linked by a linker.

# Downloaded libraries

After `cmake` the repositories are downloaded and stored in `build/_deps` directory as:

```
.
├── build
│ ├── _deps
│ │ ├── cli11-build
│ │ ├── cli11-src
│ │ ├── cli11-subbuild
│ │ ├── spdlog-build
│ │ ├── spdlog-src
│ │ └── spdlog-subbuild
(...)

```

Of course, it doesn’t build because the compiler can’t find the headers and library - it isn’t defined anywhere.

# What is needed?

I’m pretty sure that I should use:

- `target_link_libraries` for linking libraries
- `target_include_directories` for including the headers

Unfortunately, I can’t find a similar example (which may indicate that I’m doing something wrong). And I’m not sure if should I use them in: `src/CMakeLists.txt` or rather in the root `CMakeLists.txt` and the propagate it down to `src/CMakeLists.txt`.

# Questions

At the end I have some questions:

1. How to manage includes in this case?
2. How to manage libraries in this case?
3. Should I use `FetchContent_Declare` or maybe _`git submodules`_ as many other projects on github?
4. `FetchContent_Declare` is ok for downloading libraries used in includes or rather should be used to download standalone modules like `googletest` or other things independent from the application?

Best regards,  
Maciej

---

<div class="post-metadata">

### Author: ![ClausKlein](https://discourse.cmake.org/user_avatar/discourse.cmake.org/clausklein/32/352_2.png) [@ClausKlein](https://discourse.cmake.org/u/ClausKlein)
#### Post date: [February 27, 2021, 9:43pm UTC](https://discourse.cmake.org/t/use-external-libraries-using-fetchcontent/2710/2 "2021-02-27T21:43:21Z")

</div>

Fist of all, with `target_link_libraries`() the compile definitions, the cpp defines, and the libraries are imported. You should **not** need to set `target_include_directories`()

And perhaps, this may also interesting for you: [GitHub - TheLartians/ModernCppStarter: 🚀 Kick-start your C++! A template for modern C++ projects using CMake, CI, code coverage, clang-format, reproducible dependency management and much more.](https://github.com/TheLartians/ModernCppStarter)

And you may use [CPM.cmake](https://github.com/cpm-cmake/CPM.cmake):

```cmake
    # ---- Add dependencies via CPM ----
    # see https://github.com/cpm-cmake/CPM.cmake for more info

    include(cmake/CPM.cmake)

    # PackageProject.cmake will be used to make our target installable
    CPMAddPackage(
        NAME PackageProject.cmake
        GITHUB_REPOSITORY TheLartians/PackageProject.cmake
        VERSION 1.5.1
    )

    CPMAddPackage(
        NAME fmt
        GIT_TAG ${FMT_VERSION}
        GITHUB_REPOSITORY fmtlib/fmt # to get an installable target
        OPTIONS "FMT_INSTALL YES"
    )

    CPMAddPackage(
        NAME spdlog
        GIT_TAG v${SPDLOG_VERSION}
        GITHUB_REPOSITORY gabime/spdlog # to use our installed fmt lib
        OPTIONS "SPDLOG_FMT_EXTERNAL YES"
    )

```

**CPM** may faster because you can have a `local cache`, If you enable it, CPM use installed packages first. Default this feature is disable to have reproducible builds.

---

<div class="post-metadata">

### Author: ![Tyrreus](https://discourse.cmake.org/user_avatar/discourse.cmake.org/tyrreus/32/1181_2.png) [@Tyrreus](https://discourse.cmake.org/u/Tyrreus)
#### Post date: [March 3, 2021, 5:16pm UTC](https://discourse.cmake.org/t/use-external-libraries-using-fetchcontent/2710/3 "2021-03-03T17:16:53Z")

</div>

Thank you very much for the explanation and especially for the provided link! It’s super cool and thank you for your contribution! In this case - I’ll use it in my project.
