Thalhammer / jwt-cpp

A header only library for creating and validating json web tokens in c++
https://thalhammer.github.io/jwt-cpp/
MIT License
855 stars 233 forks source link

Not able to add this library using git submodules in CMake #274

Closed minttr closed 1 year ago

minttr commented 1 year ago

What's your question?

Not able to add this library using git submodules in CMake

Additional Context

I am trying to add jwt-cpp in my project using CMake.

My project structure is as follows

build
External
---- jwt
.gitignore
.gitmodules
CMakeLists.txt
main.cpp

I used command git submodule add https://github.com/Thalhammer/jwt-cpp.git External/jwt to add the mentioned git submodule to my project. and the contents of the .gitmodules file is

[submodule "External/jwt"]
    path = External/jwt
    url = https://github.com/Thalhammer/jwt-cpp.git

My CMakeLists.txt looks like

cmake_minimum_required(VERSION 3.24.2)
set(This Trial)
project(${This} C CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

set(Sources main.cpp)
add_executable(${This} ${Sources})

add_subdirectory(External/jwt)

if(NOT TARGET jwt-cpp)
  find_package(jwt-cpp CONFIG REQUIRED)
endif()

target_include_directories(${This} INTERFACE External/jwt/include)
target_link_libraries(${This} INTERFACE jwt-cpp::jwt-cpp)

and my main.cpp is

#include <iostream>
#include <jwt-cpp/jwt.h>

int main ()
{
    return 0;
}

The issue I am facing is that everything configures builds properly if is don't include #include <jwt-cpp/jwt.h> in my main.cpp file but throws and error if I do that. The error looks like as follows:

fatal error: 'jwt-cpp/jwt.h' file not found
#include <jwt-cpp/jwt.h>
         ^~~~~~~~~~~~~~~
1 error generated.
make[2]: *** [CMakeFiles/Trial.dir/main.cpp.o] Error 1
make[1]: *** [CMakeFiles/Trial.dir/all] Error 2
make: *** [all] Error 2

I am not able to figure out what should I correct/change.

Thalhammer commented 1 year ago

Hi, The issue you are seeing is not an issue with jwt-cpp, but with the way you are linking your target.

You are telling CMake to add jwt-cpp as an interface dependency to your executable in these lines:

target_include_directories(${This} INTERFACE External/jwt/include)
target_link_libraries(${This} INTERFACE jwt-cpp::jwt-cpp)

However this does not cause cmake to link to the target when building the executable but only when building something that links your executable and even then it will only copy includes. What you want to do is link using either PRIVATE (if you are only using jwt-cpp internally) or PUBLIC (if you expose jwt-cpp on the api of a library). Given that you are compiling an executable it doesn't really matter that much which one you use, but I'd go with PRIVATE.

Another thing I noticed is the if(NOT TARGET jwt-cpp) check. This can never be false. The way add_subdirectory works is that it fails the configure step if there's no CMakeLists.txt in that folder (and if there is it will always define the jwt-cpp target). If you want to make the submodule optional and use a system installation if its not there you need to check for the existence of the file prior to invoking add_subdirectory.

I attached a minimal CMakeLists.txt for your example below. Note that the target_include_directories command is not needed because thats handled by target_link_libraries in conjunction with the way the target is defined.

cmake_minimum_required(VERSION 3.16)
set(This Trial)
project(${This} C CXX)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

set(Sources main.cpp)
add_executable(${This} ${Sources})

set(JWT_BUILD_EXAMPLES OFF)
add_subdirectory(External/jwt)
target_link_libraries(${This} PUBLIC jwt-cpp::jwt-cpp)

I am going to close this because its not really an issue of jwt-cpp, but if you have further questions about how to use cmake in this case, feel free to reply and/or reopen the issue.