0

I need to modify a C++ project to use Cereal library. The build system of this project is based on CMake. Since Cereal is a header only library and also uses CMake, I expect this to be a pretty simple task. I tried editing the CMakeLists.txt with:

include(ExternalProject)
ExternalProject_Add(cereal
GIT_REPOSITORY    git@github.com:USCiLab/cereal.git
CMAKE_ARGS -DJUST_INSTALL_CEREAL=ON -DSKIP_PORTABILITY_TEST=ON -DBUILD_TESTS=OFF
PREFIX ${CMAKE_INSTALL_PREFIX})

but somehow cmake tries to install cereal under /usr/local. I appreciate any help that can point me in the right direction.

Armut
  • 969
  • 8
  • 22
  • Have you tried to change this part in your CMake file:`-DJUST_INSTALL_CEREAL=ON`? – prehistoricpenguin May 22 '21 at 02:05
  • Thanks for the suggestion. Indeed, I don't even need `CMAKE_ARGS` since there is no need for configure or install for cereal. – Armut May 22 '21 at 02:30
  • 1
    You want FetchContent if it's a header only library, not ExternalProject – Alex Reinking May 22 '21 at 06:00
  • Thanks @AlexReinking, I tried `FetchContent_Declare( cereal GIT_REPOSITORY git@github.com:USCiLab/cereal.git ) FetchContent_MakeAvailable(cereal)` and it works, but I still need to add `include_directories( ${CMAKE_BINARY_DIR}/_deps/cereal-src/include)` otherwise the build can't find cereal. – Armut May 22 '21 at 07:05
  • I should add more info. Cereal is indeed an optional dependency and the actual code checks cereal with a macro `__has_include`. If I don't have `include_directories` for cereal, that macro returns false. – Armut May 22 '21 at 07:14
  • For the target that wants to use cereal, do what Guillaume suggested after FetchContent_MakeAvailable – Alex Reinking May 22 '21 at 08:46

2 Answers2

1

The proper way is always to link to the library:

target_link_libraries(your-executable PUBLIC cereal::cereal)

Since this library define a target, you can just use it so the include directories are automatically set to your target.

Guillaume Racicot
  • 39,621
  • 9
  • 77
  • 141
  • With the answer I posted, I don't need to install cereal. I think to use `target_link_libraries`, I need to install cereal, otherwise build fails with `target "cereal::cereal" not found`. Am I missing something here? Why do you think the answer I posted is not the proper way? – Armut May 22 '21 at 04:04
  • 1
    Because cereal might need to set compiler flags, definitions, etc. in order to be used. This is handled automatically by linking to a target, but not by using `include_directories` (which should never be used in new code anyway) – Alex Reinking May 22 '21 at 06:02
  • You do not need to install it in order to use `target_link_libraries` either. Just switch to FetchContent instead of ExternalProject. – Alex Reinking May 22 '21 at 06:03
  • @AlexReinking thanks for the information. May I learn why `include_directories` should not be used? From documentation I only see that `target_include_directories()` should be preferred, but no more details. – Armut May 22 '21 at 07:18
  • It's behavior is ridiculous and impossible to predict just by reading. It affects ALL targets in the directory in which it was called, even the ones created BEFORE the call, but it only affects targets created in _subdirectories_ that were added to the project AFTER the call. Using it is pointless because the target-specific version exists and it does nothing but cause confusion and general brain-death. No one should have to know what I just explained. _**Don't use it.**_ – Alex Reinking May 22 '21 at 08:49
  • 1
    @Armut you don't need to install it? You could simply `add_directory` and use the target. Or you could set the install prefix inside your project or inside your build directory and do `find_package` from there. The is no good excuses to not use targets. – Guillaume Racicot May 22 '21 at 12:09
-1

I am not sure if this is the best thing to do, but the following works. The trick is not to install anything and set include directory correctly.

include(ExternalProject)
ExternalProject_Add(cereal
  GIT_REPOSITORY    git@github.com:USCiLab/cereal.git
  PREFIX cereal
  SOURCE_DIR "${CMAKE_BINARY_DIR}/third-party/cereal"
  CONFIGURE_COMMAND ""
  BUILD_COMMAND ""
  INSTALL_COMMAND ""
)
include_directories(
    ${CMAKE_BINARY_DIR}/third-party/cereal/include) 
Armut
  • 969
  • 8
  • 22