From 807eadc601fa05827973735839dc8f5f80383dfd Mon Sep 17 00:00:00 2001 From: Masahiro Kozuka Date: Sat, 7 Mar 2026 19:34:54 +0900 Subject: [PATCH 1/2] Improve support for custom OpenSSL selection --- CMakeLists.txt | 25 ++++++++++++++++++++++--- Cargo.toml | 1 + scripts/build.rs | 18 +++++++++++++++--- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1eb1933add..b29ea166f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -112,6 +112,7 @@ option(QUIC_SKIP_CI_CHECKS "Disable CI specific build checks" OFF) option(QUIC_TELEMETRY_ASSERTS "Enable telemetry asserts in release builds" OFF) option(QUIC_USE_SYSTEM_LIBCRYPTO "Use system libcrypto if quictls TLS" OFF) option(QUIC_USE_EXTERNAL_OPENSSL "Use external OpenSSL instead of building from submodules" OFF) +set(QUIC_OPENSSL_DIR "" CACHE PATH "Path to OpenSSL directory") set(QUIC_OPENSSL_INCLUDE_DIR "" CACHE PATH "Path to OpenSSL include directory") set(QUIC_OPENSSL_LIB_DIR "" CACHE PATH "Path to OpenSSL library directory") option(QUIC_HIGH_RES_TIMERS "Configure the system to use high resolution timers" OFF) @@ -772,11 +773,19 @@ if(QUIC_TLS_LIB STREQUAL "quictls" OR QUIC_TLS_LIB STREQUAL "openssl") add_library(OpenSSLQuic INTERFACE) if(QUIC_OPENSSL_INCLUDE_DIR AND QUIC_OPENSSL_LIB_DIR) target_include_directories(OpenSSLQuic INTERFACE ${QUIC_OPENSSL_INCLUDE_DIR}) - find_library(LIB_CRYPTO NAMES crypto libcrypto PATHS ${QUIC_OPENSSL_LIB_DIR} NO_DEFAULT_PATH) + if(BUILD_SHARED_LIBS) + find_library(LIB_CRYPTO NAMES crypto libcrypto PATHS ${QUIC_OPENSSL_LIB_DIR} NO_DEFAULT_PATH) + else() + find_library(LIB_CRYPTO NAMES "crypto${CMAKE_STATIC_LIBRARY_SUFFIX}" "libcrypto${CMAKE_STATIC_LIBRARY_SUFFIX}" PATHS ${QUIC_OPENSSL_LIB_DIR} NO_DEFAULT_PATH) + endif() if(NOT LIB_CRYPTO) message(FATAL_ERROR "libcrypto not found in ${QUIC_OPENSSL_LIB_DIR}") endif() - find_library(LIB_SSL NAMES ssl libssl PATHS ${QUIC_OPENSSL_LIB_DIR} NO_DEFAULT_PATH) + if(BUILD_SHARED_LIBS) + find_library(LIB_SSL NAMES ssl libssl PATHS ${QUIC_OPENSSL_LIB_DIR} NO_DEFAULT_PATH) + else() + find_library(LIB_SSL NAMES "ssl${CMAKE_STATIC_LIBRARY_SUFFIX}" "libssl${CMAKE_STATIC_LIBRARY_SUFFIX}" PATHS ${QUIC_OPENSSL_LIB_DIR} NO_DEFAULT_PATH) + endif() if(NOT LIB_SSL) message(FATAL_ERROR "libssl not found in ${QUIC_OPENSSL_LIB_DIR}") endif() @@ -784,8 +793,18 @@ if(QUIC_TLS_LIB STREQUAL "quictls" OR QUIC_TLS_LIB STREQUAL "openssl") elseif(QUIC_OPENSSL_INCLUDE_DIR OR QUIC_OPENSSL_LIB_DIR) message(FATAL_ERROR "Both QUIC_OPENSSL_INCLUDE_DIR and QUIC_OPENSSL_LIB_DIR must be set to select custom OpenSSL version.") else() + if(QUIC_OPENSSL_DIR) + set(OPENSSL_ROOT_DIR "${QUIC_OPENSSL_DIR}") + endif() + if(NOT BUILD_SHARED_LIBS) + set(OPENSSL_USE_STATIC_LIBS TRUE) + endif() find_package(OpenSSL 3.5.0 REQUIRED) - target_link_libraries(OpenSSLQuic INTERFACE OpenSSL::SSL OpenSSL::Crypto) + # OpenSSL::SSL and OpenSSL::Crypto imported targets include their dependencies such as zstd. + # However, these dependencies will be linked in src/platform/CMakeLists.txt, + # so link only the main OpenSSL targets here to avoid duplication. + target_include_directories(OpenSSLQuic INTERFACE ${OPENSSL_INCLUDE_DIR}) + target_link_libraries(OpenSSLQuic INTERFACE ${OPENSSL_SSL_LIBRARY} ${OPENSSL_CRYPTO_LIBRARY}) endif() add_library(MsQuic::OpenSSL ALIAS OpenSSLQuic) else() diff --git a/Cargo.toml b/Cargo.toml index 70e5049b91..b5b2ef81c1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -90,6 +90,7 @@ find = [] # This feature enables quictls on windows, and has no effect on linux. # This feature enables openssl on windows, and has no effect on linux. openssl = [] +openssl-external = [] quictls = [] static = ["src"] preview-api = [] diff --git a/scripts/build.rs b/scripts/build.rs index 0cbb348619..c1d92cafde 100644 --- a/scripts/build.rs +++ b/scripts/build.rs @@ -29,9 +29,7 @@ fn cmake_build() { let target = env::var("TARGET").unwrap().replace("\\", "/"); let out_dir = env::var("OUT_DIR").unwrap().replace("\\", "/"); // The output directory for the native MsQuic library. - let libdir = "/lib"; - let full_out_dir = [out_dir, libdir.to_string()].join(""); - let quic_output_dir = Path::new(&full_out_dir); + let quic_output_dir = Path::new(&out_dir).join("artifacts"); // Builds the native MsQuic and installs it into $OUT_DIR. let mut config = Config::new("."); @@ -50,6 +48,20 @@ fn cmake_build() { config.define("QUIC_TLS_LIB", "quictls"); } else if cfg!(feature = "openssl") { config.define("QUIC_TLS_LIB", "openssl"); + } else if cfg!(feature = "openssl-external") { + config + .define("QUIC_TLS_LIB", "openssl") + .define("QUIC_USE_EXTERNAL_OPENSSL", "on"); + if let Ok(openssl_dir) = std::env::var("OPENSSL_DIR") { + config.define("QUIC_OPENSSL_DIR", openssl_dir); + } else { + if let Ok(openssl_include_dir) = std::env::var("OPENSSL_INCLUDE_DIR") { + config.define("QUIC_OPENSSL_INCLUDE_DIR", openssl_include_dir); + } + if let Ok(openssl_lib_dir) = std::env::var("OPENSSL_LIB_DIR") { + config.define("QUIC_OPENSSL_LIB_DIR", openssl_lib_dir); + } + } } else if cfg!(windows) { config.define("QUIC_TLS_LIB", "schannel"); } else { From 1ff7fe5636e7d00d8dbeabebb9777b5bb5a7c27f Mon Sep 17 00:00:00 2001 From: Masahiro Kozuka Date: Thu, 12 Mar 2026 16:57:04 +0900 Subject: [PATCH 2/2] fix problems --- CMakeLists.txt | 10 +++++----- Cargo.toml | 2 +- scripts/build.rs | 12 ++++++++---- src/rs/config.rs | 6 +++++- 4 files changed, 19 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index b29ea166f2..48d5bfe3a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -112,9 +112,9 @@ option(QUIC_SKIP_CI_CHECKS "Disable CI specific build checks" OFF) option(QUIC_TELEMETRY_ASSERTS "Enable telemetry asserts in release builds" OFF) option(QUIC_USE_SYSTEM_LIBCRYPTO "Use system libcrypto if quictls TLS" OFF) option(QUIC_USE_EXTERNAL_OPENSSL "Use external OpenSSL instead of building from submodules" OFF) -set(QUIC_OPENSSL_DIR "" CACHE PATH "Path to OpenSSL directory") set(QUIC_OPENSSL_INCLUDE_DIR "" CACHE PATH "Path to OpenSSL include directory") set(QUIC_OPENSSL_LIB_DIR "" CACHE PATH "Path to OpenSSL library directory") +set(QUIC_OPENSSL_ROOT_DIR "" CACHE PATH "Path to OpenSSL Root directory") option(QUIC_HIGH_RES_TIMERS "Configure the system to use high resolution timers" OFF) option(QUIC_OFFICIAL_RELEASE "Configured the build for an official release" OFF) set(QUIC_FOLDER_PREFIX "" CACHE STRING "Optional prefix for source group folders when using an IDE generator") @@ -764,12 +764,12 @@ if(QUIC_TLS_LIB STREQUAL "quictls" OR QUIC_TLS_LIB STREQUAL "openssl") add_library(OpenSSL INTERFACE) # OpenSSL versions before 3.5.0 do not expose these APIs. - if(QUIC_TLS_LIB STREQUAL "quictls" AND (QUIC_USE_EXTERNAL_OPENSSL OR QUIC_OPENSSL_INCLUDE_DIR OR QUIC_OPENSSL_LIB_DIR)) + if(QUIC_TLS_LIB STREQUAL "quictls" AND (QUIC_USE_EXTERNAL_OPENSSL OR QUIC_OPENSSL_INCLUDE_DIR OR QUIC_OPENSSL_LIB_DIR OR QUIC_OPENSSL_ROOT_DIR)) message(FATAL_ERROR "Manual OpenSSL selection is not supported with the 'quictls'. 'quictls' must be built from submodules to ensure static linkage with required QUIC APIs. Use 'openssl' provider for external 3.5.0+ OpenSSL.") endif() # Only 'openssl' provider supports external selection for now - if(QUIC_TLS_LIB STREQUAL "openssl" AND (QUIC_USE_EXTERNAL_OPENSSL OR QUIC_OPENSSL_INCLUDE_DIR OR QUIC_OPENSSL_LIB_DIR)) + if(QUIC_TLS_LIB STREQUAL "openssl" AND (QUIC_USE_EXTERNAL_OPENSSL OR QUIC_OPENSSL_INCLUDE_DIR OR QUIC_OPENSSL_LIB_DIR OR QUIC_OPENSSL_ROOT_DIR)) add_library(OpenSSLQuic INTERFACE) if(QUIC_OPENSSL_INCLUDE_DIR AND QUIC_OPENSSL_LIB_DIR) target_include_directories(OpenSSLQuic INTERFACE ${QUIC_OPENSSL_INCLUDE_DIR}) @@ -793,8 +793,8 @@ if(QUIC_TLS_LIB STREQUAL "quictls" OR QUIC_TLS_LIB STREQUAL "openssl") elseif(QUIC_OPENSSL_INCLUDE_DIR OR QUIC_OPENSSL_LIB_DIR) message(FATAL_ERROR "Both QUIC_OPENSSL_INCLUDE_DIR and QUIC_OPENSSL_LIB_DIR must be set to select custom OpenSSL version.") else() - if(QUIC_OPENSSL_DIR) - set(OPENSSL_ROOT_DIR "${QUIC_OPENSSL_DIR}") + if(QUIC_OPENSSL_ROOT_DIR) + set(OPENSSL_ROOT_DIR "${QUIC_OPENSSL_ROOT_DIR}") endif() if(NOT BUILD_SHARED_LIBS) set(OPENSSL_USE_STATIC_LIBS TRUE) diff --git a/Cargo.toml b/Cargo.toml index b5b2ef81c1..27a24b977d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -90,7 +90,7 @@ find = [] # This feature enables quictls on windows, and has no effect on linux. # This feature enables openssl on windows, and has no effect on linux. openssl = [] -openssl-external = [] +openssl_external = [] quictls = [] static = ["src"] preview-api = [] diff --git a/scripts/build.rs b/scripts/build.rs index c1d92cafde..7b7c8c573c 100644 --- a/scripts/build.rs +++ b/scripts/build.rs @@ -29,7 +29,11 @@ fn cmake_build() { let target = env::var("TARGET").unwrap().replace("\\", "/"); let out_dir = env::var("OUT_DIR").unwrap().replace("\\", "/"); // The output directory for the native MsQuic library. - let quic_output_dir = Path::new(&out_dir).join("artifacts"); + let quic_output_dir = if cfg!(windows) { + Path::new(&out_dir).join("lib") + } else { + Path::new(&out_dir).join("artifacts") + }; // Builds the native MsQuic and installs it into $OUT_DIR. let mut config = Config::new("."); @@ -48,12 +52,12 @@ fn cmake_build() { config.define("QUIC_TLS_LIB", "quictls"); } else if cfg!(feature = "openssl") { config.define("QUIC_TLS_LIB", "openssl"); - } else if cfg!(feature = "openssl-external") { + } else if cfg!(feature = "openssl_external") { config .define("QUIC_TLS_LIB", "openssl") .define("QUIC_USE_EXTERNAL_OPENSSL", "on"); - if let Ok(openssl_dir) = std::env::var("OPENSSL_DIR") { - config.define("QUIC_OPENSSL_DIR", openssl_dir); + if let Ok(openssl_dir) = std::env::var("OPENSSL_ROOT_DIR") { + config.define("QUIC_OPENSSL_ROOT_DIR", openssl_dir); } else { if let Ok(openssl_include_dir) = std::env::var("OPENSSL_INCLUDE_DIR") { config.define("QUIC_OPENSSL_INCLUDE_DIR", openssl_include_dir); diff --git a/src/rs/config.rs b/src/rs/config.rs index fb6e9fe463..9de830f4fc 100644 --- a/src/rs/config.rs +++ b/src/rs/config.rs @@ -476,7 +476,11 @@ mod tests { .unwrap_err() .try_as_status_code() .unwrap(); - if cfg!(windows) && !cfg!(feature = "openssl") && !cfg!(feature = "quictls") { + if cfg!(windows) + && !cfg!(feature = "openssl") + && !cfg!(feature = "openssl_external") + && !cfg!(feature = "quictls") + { // schannel does not support load from file. assert_eq!(load_err, StatusCode::QUIC_STATUS_NOT_SUPPORTED); } else {