# Using a header only library with FetchContents while build a static lib

**URL:** https://discourse.cmake.org/t/using-a-header-only-library-with-fetchcontents-while-build-a-static-lib/2711
**Category:** Code
**Created:** [February 7, 2021, 9:43pm UTC](https://discourse.cmake.org/t/using-a-header-only-library-with-fetchcontents-while-build-a-static-lib/2711 "2021-02-07T21:43:34Z")
**Posts on this page:** 8
**Page:** 1

<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 7, 2021, 9:43pm UTC](https://discourse.cmake.org/t/using-a-header-only-library-with-fetchcontents-while-build-a-static-lib/2711/1 "2021-02-07T21:43:34Z")

</div>

Why must I install an header only lib which I only need at build time for my own library?

```auto
Claus-iMac:example clausklein$ cmake -B build -S . -G Ninja
-- The CXX compiler identification is AppleClang 12.0.0.12000032
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Downloading CPM.cmake to /Users/clausklein/cmake/example/build/cmake/CPM_0.28.2.cmake
-- Version: 7.1.3
-- Build type: 
-- CXX_STANDARD: 17
# ...
-- Performing Test FMT_HAS_VARIANT
-- Performing Test FMT_HAS_VARIANT - Success
-- Required features: cxx_variadic_templates
-- Configuring done
CMake Error: install(EXPORT "GreeterTargets" ...) includes target "Greeter" which requires target "fmt-header-only" that is not in any export set.
-- Generating done
CMake Generate step failed. Build files cannot be regenerated correctly.
Claus-iMac:example clausklein$ 

```

```cmake
cmake_minimum_required(VERSION 3.14...3.19)

# ---- Project ----

# Note: update this to your new project's name and version
project(
    Greeter
    VERSION 1.0
    LANGUAGES CXX
)

# ---- Project settings ----

if(NOT DEFINED CMAKE_CXX_STANDARD)
    set(CMAKE_CXX_STANDARD 17)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    set(CMAKE_CXX_EXTENSIONS NO)
endif()

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

include(../CPM.cmake)

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

option(USE_FETCH_CONTENT "to show the problem is not caused by CPM" ON)
# XXX find_package(fmt 7.1)
if(NOT TARGET fmt::fmt-header-only)
    # NOTE: If fmt is not imported, we need to install it! CK
    # XXX option(FMT_INSTALL "" ON)
    option(FMT_INSTALL "" OFF)
    # to prevent CMake Error: install(EXPORT # "GreeterTargets" ...) includes target "Greeter" which
    # requires target "fmt" that is not in any export set.

    if(USE_FETCH_CONTENT)
        include(FetchContent)
        FetchContent_Declare(
            fmt
            GIT_REPOSITORY https://github.com/fmtlib/fmt.git
            GIT_TAG 7.1.3
        )
        FetchContent_MakeAvailable(fmt)
    else()
        CPMAddPackage(
            NAME fmt
            GIT_TAG 7.1.3
            GITHUB_REPOSITORY fmtlib/fmt
        )
    endif()
endif()

# ---- Create library ----

# Note: for header-only libraries change all PUBLIC flags to INTERFACE and create an interface
# target:
add_library(Greeter)
add_library(${PROJECT_NAME}::Greeter ALIAS Greeter)
target_compile_features(Greeter PUBLIC cxx_std_17)

target_sources(Greeter PRIVATE source/Greeter.cpp include/greeter/greeter.h)

# Link dependencies (if required)
target_link_libraries(Greeter PRIVATE fmt::fmt-header-only)

target_include_directories(
    Greeter PUBLIC $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
                   $<INSTALL_INTERFACE:include/${PROJECT_NAME}>
)

# ---- Create an installable target ----
# this allows users to install and find the library via `find_package()`.

# the location where the project's version header will be placed should match the project's regular
# header paths
string(TOLOWER ${PROJECT_NAME}/version.h VERSION_HEADER_LOCATION)

packageProject(
    NAME ${PROJECT_NAME}
    VERSION ${PROJECT_VERSION}
    NAMESPACE ${PROJECT_NAME}
    BINARY_DIR ${PROJECT_BINARY_DIR}
    INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include
    INCLUDE_DESTINATION include/${PROJECT_NAME}
    VERSION_HEADER "${VERSION_HEADER_LOCATION}"
    DEPENDENCIES "" # optional list of dependencies
)

```

---

<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 7, 2021, 9:51pm UTC](https://discourse.cmake.org/t/using-a-header-only-library-with-fetchcontents-while-build-a-static-lib/2711/2 "2021-02-07T21:51:16Z")

</div>

sipped from fmt config target:

```cmake
# Create imported target fmt::fmt-header-only
add_library(fmt::fmt-header-only INTERFACE IMPORTED)

set_target_properties(fmt::fmt-header-only PROPERTIES
  INTERFACE_COMPILE_DEFINITIONS "FMT_HEADER_ONLY=1"
  INTERFACE_COMPILE_FEATURES "cxx_variadic_templates"
  INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include"
)

```

---

<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 7, 2021, 9:52pm UTC](https://discourse.cmake.org/t/using-a-header-only-library-with-fetchcontents-while-build-a-static-lib/2711/3 "2021-02-07T21:52:44Z")

</div>

snippet from installed config Target of my example:

```cmake
# Create imported target Greeter
add_library(Greeter STATIC IMPORTED)

set_target_properties(Greeter PROPERTIES
  INTERFACE_COMPILE_FEATURES "cxx_std_17"
  INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include/Greeter"
  INTERFACE_LINK_LIBRARIES "\$<LINK_ONLY:fmt::fmt-header-only>"
)

```

---

<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 8, 2021, 8:45am UTC](https://discourse.cmake.org/t/using-a-header-only-library-with-fetchcontents-while-build-a-static-lib/2711/4 "2021-02-08T08:45:00Z")

</div>

@craig.scott Is this a cmake bug or a usage error?

(tested with cmake version 3.14 and 3.19, Ninja and Makefile generators)

---

<div class="post-metadata">

### Author: ![craig.scott](https://discourse.cmake.org/user_avatar/discourse.cmake.org/craig.scott/32/20_2.png) [@craig.scott](https://discourse.cmake.org/u/craig.scott)
#### Post date: [February 8, 2021, 10:21am UTC](https://discourse.cmake.org/t/using-a-header-only-library-with-fetchcontents-while-build-a-static-lib/2711/5 "2021-02-08T10:21:29Z")

</div>

I went to reply earlier today with a statement that it was expected behavior because `GreeterTargets` is a static library. Normally, that means the things it links to has to be transitively applied to its consumers as a `$<LINK_ONLY:...>` requirement. That’s indeed what you’re seeing, but I’m wondering if that still is theoretically needed when the dependency (`Greeter` in this case) is only an interface library. I suspect the difficulty comes from the interface library could in turn pull in other libraries that are needed for linking. So I’m assuming CMake has to do what it is currently doing, but maybe someone else (@brad.king?) can provide a more concrete answer.

---

<div class="post-metadata">

### Author: ![brad.king](https://discourse.cmake.org/user_avatar/discourse.cmake.org/brad.king/32/11_2.png) [@brad.king](https://discourse.cmake.org/u/brad.king)
#### Post date: [February 8, 2021, 2:14pm UTC](https://discourse.cmake.org/t/using-a-header-only-library-with-fetchcontents-while-build-a-static-lib/2711/6 "2021-02-08T14:14:20Z")

</div>

> the difficulty comes from the interface library could in turn pull in other libraries that are needed for linking

Yes. See [CMake Issue 15415](https://gitlab.kitware.com/cmake/cmake/-/issues/15415).

---

<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 8, 2021, 8:59pm UTC](https://discourse.cmake.org/t/using-a-header-only-library-with-fetchcontents-while-build-a-static-lib/2711/7 "2021-02-08T20:59:13Z")

</div>

Thanks, with this workaround it works fine

```cmake
target_link_libraries(Greeter PRIVATE $<BUILD_INTERFACE:fmt::fmt-header-only>)

```

---

<div class="post-metadata">

### Author: ![yisseamake](https://discourse.cmake.org/user_avatar/discourse.cmake.org/yisseamake/32/897_2.png) [@yisseamake](https://discourse.cmake.org/u/yisseamake)
#### Post date: [March 1, 2021, 9:47pm UTC](https://discourse.cmake.org/t/using-a-header-only-library-with-fetchcontents-while-build-a-static-lib/2711/8 "2021-03-01T21:47:02Z")

</div>

> [@ClausKlein](#):
>
> `PackageProject.cmake`

In “ from fmt config target” Which “fmt config target” ? if project is fmt, the cmake install(EXPORT generates file commonly named as fmtTargets.cmake which includes these 2 lines add\_library for each exported target and set of property, but fmtConfig.cmake typically is different file generated from fmtConfig.cmake.in so which one are these lines from ?
