Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 57 additions & 0 deletions .github/workflows/modules.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
name: Build & Test with modules

on:
push:
branches: [master]
pull_request:
branches: [master]
paths:
- "CMakeLists.txt"
- "cmake/**"
- "include/jwt-cpp/**"
- "tests/cmake/**"
- ".github/actions/**"
- ".github/workflows/cmake.yml"

jobs:
build:
name: ${{ matrix.runs_on }}-${{ matrix.compiler }}
runs-on: ${{ matrix.runs_on }}
strategy:
fail-fast: false
matrix:
include:
- runs_on: windows-2025-vs2026
compiler: msvc-14.50
configure_preset: "x64-vs-modules"
build_preset: "x64-vs-modules-build"
test_preset : "x64-vs-modules-test"
- runs_on: ubuntu-26.04
compiler: gcc-15
cc: gcc-15
cxx: g++-15
configure_preset: "linux-modules"
build_preset: "linux-modules-build"
test_preset : "linux-modules-test"
- runs_on: ubuntu-26.04
compiler: clang-22
cc: clang-22
cxx: clang++-22
configure_preset: "linux-modules"
build_preset: "linux-modules-build"
test_preset : "linux-modules-test"
steps:

- uses: actions/checkout@v6

- uses: lukka/get-cmake@latest

- name: "Build & Test"
uses: lukka/run-cmake@v10
env:
CC: ${{ matrix.cc }}
CXX: ${{ matrix.cxx }}
with:
configurePreset: ${{ matrix.configure_preset }}
buildPreset: ${{ matrix.build_preset }}
testPreset: ${{ matrix.test_preset }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ bld/
[Bb]in/
[Oo]bj/
[Ll]og/
out/

# Visual Studio 2015 cache/options directory
.vs/
Expand Down
83 changes: 64 additions & 19 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ if(POLICY CMP0135) # DOWNLOAD_EXTRACT_TIMESTAMP
cmake_policy(SET CMP0135 NEW)
endif()

set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "451f2fe2-a8a2-47c3-bc32-94786d8fc91b" CACHE STRING "")

# HUNTER_ENABLED is always set if this package is included in a project using hunter (HunterGate sets it) In this case
# we will use hunter as well to stay consistent. If not the use can supply it on configure to force using hunter.
if(HUNTER_ENABLED)
Expand All @@ -20,6 +22,7 @@ option(JWT_BUILD_TESTS "Configure CMake to build tests (or not)" OFF)
option(JWT_BUILD_DOCS "Adds a target for building the doxygen documentation" OFF)
option(JWT_ENABLE_COVERAGE "Enable code coverage testing" OFF)
option(JWT_ENABLE_FUZZING "Enable fuzz testing" OFF)
option(JWT_ENABLE_MODULES "Build C++ modules" OFF)

option(JWT_DISABLE_PICOJSON "Do not provide the picojson template specialiaze" OFF)
option(JWT_DISABLE_BASE64 "Do not include the base64 implementation from this library" OFF)
Expand Down Expand Up @@ -92,50 +95,88 @@ endif()

set(JWT_INCLUDE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/include)
set(JWT_HEADER_FILES ${JWT_INCLUDE_PATH}/jwt-cpp/jwt.h)
set(JWT_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/modules)
foreach(traits ${JWT_JSON_TRAITS_OPTIONS})
list(APPEND JWT_HEADER_FILES ${JWT_INCLUDE_PATH}/jwt-cpp/traits/${traits}/defaults.h
${JWT_INCLUDE_PATH}/jwt-cpp/traits/${traits}/traits.h)
endforeach()

if(NOT JWT_DISABLE_BASE64)
list(APPEND JWT_HEADER_FILES ${JWT_INCLUDE_PATH}/jwt-cpp/base.h)
list(APPEND JWT_HEADER_FILES ${JWT_INCLUDE_PATH}/jwt-cpp/base.h)
endif()

if (JWT_ENABLE_MODULES)
if(CMAKE_VERSION VERSION_LESS "4.3")
message(FATAL_ERROR "CMake >= 4.3 is required to build with modules")
endif()

set(CMAKE_CXX_SCAN_FOR_MODULES ON)

if(NOT CMAKE_GENERATOR MATCHES "Visual Studio")
set(CMAKE_CXX_MODULE_STD 1)
endif()
endif()

add_library(jwt-cpp INTERFACE)
if (JWT_ENABLE_MODULES)
add_library(jwt-cpp STATIC)
set(JWT_LIBRARY_TYPE PUBLIC)
else()
add_library(jwt-cpp INTERFACE)
set(JWT_LIBRARY_TYPE INTERFACE)
endif()
add_library(jwt-cpp::jwt-cpp ALIAS jwt-cpp) # To match export
target_compile_features(jwt-cpp INTERFACE cxx_std_11)

if(NOT JWT_ENABLE_MODULES)
target_compile_features(jwt-cpp ${JWT_LIBRARY_TYPE} cxx_std_11)
else()
target_compile_features(jwt-cpp ${JWT_LIBRARY_TYPE} cxx_std_23)
target_sources(jwt-cpp
PUBLIC
FILE_SET cxx_modules TYPE CXX_MODULES
BASE_DIRS ${JWT_MODULE_PATH}
FILES ${JWT_MODULE_PATH}/jwt.cppm
)
endif()

if(JWT_DISABLE_BASE64)
target_compile_definitions(jwt-cpp INTERFACE JWT_DISABLE_BASE64)
target_compile_definitions(jwt-cpp ${JWT_LIBRARY_TYPE} JWT_DISABLE_BASE64)
endif()
if(JWT_DISABLE_PICOJSON)
target_compile_definitions(jwt-cpp INTERFACE JWT_DISABLE_PICOJSON)
target_compile_definitions(jwt-cpp ${JWT_LIBRARY_TYPE} JWT_DISABLE_PICOJSON)
endif()


source_group(
TREE "${JWT_INCLUDE_PATH}"
PREFIX "Implementation files"
FILES ${JWT_HEADER_FILES}
)

include(GNUInstallDirs)
include(CMakePackageConfigHelpers)
target_include_directories(jwt-cpp INTERFACE $<BUILD_INTERFACE:${JWT_INCLUDE_PATH}>
target_include_directories(jwt-cpp ${JWT_LIBRARY_TYPE} $<BUILD_INTERFACE:${JWT_INCLUDE_PATH}>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)

if(${JWT_SSL_LIBRARY} MATCHES "OpenSSL")
target_link_libraries(jwt-cpp INTERFACE OpenSSL::SSL OpenSSL::Crypto)
target_link_libraries(jwt-cpp ${JWT_LIBRARY_TYPE} OpenSSL::SSL OpenSSL::Crypto)
endif()

if(${JWT_SSL_LIBRARY} MATCHES "LibreSSL")
target_link_libraries(jwt-cpp INTERFACE LibreSSL::TLS)
target_link_libraries(jwt-cpp ${JWT_LIBRARY_TYPE} LibreSSL::TLS)
endif()

if(${JWT_SSL_LIBRARY} MATCHES "wolfSSL")
target_link_libraries(jwt-cpp INTERFACE PkgConfig::wolfssl)
target_link_libraries(jwt-cpp ${JWT_LIBRARY_TYPE} PkgConfig::wolfssl)
# This is required to access OpenSSL compatibility API
target_include_directories(jwt-cpp INTERFACE ${wolfssl_INCLUDE_DIRS})
# This flag is required to have the mandatory header included automatically
target_include_directories(jwt-cpp ${JWT_LIBRARY_TYPE} ${wolfssl_INCLUDE_DIRS})
# This flag is required to have the mandatory header included automatically
# https://github.com/Thalhammer/jwt-cpp/pull/352#discussion_r1627971786
# https://github.com/wolfSSL/wolfssl/blob/3b74a6402998a8b8839e25e31ba8ac74749aa9b0/wolfssl/wolfcrypt/settings.h#L58
target_compile_definitions(jwt-cpp INTERFACE EXTERNAL_OPTS_OPENVPN)
target_compile_definitions(jwt-cpp ${JWT_LIBRARY_TYPE} EXTERNAL_OPTS_OPENVPN)
endif()

if(NOT JWT_DISABLE_PICOJSON AND JWT_EXTERNAL_PICOJSON)
target_link_libraries(jwt-cpp INTERFACE picojson::picojson)
target_link_libraries(jwt-cpp ${JWT_LIBRARY_TYPE} picojson::picojson)
endif()

# Hunter needs relative paths so the files are placed correctly
Expand All @@ -146,18 +187,22 @@ endif()
configure_package_config_file(
${CMAKE_CURRENT_LIST_DIR}/cmake/jwt-cpp-config.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/jwt-cpp-config.cmake
INSTALL_DESTINATION ${JWT_CMAKE_FILES_INSTALL_DIR})
write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/jwt-cpp-config-version.cmake VERSION 0.7.2
COMPATIBILITY ExactVersion)

install(TARGETS jwt-cpp EXPORT jwt-cpp-targets PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
write_basic_package_version_file(${CMAKE_CURRENT_BINARY_DIR}/jwt-cpp-config-version.cmake VERSION 0.7.2 COMPATIBILITY ExactVersion)
if (JWT_ENABLE_MODULES)
install(TARGETS jwt-cpp EXPORT jwt-cpp-targets
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
FILE_SET cxx_modules DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/modules)
else()
install(TARGETS jwt-cpp EXPORT jwt-cpp-targets
PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
endif()
install(EXPORT jwt-cpp-targets NAMESPACE jwt-cpp:: FILE jwt-cpp-targets.cmake
DESTINATION ${JWT_CMAKE_FILES_INSTALL_DIR})
install(DIRECTORY ${JWT_INCLUDE_PATH}/jwt-cpp DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
if(NOT JWT_EXTERNAL_PICOJSON AND NOT JWT_DISABLE_PICOJSON)
install(FILES ${JWT_INCLUDE_PATH}/picojson/picojson.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/picojson)
endif()
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/jwt-cpp-config.cmake ${CMAKE_CURRENT_BINARY_DIR}/jwt-cpp-config-version.cmake
Comment thread
DockedFerret800 marked this conversation as resolved.
DESTINATION ${JWT_CMAKE_FILES_INSTALL_DIR})
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/jwt-cpp-config.cmake ${CMAKE_CURRENT_BINARY_DIR}/jwt-cpp-config-version.cmake DESTINATION ${JWT_CMAKE_FILES_INSTALL_DIR})

if(JWT_BUILD_EXAMPLES)
add_subdirectory(example)
Expand Down
55 changes: 55 additions & 0 deletions CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,75 @@
"JWT_BUILD_EXAMPLES": "ON",
"JWT_BUILD_TESTS": "ON"
}
},
{
"name": "windows-vs-base",
"hidden": true,
"generator": "Visual Studio 18 2026",
"binaryDir": "${sourceDir}/out/build/${presetName}",
"installDir": "${sourceDir}/out/install/${presetName}",
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Windows"
}
},
{
"name": "x64-vs-modules",
"displayName": "x64 (VS generator) with Modules (CI)",
"inherits": "windows-vs-base",
"architecture": "x64",
"cacheVariables": {
"JWT_ENABLE_MODULES": "ON",
"JWT_BUILD_EXAMPLES": "ON"
}
},
{
"name": "linux-modules",
"displayName": "Linux Debug with Modules (CI)",
"generator": "Ninja",
"binaryDir": "${sourceDir}/out/build/${presetName}",
"installDir": "${sourceDir}/out/install/${presetName}",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"JWT_ENABLE_MODULES": "ON",
"JWT_BUILD_EXAMPLES": "ON"
},
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Linux"
}
}
],
"buildPresets": [
{
"name": "dev",
"configurePreset": "dev",
"configuration": "Debug"
},
{
"name": "x64-vs-modules-build",
"configurePreset": "x64-vs-modules"
},
{
"name": "linux-modules-build",
"configurePreset": "linux-modules"
}
],
"testPresets": [
{
"name": "dev",
"displayName": "Run all tests",
"configurePreset": "dev"
},
{
"name": "x64-vs-modules-test",
"configurePreset": "x64-vs-modules"
},
{
"name": "linux-modules-test",
"configurePreset": "linux-modules"
}
]
}
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,14 @@ If you are looking to issue or verify more unique tokens, checkout out the [exam

Building on the goal of providing flexibility.

#### Modules support
jwt-cpp supports modules. Use `JWT_ENABLE_MODULES` to enable modules. This requires C++23, because modules are used in combination with `import std`.
CMake example:
```cmake
set(JWT_ENABLE_MODULES ON)
```
You can now `import jwt_cpp;`.

#### SSL Compatibility

jwt-cpp supports [OpenSSL](https://github.com/openssl/openssl), [LibreSSL](https://github.com/libressl-portable/portable), and [wolfSSL](https://github.com/wolfSSL/wolfssl). For a listed of tested versions, check [this page](docs/ssl.md) for more details.
Expand Down
8 changes: 8 additions & 0 deletions docs/install.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,14 @@ It's strongly recommended to use a package manager, as JWT-CPP has dependencies

When manually adding this dependency, and the dependencies this has, check the GitHub Actions and Workflows for some inspiration about how to go about it.

#### Modules support
jwt-cpp supports modules. Use `JWT_ENABLE_MODULES` to enable modules. This requires C++23, because modules are used in combination with `import std`.
CMake example:
```cmake
set(JWT_ENABLE_MODULES ON)
```
You can now `import jwt_cpp;`.

### Package Manager

- Conan: <https://conan.io/center/recipes/jwt-cpp>
Expand Down
20 changes: 19 additions & 1 deletion example/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.14)
cmake_minimum_required(VERSION 3.15)
project(jwt-cpp-examples)

if(NOT TARGET jwt-cpp)
Expand All @@ -14,25 +14,43 @@ endif()
add_executable(print-claims print-claims.cpp)
target_link_libraries(print-claims jwt-cpp::jwt-cpp)
add_custom_target(print-claims-run COMMAND print-claims)
if (JWT_ENABLE_MODULES)
target_compile_definitions(print-claims PRIVATE JWT_ENABLE_MODULES)
endif()

add_executable(private-claims private-claims.cpp)
target_link_libraries(private-claims jwt-cpp::jwt-cpp)
add_custom_target(private-claims-run COMMAND private-claims)
if (JWT_ENABLE_MODULES)
target_compile_definitions(private-claims PRIVATE JWT_ENABLE_MODULES)
endif()

add_executable(rsa-create rsa-create.cpp)
target_link_libraries(rsa-create jwt-cpp::jwt-cpp)
add_custom_target(rsa-create-run COMMAND rsa-create)
if (JWT_ENABLE_MODULES)
target_compile_definitions(rsa-create PRIVATE JWT_ENABLE_MODULES)
endif()

add_executable(rsa-verify rsa-verify.cpp)
target_link_libraries(rsa-verify jwt-cpp::jwt-cpp)
add_custom_target(rsa-verify-run COMMAND rsa-verify)
if (JWT_ENABLE_MODULES)
target_compile_definitions(rsa-verify PRIVATE JWT_ENABLE_MODULES)
endif()

add_executable(jwks-verify jwks-verify.cpp)
target_link_libraries(jwks-verify jwt-cpp::jwt-cpp)
add_custom_target(jwks-verify-run COMMAND jwks-verify)
if (JWT_ENABLE_MODULES)
target_compile_definitions(jwks-verify PRIVATE JWT_ENABLE_MODULES)
endif()

add_executable(es256k es256k.cpp)
target_link_libraries(es256k jwt-cpp::jwt-cpp)
if (JWT_ENABLE_MODULES)
target_compile_definitions(es256k PRIVATE JWT_ENABLE_MODULES)
endif()

add_executable(partial-claim-verifier partial-claim-verifier.cpp)
target_link_libraries(partial-claim-verifier jwt-cpp::jwt-cpp nlohmann_json::nlohmann_json)
7 changes: 7 additions & 0 deletions example/es256k.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
/// @file es256k.cpp

#ifndef JWT_ENABLE_MODULES
#include <chrono>
#include <iostream>
#include <jwt-cpp/jwt.h>
#else
import std;
import jwt_cpp;
#endif

int main() {
// openssl ecparam -name secp256k1 -genkey -noout -out ec-secp256k1-priv-key.pem
Expand Down
Loading