4

I'm trying to apply modern CMake practices in my project. And I've came up with an issue with the {fmt} library dependency.

The structure of a project is the following (in a brief):

dev/
|
+--- fmt/   *unpacked archive of 4.1.0 version*
|
+--- mylib/
|    |
|    +--- mylib.hpp
|    |
|    +--- CMakeLists.txt
|         ***************************
|         * ...
|         * add_library(mylib INTERFACE)
|         * TARGET_LINK_LIBRARIES(mylib PUBLIC fmt-header-only)
|         * set(MYLIB_HEADERS_ALL mylib.hpp )
|         * ...
|         ***************************
|
+--- sample/
|    |
|    +--- main.cpp
|    |
|    +--- CMakeLists.txt
|         ***************************
|         * set(SAMPLE sample.hello_world)
|         * add_executable(${SAMPLE} main.cpp)
|         * TARGET_LINK_LIBRARIES(${SAMPLE} PRIVATE mylib)
|         * install(TARGETS ${SAMPLE} DESTINATION bin)
|         ***************************
|
+--- CMakeLists.txt
     ***************************
     * include_directories(${CMAKE_CURRENT_SOURCE_DIR})
     * add_subdirectory(fmt EXCLUDE_FROM_ALL)
     * add_subdirectory(sample/hello_world)
     ***************************

When I try to build it I receive an error:

PATH/mylib/mylib.hpp:6:10: fatal error: fmt/format.hpp: No such file or directory
 #include <fmt/format.hpp>
          ^~~~~~~~~~~~~~~~
compilation terminated.

Full reproduction can be found here: https://bitbucket.org/ngrodzitski/cmake-issue-fmt-20180410

Any suggestions on the issue?

vitaut
  • 49,672
  • 25
  • 199
  • 336
kola
  • 310
  • 2
  • 10
  • Instead of `make --build` run `make VERBOSE=1` and check whether corresponded include directory is passed to the compiler. – Tsyvarev Apr 10 '18 at 10:19
  • 1
    @Tsyvarev , no there is no path ${project_root}/dev/fmt which would have resolved the issue. Obviously I can add `include_directories(${CMAKE_CURRENT_SOURCE_DIR}/fmt)` to root CMakeLists.txt, but as it comes from presentation by Mathieu Ropert: [video](https://www.youtube.com/watch?v=eC9-iRN2b04) (slides page 44) `include_directories()` is considered harmful. And on the same slide it i stated: _Don’t use TARGET_INCLUDE_DIRECTORIES() with a path outside your module_. – kola Apr 10 '18 at 12:23
  • A link to [slides](https://github.com/CppCon/CppCon2017/blob/master/Tutorials/Using%20Modern%20CMake%20Patterns%20to%20Enforce%20a%20Good%20Modular%20Design/Using%20Modern%20CMake%20Patterns%20to%20Enforce%20a%20Good%20Modular%20Design%20-%20Mathieu%20Ropert%20-%20CppCon%202017.pdf) in separate comment as it was too long. – kola Apr 10 '18 at 12:25
  • Weird, according to the [code](https://github.com/fmtlib/fmt/blob/master/CMakeLists.txt#L140), target `fmt-header-only` has corresponded include directories attached. – Tsyvarev Apr 10 '18 at 12:37

1 Answers1

2

With the help from Mathieu Ropert in slack, I've resolved the issue in following steps:

  1. TARGET_LINK_LIBRARIES(mylib INTERFACE fmt::fmt-header-only) in mylib/CMakeLists.txt (PUBLIC before).
  2. add the following to root CMakeLists.txt: add_subdirectory(mylib) (that what makes a change).

I pushed final version to repo: https://bitbucket.org/ngrodzitski/cmake-issue-fmt-20180410.

kola
  • 310
  • 2
  • 10