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://thelartians.github.io/ModernCppStarter
The Unlicense
4.45k stars 388 forks source link

CMake Error: install(EXPORT "GreeterTargets" ...) includes target "Greeter" which requires target "fmt-header-only" that is not in any export set. #79

Closed ClausKlein closed 3 years ago

ClausKlein commented 3 years ago

after adding a new build dependency I get this error:

Claus-iMac:ModernCppStarter clausklein$ !rm
rm -rf build/
Claus-iMac:ModernCppStarter clausklein$ cmake -G Ninja -B build -S standalone/
-- 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/Workspace/cpp/ModernCppStarter/build/cmake/CPM_0.28.2.cmake
-- CPM: adding package Ccache.cmake@1.2.2 (v1.2.2)
-- Using ccache: /usr/local/bin/ccache
-- CPM: adding package cxxopts@2.2.0 (v2.2.0)
-- cxxopts version 2.2.0
-- The C compiler identification is AppleClang 12.0.0.12000032
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- CPM: adding package Greeter@ (/Users/clausklein/Workspace/cpp/ModernCppStarter/standalone/..)
-- CPM: Greeter: adding package PackageProject.cmake@1.4 (v1.4)
-- CPM: Greeter: adding package fmt@7.1.3 (7.1.3)
-- Version: 7.1.3
-- Build type: 
-- CXX_STANDARD: 17
-- Performing Test has_std_17_flag
-- Performing Test has_std_17_flag - Success
-- Performing Test has_std_1z_flag
-- Performing Test has_std_1z_flag - Success
-- Performing Test SUPPORTS_USER_DEFINED_LITERALS
-- Performing Test SUPPORTS_USER_DEFINED_LITERALS - Success
-- Performing Test FMT_HAS_VARIANT
-- Performing Test FMT_HAS_VARIANT - Success
-- Required features: cxx_variadic_templates
-- Performing Test HAS_NULLPTR_WARNING
-- Performing Test HAS_NULLPTR_WARNING - Success
-- Looking for strtod_l
-- Looking for strtod_l - found
-- 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:ModernCppStarter clausklein$ 
TheLartians commented 3 years ago

The problem seems to be that the fmt library does not provide an installable target by default. This appears to be solved by setting the additional option FMT_INSTALL when adding the library.

CPMAddPackage(
  NAME fmt
  GIT_TAG 7.1.3
  GITHUB_REPOSITORY fmtlib/fmt
  OPTIONS "FMT_INSTALL YES"
)
ClausKlein commented 3 years ago

The problem seems to be that the fmt library does not provide an installable target by default. This appears to be solved by setting the additional option FMT_INSTALL when adding the library.

It is a different way they use: as a master project, the install option is ON.

But as subproject the option is OFF, what it is with fetchcontents module

I know a lot of projects doing it in this way.

spdlog, span, cereal, tomlplusplus, ...

ClausKlein commented 3 years ago

FYI https://discourse.cmake.org/t/using-a-header-only-library-with-fetchcontents-while-build-a-static-lib/2711?u=clausklein

TheLartians commented 3 years ago

It is a different way they use: as a master project, the install option is ON.

Yeah, in master project the option is set on by default, but it's still overridable. By adding the FMT_INSTALL YES option as described above the fmt target is now installable. Imo it's a good idea to install any targets that your library uses, even if they're header-only at the moment. For one if one of your headers includes the fmt library then users will need the library themselves anyways. Also if the library does ever change to a compiled library in a future version, you wouldn't run into any issues upgrading.

That said, if you've added the library using CPM.cmake, you can probably simply include the header directory to skip installation issues: target_include_directories(MyTarget ${fmt_SOURCE_DIR}/include).

ClausKlein commented 3 years ago

That said, if you've added the library using CPM.cmake, you can probably simply include the header directory to skip installation issues: target_include_directories(MyTarget ${fmt_SOURCE_DIR}/include).

I think this does not help if you want install your own project. Cmake will not generate the project with the error msg above.

TheLartians commented 3 years ago

I just tested using


CPMAddPackage(
  NAME fmt
  GIT_TAG 7.1.3
  GITHUB_REPOSITORY fmtlib/fmt
)

[...]

target_include_directories(MyTarget PRIVATE ${fmt_SOURCE_DIR}/include)

and could install the project without issues. As said before I still recommend using FMT_INSTALL, but it does seem to work without it.

ClausKlein commented 3 years ago

it is a CMAKE feature (with existing workaround)

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

helps. see too https://gitlab.kitware.com/cmake/cmake/-/issues/15415