0

I've looked at many different threads, but nothing seemed to work.

I'm trying to include the NLohmann JSON library using CMake. IntelliSense does autocomplete the filename sometimes, but you see a red or purple error line underneath the include and during compilation it can't find it. GTest does work though. Does someone know what's going on?

root: CMakeLists.txt

cmake_minimum_required (VERSION 3.10)

project(my_project LANGUAGES CXX VERSION 1.0.0)

enable_testing()

add_subdirectory("src")
add_subdirectory("test")

set_property(TARGET my_project PROPERTY CXX_STANDARD 20)

src: CMakeLists.txt

cmake_minimum_required (VERSION 3.10)

add_executable(my_project
    ...
    "main.cpp"
)

set_property(TARGET my_project PROPERTY CXX_STANDARD 20)

add_subdirectory("C:/dev/libs/nlohmann_json/3.11.2" "build/nlohmann_json")
target_link_libraries(my_project PRIVATE nlohmann_json::nlohmann_json)

test: CMakeLists.txt

cmake_minimum_required (VERSION 3.10)

add_executable(my_project_test
    "properties.cpp"
    "main.cpp"
)

set(CMAKE_CXX_FLAGS_DEBUG "/MTd")
set(CMAKE_CXX_FLAGS_RELEASE "/MT")

set_property(TARGET my_project_test PROPERTY CXX_STANDARD 20)

add_subdirectory("C:/dev/libs/googletest/1.12.1" "build/google_test")
target_link_libraries(my_project_test PRIVATE gtest)
JMRC
  • 1,473
  • 1
  • 17
  • 36
  • 1
    Next time make sure to include into the question post the **exact error message**, which in turn should note the **path** of the source/object **file** which causes it. By knowing that the error message is emitted not by your **library** but by your **test** it is easy to spot, that your `my_project_test` executable is not linked with nlohmann_json at all. – Tsyvarev Jan 20 '23 at 10:25
  • @Tsyvarev That was indeed the problem. I tried that, but made a mistake, which caused the confusion. The error message unfortunately didn't help though. – JMRC Jan 20 '23 at 10:36
  • 1
    "The error message unfortunately didn't help though." - In almost every case the error message gives important information about the problem. It could be that you failed to understand that information. No worries: this is why you (and many others) ask on Stack Overflow. But again, make sure to post that error message: it would help to an expert to understand your problem and answer your question. BTW. a requirement to post the error message is noted in [ask]. – Tsyvarev Jan 20 '23 at 10:55
  • @Tsyvarev CMake compiled without errors. The compiler only said: `C:\dev\...\c++\src\include\properties\property.h(6): fatal error C1083: Cannot open include file: 'nlohmann/json.hpp': No such file or directory ninja: build stopped: subcommand failed.`. But I'll keep it in mind. – JMRC Jan 20 '23 at 23:02
  • "The compiler only said..." - Aside from the **header** file, which contains incorrect `#include`, the build system should also output the **source** file (`.c`/`.cpp`) which has been compiled when the error message is printed. See e.g. the messages in [this question](https://stackoverflow.com/questions/58946328/microsoft-visual-studio-community-2019-fatal-error-c1083-cannot-open-include-f) or in [that one](https://stackoverflow.com/questions/74135276/qt-fatal-error-c1083-cannot-open-include-file-type-traits). – Tsyvarev Jan 20 '23 at 23:22

2 Answers2

1

I don't know how to make your setup work, but here is how I use the nlohmann json library in my project:

include(FetchContent)
FetchContent_Declare(
  json
  URL https://github.com/nlohmann/json/releases/download/v3.11.2/json.tar.xz
  DOWNLOAD_EXTRACT_TIMESTAMP YES  # <- May be needed depending on CMake version
)
FetchContent_MakeAvailable(json)
set(JSON_ImplicitConversions OFF) # <- You can skip this if you want

target_link_libraries(<your target> PRIVATE nlohmann_json::nlohmann_json)

FetchContent downloads, extracts, and compiles the library automatically, and then I just have to target_link_libraries to it.

Frodyne
  • 3,547
  • 6
  • 16
  • I'm trying to load a local install, but thank you for taking the time. 1+, because I do believe that this is a valid way. – JMRC Jan 20 '23 at 08:50
  • @JMRC for the local install you just need to import the targets like `FetchContent_MakeAvailable(...)` does. – Milan Š. Jan 20 '23 at 08:57
1

EDIT: Based on the discussion in chat the issue was related to a different project (the test project) which needed to be linked against nlohmann_json as well.

The bellow code was not needed, as the targets were already imported.


First of all your usage of add_subdirectory is not recommended, there is a reason why it's called add_subdirectory. That being said this is most likely due to the fact that the targets which you use are not exported and thus not visible to your CMakeLists.txt. REPLACE the build/nlohmann_json with a relative path using ${CMAKE_BINARY_DIR}.

The reason why Frodynes solution will work is because FetchContent_MakeAvailable(json) makes sure that the targets are exported.

What you need to do is use add_library with the IMPORTED tag. So to fix your solution you should most likely do the following to your CMakeLists.txt i.e. import the targets. Also note that I'm using the actual library name and not the alias. It might work with the alias but I'm not 100% sure about it:

set_property(TARGET my_project PROPERTY CXX_STANDARD 20)

add_subdirectory("C:/dev/libs/nlohmann_json/3.11.2" ${CMAKE_BINARY_DIR}/nlohmann_json) #fixed
#This doesn't generate a build step (which is already done by the add_subdirectory)
enter code here
add_library(nlohmann_json STATIC IMPORTED)
#OR add_library(nlohmann_json SHARED IMPORTED)
target_link_libraries(my_project PRIVATE nlohmann_json)

########
# OR with the alias:
# add_library(nlohmann_json::nlohmann_json STATIC IMPORTED)
# OR add_library(nlohmann_json::nlohmann_json SHARED IMPORTED)
# target_link_libraries(my_project PRIVATE nlohmann_json::nlohmann_json)
Milan Š.
  • 1,353
  • 1
  • 2
  • 11
  • If I remove the build folder I get an error: `add_subdirectory not given a binary directory but the given source directory "C:/dev/libs/nlohmann_json/3.11.2" is not a subdirectory of "C:/dev/mllow/c++/src". When specifying an out-of-tree source a binary directory must be explicitly specified.` – JMRC Jan 20 '23 at 08:38
  • Ah I see, my bad (the more you know), it's `CMake` way of handling out-of-tree source directories. I will edit my answer. – Milan Š. Jan 20 '23 at 08:40
  • @JMRC added an update using `${CMAKE_BINARY_DIR}` as that is more preferable (it's received from the variable that you get by specifying `cmake -Ssrc -Bbuild`, i.e. `build`) – Milan Š. Jan 20 '23 at 08:43
  • `add_subdirectory` already creates `nlohmann_json` and will therefore give an error at `add_library`. – JMRC Jan 20 '23 at 08:57
  • @JMRC that shouldn't be the case if you use the `IMPORTED` tag. But if it gives you an error you most likely have the targets already imported. Can you please provide the entire error logs both without my changes and with the changes? – Milan Š. Jan 20 '23 at 08:59
  • add_subdirectory("C:/dev/libs/nlohmann_json/3.11.2" `"${CMAKE_BINARY_DIR}/nlohmann_json") add_library(nlohmann_json STATIC IMPORTED) #set_property(TARGET nlohmann_json PROPERTY IMPORTED_LOCATION "C:/dev/libs/nlohmann_json/3.11.2") target_link_libraries(my_project_test PRIVATE nlohmann_json)` 1> [CMake] -- Using the multi-header code from C:/dev/libs/nlohmann_json/3.11.2/include/ 1> [CMake] CMake Error at src/CMakeLists.txt:26 (add_library): 1> [CMake] add_library cannot create imported target "nlohmann_json" because another 1> [CMake] target with the same name already exists. – JMRC Jan 20 '23 at 09:05
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/251280/discussion-between-milan-s-and-jmrc). – Milan Š. Jan 20 '23 at 09:06