open-source-parsers / jsoncpp

A C++ library for interacting with JSON.
Other
8.15k stars 2.64k forks source link

CMake FetchContent build error #1466

Open mratzloff opened 1 year ago

mratzloff commented 1 year ago

Describe the bug I'm attempting to switch my project's dependencies over to CMake's FetchContent functionality, but jsoncpp returns a build error. Full disclaimer, I'm just starting to experiment with the FetchContent functionality and I'm not an expert on CMake.

I'm using CMake 3.25.2. The version of CMake that introduced FetchContent_MakeAvailable, which downloads and builds external dependencies, was 3.14.

Here's the error:

λ cmake .
[...]
-- JsonCpp Version: 1.9.5
######################################################
# jsoncpp should not be configured & built in the jsoncpp source directory
# You must run cmake in a build directory.
# For example:
# mkdir jsoncpp-Sandbox ; cd jsoncpp-sandbox
# git clone https://github.com/open-source-parsers/jsoncpp.git # or download & unpack the source tarball
# mkdir jsoncpp-build
# this will create the following directory structure
#
# jsoncpp-Sandbox
#  +--jsoncpp
#  +--jsoncpp-build
#
# Then you can proceed to configure and build
# by using the following commands
#
# cd jsoncpp-build
# cmake ../jsoncpp # or ccmake, or cmake-gui
# make
#
# NOTE: Given that you already tried to make an in-source build
#       CMake have already created several files & directories
#       in your source tree. run 'git status' to find them and
#       remove them by doing:
#
#       cd jsoncpp-Sandbox/jsoncpp
#       git clean -n -d
#       git clean -f -d
#       git checkout --
#
######################################################
CMake Error at _deps/jsoncpp_dep-src/include/PreventInSourceBuilds.cmake:41 (message):
  Quitting configuration
Call Stack (most recent call first):
  _deps/jsoncpp_dep-src/include/PreventInSourceBuilds.cmake:45 (AssureOutOfSourceBuilds)
  _deps/jsoncpp_dep-src/CMakeLists.txt:81 (include)

To Reproduce Steps to reproduce the behavior:

  1. Include the following snippet in a project with a CMakeLists.txt file:
    
    cmake_minimum_required (VERSION 3.14)
    [...]
    FetchContent_Declare (jsoncpp_dep
    GIT_REPOSITORY https://github.com/open-source-parsers/jsoncpp
    GIT_TAG 5defb4ed1a4293b8e2bf641e16b156fb9de498cc)

FetchContent_MakeAvailable (jsoncpp_dep)


2. Run `cmake .` in the project directory.

**Expected behavior**
The project would build as expected.

**Desktop (please complete the following information):**
 - OS: macOS 12.6.3 Monterey
 - CMake 3.25.2
mratzloff commented 1 year ago

For anyone who might encounter the same issue, I resolved it with ExternalProject. I'm doing this after several FetchContent calls for other libraries, so if you don't do that, be sure to change jsoncpp_prefix.

include (ExternalProject)

set (jsoncpp_prefix ${FETCHCONTENT_BASE_DIR}/jsoncpp_dep)

ExternalProject_Add (jsoncpp_dep
    GIT_REPOSITORY https://github.com/open-source-parsers/jsoncpp
    GIT_TAG 5defb4ed1a4293b8e2bf641e16b156fb9de498cc
    PREFIX ${jsoncpp_prefix}
    CMAKE_CACHE_ARGS
        -DBUILD_SHARED_LIBS:BOOL=OFF
        -DBUILD_OBJECT_LIBS:BOOL=OFF
        -DJSONCPP_WITH_CMAKE_PACKAGE:BOOL=OFF
        -DJSONCPP_WITH_POST_BUILD_UNITTEST:BOOL=OFF
        -DJSONCPP_WITH_PKGCONFIG_SUPPORT:BOOL=OFF
        -DJSONCPP_WITH_TESTS:BOOL=OFF
    INSTALL_COMMAND "")

ExternalProject_Get_Property (jsoncpp_dep SOURCE_DIR BINARY_DIR)
set (jsoncpp_dep_SOURCE_DIR ${SOURCE_DIR})
set (jsoncpp_dep_BINARY_DIR ${BINARY_DIR})

set (jsoncpp_includes ${jsoncpp_dep_SOURCE_DIR}/include)
set (jsoncpp_lib ${jsoncpp_dep_BINARY_DIR}/lib)

target_link_libraries (my_project PRIVATE jsoncpp_object)
target_include_directories (my_project PRIVATE ${jsoncpp_includes})

If you're less familiar with CMake, jsoncpp_dep is my own name for the dependency, but jsoncpp_object comes from jsoncpp's CMakeLists.txt. It also defines and builds targets for jsoncpp_static and jsoncpp_lib, depending on what type of library you want to link to. I also wanted isolated builds, so I disabled the install step.

This could still be made to work with FetchContent, but I'll leave it up to the project maintainers on whether or not to close this ticket.

nabilwadih commented 1 year ago

Running into this same issue, it looks like by default FetchContent tries to build in the src dir instead of using a separate build dir, so this requirement breaks depending on this from FetchContent