How to re-use sub-target header-files/dependencies

Hi!

I have the following structure
My project “example” depends on “wui” which inside of it has this statement:

include(ExternalProject)
ExternalProject_Add(cJSON_download
GIT_REPOSITORY https://github.com/DaveGamble/cJSON.git 
GIT_TAG "aafb64a1c549b7b927e339df6d35b1d5059dc235"
CMAKE_ARGS += -DCMAKE_INSTALL_PREFIX=${TARGET_OUT_DIR}/libs/cJSON
) 

add_library(libcJSON STATIC IMPORTED ${TARGET_OUT_DIR}/libs/cJSON/include) add_dependencies(libcJSON cJSON_download) 

# wui 
target_include_directories(wui INTERFACE ${TARGET_OUT_DIR}/libs/cJSON/include)

Now i am trying to build ‘example’ but i can’t seem to get the single header library to link properly.

In my ‘example’ I try to:

target_link_libraries(${PROJECT_NAME} INTERFACE cjson);

and I can see that it is downloaded and in the build files, but i can’t use it because #include "cJSON.h" cannot find any file.

How do you properly do it?

I know this should be somewhat possible.
I want to compile cJSON into a shared library and then share it with both consumers and let them use the same header.

Why not simply use this CMakeLists.txt and install the cmake config package yourself?

cmake_minimum_required(VERSION 3.28...3.30)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

project(cJSON-test VERSION 0.1.0 LANGUAGES C)

add_compile_options(-std=c17)
set(CMAKE_C_STANDARD 17)
set(CMAKE_C_EXTENSIONS NO)
set(CMAKE_C_STANDARD_REQUIRED YES)
set(CMAKE_BUILD_TYPE Release)

set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/stagedir)

enable_testing()

include(FetchContent)

FetchContent_Declare(
  cJSON
  GIT_REPOSITORY https://github.com/DaveGamble/cJSON.git
  GI_TAG "v1.7.18"
  SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cJSON-src"
  GIT_SHALLOW TRUE
)

set(ENABLE_CUSTOM_COMPILER_FLAGS OFF)
set(BUILD_SHARED_AND_STATIC_LIBS ON)

FetchContent_MakeAvailable(cJSON)

set(CPACK_GENERATOR TGZ)
include(cpack) # does not work with this cJSON!

This code fetches the files with FetchContent_Declare but doesn’t adress my main issue.
I want my ‘wui’ dependency to buil cJSON in a shared library way to use it again one target up.

The snipped above doesn’t build anything shared or otherwise; unless i am missreading cpacks docs.

What your code does as far as i understand it:

cmake_minimum_required(VERSION 3.28...3.30)

set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

project(cJSON-test VERSION 0.1.0 LANGUAGES CXX)

add_compile_options(-std=c17)
set(CMAKE_C_STANDARD 17)
set(CMAKE_C_EXTENSIONS NO)
set(CMAKE_C_STANDARD_REQUIRED YES)
set(CMAKE_BUILD_TYPE Release)

set(CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR}/stagedir)

enable_testing()

include(FetchContent)

FetchContent_Declare(
  cJSON
  GIT_REPOSITORY https://github.com/DaveGamble/cJSON.git
  GI_TAG "v1.7.18"
  # SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cJSON-src" # Puts the source of cJSON directly into this directory (where the cmakefile is). This might not be desired (personally i wouldn't want fetched content in my source control)
  GIT_SHALLOW TRUE
)


set(ENABLE_CUSTOM_COMPILER_FLAGS OFF)
set(BUILD_SHARED_AND_STATIC_LIBS ON)

FetchContent_MakeAvailable(cJSON) # Get the content

# What I would understand to work:
target_link_libraries(wui INTERFACE cJSON) # which should work as the cmake project builds this target

# Variable cJSON_SOURCE_DIR is populated by FetchContent, s othis points to my source
target_link_directories(wui PUBLIC ${cJSON_SOURCE_DIR})

# but even if i do this, my project cannot find `#include <cJSON.h>` in _wui_ which means not even the library i want to primarily use it in works

#

set(CPACK_GENERATOR TGZ) # Build with cpack, but this has nothing to do with the question as far as i can tell. I am not requiring a zip
include(cpack)

I found an error in my code,

I used target_link_directories instead of target_include_directories

With my code you use the lib with targe_-link_library() only!

Do you know how to do what I want to do without cpack ?
I tried doing this:


include(FetchContent) 
FetchContent_Declare( cjson 
GIT_REPOSITORY https://github.com/DaveGamble/cJSON.git 
GIT_TAG "v1.7.18" GIT_SHALLOW TRUE )

 SET(ENABLE_CJSON_TEST OFF CACHE BOOL "Enable cJSON tests") 

FetchContent_MakeAvailable(cjson) 
set(cjson_SOURCE_DIR ${cjson_SOURCE_DIR} PARENT_SCOPE) 

function(USE_CJSON target) 

target_include_directories(${target} PUBLIC ${cjson_SOURCE_DIR}) 

#target_link_libraries(${target} ${TARGET_OUT_DIR}/libs/cJSON/lib/cJSON.a) 

endfunction()

and then using USE_CJSON on any target i want this to be linked to.
But this breaks the build of the other executable i have completly.

That is a bad hack, do you know how modern cmake works?

include(FetchContent) 
FetchContent_Declare( cjson 
GIT_REPOSITORY https://github.com/DaveGamble/cJSON.git 
GIT_TAG "v1.7.18" GIT_SHALLOW TRUE )

 SET(ENABLE_CJSON_TEST OFF CACHE BOOL "Enable cJSON tests") 

FetchContent_MakeAvailable(cjson) 

function(USE_CJSON target) 
   target_link_libraries(${target} PUBLIC cjson) 
endfunction()

I fixed it myself, my problem wasn’t the fetch contet, cjson messed with my compile flags and that wrecked something else that looked like it was a problem with fetchcontent.

You ignore every suggestion?

Sometime it is a good idea to review the project before use it: see the cJSON CMakeLists.txt

Your suggestion pretty much says “Here is the piece of code you want, with no clear references of how it works or why it should be used instead of what you are doing”.

And no I don’t know how modern cmake works, that’s why I am here ? If I did I wouldn’t be asking; but throwing me the solution of a problem doesn’t help me learn about cmake.

Even after i found the compiler flag of cjson and turned it off. I still wanted to understand how to do that properly. I switched to a completly different library in the end for other reasons.

And excuse me for not understand all 260 lines of cmake code that cjson has, not all of which are clear to a beginner, and not finding that flag on the first go?

I understand its frustrating trying to explain something to someone, but you are assuming i already know stuff about cmake, which is an unsafe assumption.

I am sorry if i accidently posted this in the wrong forum, but i assumed this might as well be a “noob corner” question area where I can just ask if i am overwhelmed as well.

Sincerely: Someone who is learning. You don’t teach someone driving by throwing them into Arc de Triomphe after the first lesson.