diff --git a/.gitignore b/.gitignore index a594c29b7..bc177edfd 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ bld/ [Bb]in/ [Oo]bj/ [Ll]og/ +out/ # Visual Studio 2015 cache/options directory .vs/ diff --git a/CMakeLists.txt b/CMakeLists.txt index c22318810..4a501c6eb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,8 @@ if(POLICY CMP0135) # DOWNLOAD_EXTRACT_TIMESTAMP cmake_policy(SET CMP0135 NEW) endif() +set(CMAKE_EXPERIMENTAL_CXX_IMPORT_STD "d0edc3af-4c50-42ea-a356-e2862fe7a444") + # 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) @@ -20,6 +22,8 @@ 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_USE_IMPORT_STD "Use import std" 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) @@ -89,50 +93,94 @@ 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() -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 (JWT_ENABLE_MODULES) + if(CMAKE_VERSION VERSION_LESS "4.0") + message(FATAL_ERROR "CMake >= 4.0 is required to build with modules") + endif() + + set(CMAKE_CXX_SCAN_FOR_MODULES ON) + + if(JWT_USE_IMPORT_STD) + target_compile_features(jwt-cpp ${JWT_LIBRARY_TYPE} cxx_std_23) + if (NOT CMAKE_GENERATOR MATCHES "Visual Studio") + set(CMAKE_CXX_MODULE_STD 1) + endif() + else() + target_compile_features(jwt-cpp ${JWT_LIBRARY_TYPE} cxx_std_20) + endif() + + target_sources(jwt-cpp + PUBLIC + FILE_SET cxx_modules TYPE CXX_MODULES + BASE_DIRS ${JWT_MODULE_PATH} + FILES ${JWT_MODULE_PATH}/jwt.ixx + ) +else() + target_compile_features(jwt-cpp ${JWT_LIBRARY_TYPE} cxx_std_11) +endif() + +if (JWT_USE_IMPORT_STD) + target_compile_definitions(jwt-cpp ${JWT_LIBRARY_TYPE} JWT_USE_IMPORT_STD) +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 $ +target_include_directories(jwt-cpp ${JWT_LIBRARY_TYPE} $ $) 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}) + 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 @@ -143,18 +191,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.1 - 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.1 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 - 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) @@ -171,4 +223,4 @@ endif() if(JWT_BUILD_DOCS) add_subdirectory(docs) -endif() +endif() \ No newline at end of file diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index 3f87f424e..ffd04118d 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.8) +cmake_minimum_required(VERSION 3.15) project(jwt-cpp-examples) if(NOT TARGET jwt-cpp) @@ -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) diff --git a/example/es256k.cpp b/example/es256k.cpp index 0ba701927..3e8d8caf3 100644 --- a/example/es256k.cpp +++ b/example/es256k.cpp @@ -1,6 +1,12 @@ /// @file es256k.cpp #include +#include + +#ifndef JWT_ENABLE_MODULES #include +#else +import jwt_cpp; +#endif int main() { // openssl ecparam -name secp256k1 -genkey -noout -out ec-secp256k1-priv-key.pem diff --git a/example/jwks-verify.cpp b/example/jwks-verify.cpp index fa966e35a..38725c10d 100644 --- a/example/jwks-verify.cpp +++ b/example/jwks-verify.cpp @@ -5,7 +5,13 @@ * and using the corresponding x5c from the JWK to verify the token */ #include +#include + +#ifndef JWT_ENABLE_MODULES #include +#else +import jwt_cpp; +#endif #include int main() { diff --git a/example/print-claims.cpp b/example/print-claims.cpp index 15badcc9f..2f428e7fe 100644 --- a/example/print-claims.cpp +++ b/example/print-claims.cpp @@ -1,6 +1,11 @@ /// @file print-claims.cpp #include + +#ifndef JWT_ENABLE_MODULES #include +#else +import jwt_cpp; +#endif int main() { const std::string token = diff --git a/example/private-claims.cpp b/example/private-claims.cpp index f2718989d..948dc2cd5 100644 --- a/example/private-claims.cpp +++ b/example/private-claims.cpp @@ -1,8 +1,13 @@ /// @file private-claims.cpp -#include - #include #include +#include + +#ifndef JWT_ENABLE_MODULES +#include +#else +import jwt_cpp; +#endif using sec = std::chrono::seconds; using min = std::chrono::minutes; diff --git a/example/rsa-create.cpp b/example/rsa-create.cpp index 2243f2689..b70501b59 100644 --- a/example/rsa-create.cpp +++ b/example/rsa-create.cpp @@ -1,6 +1,12 @@ /// @file rsa-create.cpp #include +#include + +#ifndef JWT_ENABLE_MODULES #include +#else +import jwt_cpp; +#endif int main() { std::string const rsa_priv_key = R"(-----BEGIN PRIVATE KEY----- diff --git a/example/rsa-verify.cpp b/example/rsa-verify.cpp index c8240b49f..e2ed79127 100644 --- a/example/rsa-verify.cpp +++ b/example/rsa-verify.cpp @@ -1,6 +1,12 @@ /// \file rsa-verify.cpp #include +#include + +#ifndef JWT_ENABLE_MODULES #include +#else +import jwt_cpp; +#endif int main() { const std::string rsa_pub_key = R"(-----BEGIN PUBLIC KEY----- diff --git a/include/jwt-cpp/base.h b/include/jwt-cpp/base.h index 7258b2e70..912b84821 100644 --- a/include/jwt-cpp/base.h +++ b/include/jwt-cpp/base.h @@ -1,12 +1,16 @@ #ifndef JWT_CPP_BASE_H #define JWT_CPP_BASE_H +#ifdef JWT_USE_IMPORT_STD +import std; +#else #include #include #include #include #include #include +#endif #ifdef __has_cpp_attribute #if __has_cpp_attribute(fallthrough) diff --git a/include/jwt-cpp/jwt.h b/include/jwt-cpp/jwt.h index 80d8b95ef..65219b878 100644 --- a/include/jwt-cpp/jwt.h +++ b/include/jwt-cpp/jwt.h @@ -21,6 +21,9 @@ #include #include +#ifdef JWT_USE_IMPORT_STD +import std; +#else #include #include #include @@ -45,6 +48,8 @@ #endif #endif +#endif + #if OPENSSL_VERSION_NUMBER >= 0x30000000L // 3.0.0 #define JWT_OPENSSL_3_0 #include diff --git a/modules/jwt.ixx b/modules/jwt.ixx new file mode 100644 index 000000000..597eb5118 --- /dev/null +++ b/modules/jwt.ixx @@ -0,0 +1,66 @@ +module; + +#ifndef NOMINMAX +#define NOMINMAX 1 +#endif + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN 1 +#endif + +#ifndef JWT_USE_IMPORT_STD +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x30000000L +#include +#endif + +export module jwt_cpp; + +export { +#include "jwt-cpp/jwt.h" +} \ No newline at end of file