From 62273bc3f7e131c8a6376bc8586d2c3cd9ba6091 Mon Sep 17 00:00:00 2001 From: OpenAI Date: Wed, 3 Jun 2026 18:31:39 +0000 Subject: [PATCH] Support build-tree libowfat and MatrixSSL dependencies --- CMakeLists.txt | 130 +++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 27 ++++++++++ 2 files changed, 157 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8700bd4..1a488a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,9 @@ set(TINYLDAP_SERVER_NAME "" CACHE STRING "Installed server executable name. Defa set(TINYLDAP_TOOL_PREFIX "" CACHE STRING "Optional prefix for non-server tool executable names") set(TINYLDAP_INCLUDE_SUBDIR "" CACHE STRING "Public include subdirectory below CMAKE_INSTALL_INCLUDEDIR. Defaults to TINYLDAP_OUTPUT_NAME") set(TINYLDAP_LIBOWFAT_INCLUDE_SUBDIR "" CACHE STRING "libowfat public include subdirectory. Defaults to LIBOWFAT_INSTALL_INCLUDE_SUBDIR if present, otherwise libowfat") +set(TINYLDAP_LIBOWFAT_BUILD_DIR "" CACHE PATH "Optional libowfat CMake build directory to consume directly without installation") +set(TINYLDAP_MATRIXSSL_BUILD_DIR "" CACHE PATH "Optional MatrixSSL CMake build directory to use for OpenSSL::Crypto compatibility") +set(TINYLDAP_MATRIXSSL_INCLUDE_SUBDIR "" CACHE STRING "MatrixSSL public include subdirectory inside TINYLDAP_MATRIXSSL_BUILD_DIR/include. Auto-detected when empty") if(NOT TINYLDAP_BUILD_STATIC AND NOT TINYLDAP_BUILD_SHARED) message(FATAL_ERROR "At least one of TINYLDAP_BUILD_STATIC or TINYLDAP_BUILD_SHARED must be ON") @@ -31,9 +34,74 @@ endif() if(TINYLDAP_INCLUDE_SUBDIR STREQUAL "") set(TINYLDAP_INCLUDE_SUBDIR "${TINYLDAP_OUTPUT_NAME}") endif() + +function(tinyldap_find_library_file out_var search_dir) + set(_tinyldap_found "") + foreach(_name IN LISTS ARGN) + foreach(_suffix IN ITEMS ".so*" ".dylib*" ".a") + file(GLOB _tinyldap_candidates LIST_DIRECTORIES false "${search_dir}/lib${_name}${_suffix}") + if(_tinyldap_candidates) + list(SORT _tinyldap_candidates) + list(GET _tinyldap_candidates 0 _tinyldap_found) + break() + endif() + endforeach() + if(_tinyldap_found) + break() + endif() + endforeach() + set(${out_var} "${_tinyldap_found}" PARENT_SCOPE) +endfunction() + +function(tinyldap_first_existing_dir out_var) + set(_tinyldap_found "") + foreach(_dir IN LISTS ARGN) + if(IS_DIRECTORY "${_dir}") + set(_tinyldap_found "${_dir}") + break() + endif() + endforeach() + set(${out_var} "${_tinyldap_found}" PARENT_SCOPE) +endfunction() + +function(tinyldap_first_include_root out_var include_subdir) + set(_tinyldap_found "") + foreach(_dir IN LISTS ARGN) + if(IS_DIRECTORY "${_dir}/${include_subdir}") + set(_tinyldap_found "${_dir}") + break() + endif() + endforeach() + set(${out_var} "${_tinyldap_found}" PARENT_SCOPE) +endfunction() + +# A libowfat build tree exports libowfat-config.cmake before install, but it may +# not have an adjacent libowfat-targets.cmake. Detect that layout when callers +# pass the build directory through CMAKE_PREFIX_PATH and consume the build tree +# directly instead of letting find_package() fail inside the incomplete config. +if(TINYLDAP_LIBOWFAT_BUILD_DIR STREQUAL "") + foreach(_prefix IN LISTS CMAKE_PREFIX_PATH) + if(EXISTS "${_prefix}/libowfat-config.cmake" AND NOT EXISTS "${_prefix}/libowfat-targets.cmake") + set(TINYLDAP_LIBOWFAT_BUILD_DIR "${_prefix}") + break() + endif() + endforeach() +endif() + if(TINYLDAP_LIBOWFAT_INCLUDE_SUBDIR STREQUAL "") if(DEFINED LIBOWFAT_INSTALL_INCLUDE_SUBDIR) set(TINYLDAP_LIBOWFAT_INCLUDE_SUBDIR "${LIBOWFAT_INSTALL_INCLUDE_SUBDIR}") + elseif(NOT TINYLDAP_LIBOWFAT_BUILD_DIR STREQUAL "") + file(GLOB _tinyldap_libowfat_build_include_dirs LIST_DIRECTORIES true + "${TINYLDAP_LIBOWFAT_BUILD_DIR}/include/*libowfat" + "${TINYLDAP_LIBOWFAT_BUILD_DIR}/generated/*libowfat") + if(_tinyldap_libowfat_build_include_dirs) + list(SORT _tinyldap_libowfat_build_include_dirs) + list(GET _tinyldap_libowfat_build_include_dirs 0 _tinyldap_libowfat_build_include_dir) + get_filename_component(TINYLDAP_LIBOWFAT_INCLUDE_SUBDIR "${_tinyldap_libowfat_build_include_dir}" NAME) + else() + set(TINYLDAP_LIBOWFAT_INCLUDE_SUBDIR "libowfat") + endif() else() set(TINYLDAP_LIBOWFAT_INCLUDE_SUBDIR "libowfat") endif() @@ -92,6 +160,23 @@ endif() if(TARGET libowfat::libowfat) set(TINYLDAP_LIBOWFAT_TARGET libowfat::libowfat) +elseif(NOT TINYLDAP_LIBOWFAT_BUILD_DIR STREQUAL "") + tinyldap_find_library_file(TINYLDAP_OWFAT_LIBRARY "${TINYLDAP_LIBOWFAT_BUILD_DIR}" + "${TINYLDAP_LIBOWFAT_INCLUDE_SUBDIR}" nwowfat owfat) + if(NOT TINYLDAP_OWFAT_LIBRARY) + message(FATAL_ERROR "Could not find libowfat library in TINYLDAP_LIBOWFAT_BUILD_DIR=${TINYLDAP_LIBOWFAT_BUILD_DIR}") + endif() + tinyldap_first_include_root(TINYLDAP_OWFAT_INCLUDE_ROOT "${TINYLDAP_LIBOWFAT_INCLUDE_SUBDIR}" + "${TINYLDAP_LIBOWFAT_BUILD_DIR}/include" + "${TINYLDAP_LIBOWFAT_BUILD_DIR}/generated") + if(NOT TINYLDAP_OWFAT_INCLUDE_ROOT) + message(FATAL_ERROR "Could not find libowfat build include root containing ${TINYLDAP_LIBOWFAT_INCLUDE_SUBDIR}/ in ${TINYLDAP_LIBOWFAT_BUILD_DIR}") + endif() + add_library(tinyldap_owfat_external UNKNOWN IMPORTED) + set_target_properties(tinyldap_owfat_external PROPERTIES + IMPORTED_LOCATION "${TINYLDAP_OWFAT_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${TINYLDAP_OWFAT_INCLUDE_ROOT}") + set(TINYLDAP_LIBOWFAT_TARGET tinyldap_owfat_external) else() find_package(libowfat CONFIG QUIET) if(TARGET libowfat::libowfat) @@ -106,6 +191,45 @@ endif() if(TARGET OpenSSL::Crypto) set(TINYLDAP_CRYPTO_TARGET OpenSSL::Crypto) +elseif(NOT TINYLDAP_MATRIXSSL_BUILD_DIR STREQUAL "") + if(TINYLDAP_MATRIXSSL_INCLUDE_SUBDIR STREQUAL "") + file(GLOB _tinyldap_matrixssl_include_dirs LIST_DIRECTORIES true + "${TINYLDAP_MATRIXSSL_BUILD_DIR}/include/*matrixssl") + if(_tinyldap_matrixssl_include_dirs) + list(SORT _tinyldap_matrixssl_include_dirs) + list(GET _tinyldap_matrixssl_include_dirs 0 _tinyldap_matrixssl_include_dir) + get_filename_component(TINYLDAP_MATRIXSSL_INCLUDE_SUBDIR "${_tinyldap_matrixssl_include_dir}" NAME) + else() + set(TINYLDAP_MATRIXSSL_INCLUDE_SUBDIR "matrixssl") + endif() + endif() + tinyldap_find_library_file(TINYLDAP_MATRIXSSL_CRYPTO_LIBRARY "${TINYLDAP_MATRIXSSL_BUILD_DIR}" + "${TINYLDAP_MATRIXSSL_INCLUDE_SUBDIR}" nwmatrixssl matrixssl) + if(NOT TINYLDAP_MATRIXSSL_CRYPTO_LIBRARY) + message(FATAL_ERROR "Could not find MatrixSSL library in TINYLDAP_MATRIXSSL_BUILD_DIR=${TINYLDAP_MATRIXSSL_BUILD_DIR}") + endif() + tinyldap_first_include_root(TINYLDAP_MATRIXSSL_OPENSSL_INCLUDE_ROOT "openssl" + "${TINYLDAP_MATRIXSSL_BUILD_DIR}/include/${TINYLDAP_MATRIXSSL_INCLUDE_SUBDIR}" + "${TINYLDAP_MATRIXSSL_BUILD_DIR}/include") + if(NOT TINYLDAP_MATRIXSSL_OPENSSL_INCLUDE_ROOT) + message(FATAL_ERROR "Could not find MatrixSSL OpenSSL compatibility include root in ${TINYLDAP_MATRIXSSL_BUILD_DIR}") + endif() + file(MAKE_DIRECTORY "${TINYLDAP_COMPAT_INCLUDE_DIR}/openssl") + if(NOT EXISTS "${TINYLDAP_MATRIXSSL_OPENSSL_INCLUDE_ROOT}/openssl/md5.h") + file(WRITE "${TINYLDAP_COMPAT_INCLUDE_DIR}/openssl/md5.h" "#pragma once +#include +#include +typedef psMd5_t MD5_CTX; +static inline int MD5_Init(MD5_CTX *c) { return psMd5Init(c) >= 0 ? 1 : 0; } +static inline int MD5_Update(MD5_CTX *c, const void *data, size_t len) { psMd5Update(c, (const unsigned char *)data, (uint32_t)len); return 1; } +static inline int MD5_Final(unsigned char *md, MD5_CTX *c) { psMd5Final(c, md); return 1; } +") + endif() + add_library(tinyldap_matrixssl_crypto_external UNKNOWN IMPORTED) + set_target_properties(tinyldap_matrixssl_crypto_external PROPERTIES + IMPORTED_LOCATION "${TINYLDAP_MATRIXSSL_CRYPTO_LIBRARY}" + INTERFACE_INCLUDE_DIRECTORIES "${TINYLDAP_MATRIXSSL_OPENSSL_INCLUDE_ROOT}") + set(TINYLDAP_CRYPTO_TARGET tinyldap_matrixssl_crypto_external) else() find_package(OpenSSL REQUIRED COMPONENTS Crypto) set(TINYLDAP_CRYPTO_TARGET OpenSSL::Crypto) @@ -323,3 +447,9 @@ if(TINYLDAP_INSTALL) endif() message(STATUS "tinyldap: building lib${TINYLDAP_OUTPUT_NAME}, server=${TINYLDAP_SERVER_NAME}, include=${TINYLDAP_INCLUDE_SUBDIR}, libowfat include=${TINYLDAP_LIBOWFAT_INCLUDE_SUBDIR}") +if(NOT TINYLDAP_LIBOWFAT_BUILD_DIR STREQUAL "") + message(STATUS "tinyldap: using libowfat build tree ${TINYLDAP_LIBOWFAT_BUILD_DIR}") +endif() +if(NOT TINYLDAP_MATRIXSSL_BUILD_DIR STREQUAL "") + message(STATUS "tinyldap: using MatrixSSL build tree ${TINYLDAP_MATRIXSSL_BUILD_DIR}") +endif() diff --git a/README.md b/README.md index 0ed041a..4d548e8 100644 --- a/README.md +++ b/README.md @@ -78,9 +78,36 @@ prefixed include directory such as `nwlibowfat`, set: When TinyLDAP is added below the CMake libowfat build, this is detected from `LIBOWFAT_INSTALL_INCLUDE_SUBDIR` automatically. +If libowfat has been configured in a separate build tree but not installed yet, +pass that build directory directly: + +```sh +cmake -S . -B build \ + -DTINYLDAP_LIBOWFAT_BUILD_DIR=/path/to/mars-libowfat-build \ + -DTINYLDAP_LIBOWFAT_INCLUDE_SUBDIR=nwlibowfat +``` + +TinyLDAP also detects this situation when the libowfat build directory is listed +in `CMAKE_PREFIX_PATH` and contains a build-tree `libowfat-config.cmake` without +an installed `libowfat-targets.cmake`. + ## OpenSSL / MatrixSSL compat TinyLDAP currently needs OpenSSL-style MD5 APIs for `auth.c` and `md5password.c`. If the parent project already provides `OpenSSL::Crypto` via MatrixSSL's OpenSSL-compat target, TinyLDAP will use it. Otherwise CMake falls back to the system OpenSSL Crypto library. + +For a separate MatrixSSL build tree that has not been installed, pass: + +```sh +cmake -S . -B build \ + -DTINYLDAP_MATRIXSSL_BUILD_DIR=/path/to/mars-matrixssl-build \ + -DTINYLDAP_MATRIXSSL_INCLUDE_SUBDIR=nwmatrixssl +``` + +The MatrixSSL include subdirectory is auto-detected when possible. The imported +build-tree target adds the correct include root so TinyLDAP's +`#include ` can resolve MatrixSSL's OpenSSL compatibility header. +If that build tree does not provide `openssl/md5.h`, TinyLDAP generates a small +build-local MD5 wrapper around MatrixSSL's `psMd5*` API.