xdigest-src 0.5.0

Extremely fast digest algorithm implementations packaged into a lightweight library (source code).
Documentation
#
# CMakeLists.txt: configuration for cmake build system
#
# ====================================================================
# Copyright 2026, Timofei Zhakov
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ====================================================================
#

cmake_minimum_required(VERSION 3.12)

project(xdigest LANGUAGES C)

include(GNUInstallDirs)
include(build/target_exports.cmake)

# Detect architecture
try_compile(
    DETECT_PLATFORM_RESULT
    ${CMAKE_CURRENT_BINARY_DIR}
    ${CMAKE_CURRENT_SOURCE_DIR}/build/detect_platform.c
    OUTPUT_VARIABLE DETECT_PLATFORM_OUTPUT
)

string(REGEX MATCH "DETECTED: ([a-z0-9]+)" _ ${DETECT_PLATFORM_OUTPUT})
set(CONFIG ${CMAKE_MATCH_1})

if ("${CONFIG}" STREQUAL "unsupported")
    set(ASM_SUPPORTED OFF)
else()
    set(ASM_SUPPORTED ON)
endif()

# options
include(CMakeDependentOption)

option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
cmake_dependent_option(USE_ASM "Enable assembly implementation." ON ASM_SUPPORTED OFF)
option(ENABLE_TESTS "Compile test-suite" ON)

if ("${CONFIG}" STREQUAL "unsupported")
    message(ERROR "Could not detect assembly architecture or one is not supported.")
endif()

if (USE_ASM)
    if (CONFIG MATCHES "win*.")
        enable_language(ASM_NASM)
        set(ASMEXT asm)
    else()
        enable_language(ASM)
        set(ASMEXT S)
        set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -Wa,--noexecstack")
    endif()
endif()

file(
  STRINGS "xdigest/include/xdigest/xdigest.h" VERSION_STRINGS
  REGEX "#define (XDIG_VERSION_MAJOR|XDIG_VERSION_MINOR|XDIG_VERSION_PATCH)"
)

string(REGEX REPLACE ".*XDIG_VERSION_MAJOR +([0-9]+).*" "\\1" XDIG_VERSION_MAJOR ${VERSION_STRINGS})
string(REGEX REPLACE ".*XDIG_VERSION_MINOR +([0-9]+).*" "\\1" XDIG_VERSION_MINOR ${VERSION_STRINGS})
string(REGEX REPLACE ".*XDIG_VERSION_PATCH +([0-9]+).*" "\\1" XDIG_VERSION_PATCH ${VERSION_STRINGS})

set(XDIG_VERSION "${XDIG_VERSION_MAJOR}.${XDIG_VERSION_MINOR}.${XDIG_VERSION_PATCH}")

add_library(xdigest
    xdigest/core/cpuid.c
    xdigest/core/armcap.c
    xdigest/core/riscvcap.c
    xdigest/core/version.c
    xdigest/core/mem_clr.c
    xdigest/sha/sha1.c
    xdigest/sha/sha256.c
    xdigest/sha/sha512.c
    xdigest/sha/sha_riscv.c
    xdigest/md5/md5_dgst.c
    xdigest/md5/md5_one.c
    xdigest/md5/md5_riscv.c
    xdigest/md4/md4_dgst.c
    xdigest/md4/md4_one.c
    xdigest/md2/md2_dgst.c
    xdigest/md2/md2_one.c
)

set_target_properties(xdigest PROPERTIES
    VERSION "${XDIG_VERSION}"
    SOVERSION "${XDIG_VERSION_MAJOR}"
)

if (USE_ASM)
    if (CONFIG MATCHES "riscv")
        target_sources(xdigest PRIVATE
            xdigest/core/asm/cpuid-${CONFIG}.${ASMEXT}
            xdigest/sha/asm/sha512-zbb-${CONFIG}.${ASMEXT}
            xdigest/sha/asm/sha512-zvkb-zvknhb-${CONFIG}.${ASMEXT}
            xdigest/sha/asm/sha256-zbb-${CONFIG}.${ASMEXT}
            xdigest/sha/asm/sha256-zvkb-zvknha_or_zvknhb-${CONFIG}.${ASMEXT}
            xdigest/md5/asm/md5-zbb-${CONFIG}.${ASMEXT}
        )

        target_compile_definitions(xdigest PRIVATE
            SHA256_ASM
            SHA512_ASM
            MD5_ASM
            xdig_CPUID_OBJ
        )
    else()
        target_sources(xdigest PRIVATE
            xdigest/core/asm/cpuid-${CONFIG}.${ASMEXT}
            xdigest/sha/asm/sha256-${CONFIG}.${ASMEXT}
            xdigest/sha/asm/sha512-${CONFIG}.${ASMEXT}
            xdigest/sha/asm/sha1-${CONFIG}.${ASMEXT}
            xdigest/md5/asm/md5-${CONFIG}.${ASMEXT}
        )

        target_compile_definitions(xdigest PRIVATE
            SHA1_ASM
            SHA256_ASM
            SHA512_ASM
            MD5_ASM
            xdig_CPUID_OBJ
        )
    endif()
else()
    target_compile_definitions(xdigest PRIVATE NO_ASM)
endif()

if (ENABLE_TESTS)
    enable_testing()

    add_executable(test_xdigest
        tests/test_xdigest.c
        tests/sha_test.c
    )
    target_link_libraries(test_xdigest PRIVATE xdigest)
    target_compile_definitions(test_xdigest PRIVATE XDIG)
    add_test(
        NAME test_xdigest
        COMMAND test_xdigest
    )
endif()

target_include_directories(xdigest PUBLIC
    "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/xdigest/include/xdigest>"
    "$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/xdigest>"
)

target_include_directories(xdigest PRIVATE
    "${CMAKE_CURRENT_SOURCE_DIR}/xdigest/include"
    "${CMAKE_CURRENT_SOURCE_DIR}/xdigest/core"
)

# Installation
install(
    TARGETS xdigest
    EXPORT xdigest-config
)

include(CMakePackageConfigHelpers)

install(
    EXPORT xdigest-config
    NAMESPACE xdigest::
    FILE "xdigest-config.cmake"
    DESTINATION "lib/cmake/xdigest"
)

write_basic_package_version_file(
    "${CMAKE_CURRENT_BINARY_DIR}/xdigest-config-version.cmake"
    VERSION ${XDIG_VERSION}
    COMPATIBILITY SameMajorVersion
)
install(
    FILES "${CMAKE_CURRENT_BINARY_DIR}/xdigest-config-version.cmake"
    DESTINATION "lib/cmake/xdigest"
)

file(GLOB public_headers "xdigest/include/xdigest/*.h")
install(FILES
    ${public_headers}
    DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/xdigest"
)
target_exports(xdigest ${public_headers})

configure_file(
    "${CMAKE_CURRENT_SOURCE_DIR}/build/xdigest.pc.in"
    "${CMAKE_CURRENT_BINARY_DIR}/xdigest.pc" @ONLY
)

install(
    FILES "${CMAKE_CURRENT_BINARY_DIR}/xdigest.pc"
    DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig"
)

message(STATUS "Configuration summary:")
message(STATUS "  Version ......................... : ${XDIG_VERSION}")
message(STATUS "  Build type ...................... : ${CMAKE_BUILD_TYPE}")
message(STATUS "  Assembly configuration .......... : ${CONFIG}")
message(STATUS "  Using Assembly .................. : ${USE_ASM}")
message(STATUS "  Build test suite ................ : ${ENABLE_TESTS}")
message(STATUS "  Install prefix: ................. : ${CMAKE_INSTALL_PREFIX}")