cmake_minimum_required(VERSION 3.16) project(stable-diffusion.cpp-rest VERSION 1.0.0 DESCRIPTION "REST API server for stable-diffusion.cpp" LANGUAGES CXX ) # Set C++ standard set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Set build type if not specified if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release) endif() find_program(CCACHE_FOUND ccache) if(CCACHE_FOUND) set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache) set(ENV{CCACHE_SLOPPINESS} time_macros) message(STATUS "ccache found, compilation results will be cached") endif() # Add cmake modules path list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") # Include dependencies include(FindDependencies) # Version detection from git find_package(Git QUIET) if(GIT_FOUND) # Get current git commit hash (short) execute_process( COMMAND ${GIT_EXECUTABLE} rev-parse --short=8 HEAD WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE GIT_COMMIT_HASH OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET ) # Get full git commit hash execute_process( COMMAND ${GIT_EXECUTABLE} rev-parse HEAD WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE GIT_COMMIT_HASH_FULL OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET ) # Get current git tag (prefer annotated tags) execute_process( COMMAND ${GIT_EXECUTABLE} describe --tags --exact-match --abbrev=0 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE GIT_TAG OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET ) # Get git describe for fallback (e.g., v1.0.0-5-g12345678) execute_process( COMMAND ${GIT_EXECUTABLE} describe --tags --always --abbrev=8 WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE GIT_DESCRIBE OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET ) # Get git branch execute_process( COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE GIT_BRANCH OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET ) # Check if working directory is clean execute_process( COMMAND ${GIT_EXECUTABLE} status --porcelain WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE GIT_STATUS OUTPUT_STRIP_TRAILING_WHITESPACE ERROR_QUIET ) if(NOT GIT_COMMIT_HASH) set(GIT_COMMIT_HASH "unknown") endif() if(NOT GIT_COMMIT_HASH_FULL) set(GIT_COMMIT_HASH_FULL "unknown") endif() if(NOT GIT_DESCRIBE) set(GIT_DESCRIBE "unknown") endif() if(NOT GIT_BRANCH) set(GIT_BRANCH "unknown") endif() # Determine if working directory is clean if(GIT_STATUS STREQUAL "") set(GIT_CLEAN "true") else() set(GIT_CLEAN "false") endif() else() set(GIT_COMMIT_HASH "unknown") set(GIT_COMMIT_HASH_FULL "unknown") set(GIT_TAG "") set(GIT_DESCRIBE "unknown") set(GIT_BRANCH "unknown") set(GIT_CLEAN "false") endif() # Determine version string if(GIT_TAG) # Release build with tag set(PROJECT_VERSION_FULL "${GIT_TAG}") set(PROJECT_VERSION_TYPE "release") elseif(GIT_DESCRIBE AND NOT GIT_DESCRIBE STREQUAL "unknown") # Development build with git describe set(PROJECT_VERSION_FULL "${GIT_DESCRIBE}") set(PROJECT_VERSION_TYPE "development") else() # Fallback to commit hash set(PROJECT_VERSION_FULL "g${GIT_COMMIT_HASH}") set(PROJECT_VERSION_TYPE "development") endif() # Add dirty suffix if working directory is not clean if(GIT_CLEAN STREQUAL "false") set(PROJECT_VERSION_FULL "${PROJECT_VERSION_FULL}-dirty") endif() # Build timestamp string(TIMESTAMP BUILD_TIMESTAMP "%Y-%m-%dT%H:%M:%SZ" UTC) # Set project variables set(PROJECT_VERSION_COMMIT "${GIT_COMMIT_HASH}") set(PROJECT_VERSION_COMMIT_FULL "${GIT_COMMIT_HASH_FULL}") set(PROJECT_VERSION_BRANCH "${GIT_BRANCH}") set(PROJECT_VERSION_CLEAN "${GIT_CLEAN}") set(PROJECT_VERSION_BUILD_TIME "${BUILD_TIMESTAMP}") # Display version information message(STATUS "Version Information:") message(STATUS " Version: ${PROJECT_VERSION_FULL}") message(STATUS " Type: ${PROJECT_VERSION_TYPE}") message(STATUS " Commit: ${GIT_COMMIT_HASH}") message(STATUS " Branch: ${GIT_BRANCH}") message(STATUS " Clean: ${GIT_CLEAN}") message(STATUS " Build Time: ${BUILD_TIMESTAMP}") # Generate version header file configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/include/version.h.in" "${CMAKE_CURRENT_BINARY_DIR}/include/version.h" @ONLY ) # Option for CUDA support option(SD_CUDA_SUPPORT "Enable CUDA support in stable-diffusion.cpp" ON) # Option for building Web UI option(BUILD_WEBUI "Build the web UI and bundle it with the server" ON) # Option for PAM authentication support option(ENABLE_PAM_AUTH "Enable PAM (Pluggable Authentication Modules) support" ON) # Find CUDA if support is enabled if(SD_CUDA_SUPPORT) find_package(CUDAToolkit REQUIRED) message(STATUS "CUDA Toolkit found: ${CUDAToolkit_VERSION}") endif() # ExternalProject for stable-diffusion.cpp include(ExternalProject) # Set up external project for stable-diffusion.cpp ExternalProject_Add(stable-diffusion.cpp GIT_REPOSITORY https://github.com/leejet/stable-diffusion.cpp.git GIT_TAG master-347-6103d86 SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/stable-diffusion.cpp-src" BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/stable-diffusion.cpp-build" CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}/stable-diffusion.cpp-install -DSD_CUDA=${SD_CUDA_SUPPORT} -DSD_BUILD_EXAMPLES=OFF BUILD_COMMAND ${CMAKE_COMMAND} --build . --config ${CMAKE_BUILD_TYPE} INSTALL_COMMAND ${CMAKE_COMMAND} --install . --config ${CMAKE_BUILD_TYPE} LOG_DOWNLOAD ON LOG_CONFIGURE ON LOG_BUILD ON LOG_INSTALL ON ) # Get the include directories and libraries from the external project ExternalProject_Get_Property(stable-diffusion.cpp SOURCE_DIR BINARY_DIR) # Set include directories for the external project set(SD_CPP_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}/stable-diffusion.cpp-install/include ${SOURCE_DIR} ${SOURCE_DIR}/ggml/include ) # Set library directories set(SD_CPP_LIB_DIR ${CMAKE_CURRENT_BINARY_DIR}/stable-diffusion.cpp-install/lib) # Build Web UI if enabled if(BUILD_WEBUI) # Check if Node.js and npm are available find_program(NPM_EXECUTABLE npm) if(NPM_EXECUTABLE) message(STATUS "npm found: ${NPM_EXECUTABLE}") message(STATUS "Web UI will be built and bundled") # Set the output directory for the web UI set(WEBUI_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/webui) set(WEBUI_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/webui) message(STATUS "Git commit hash for UI versioning: ${PROJECT_VERSION_FULL}") # Get build timestamp string(TIMESTAMP BUILD_TIMESTAMP "%Y-%m-%dT%H:%M:%SZ" UTC) # Create custom target for building the web UI add_custom_target(webui-build COMMAND ${CMAKE_COMMAND} -E echo "Building Web UI..." # Clean build/webui directory before building COMMAND ${CMAKE_COMMAND} -E remove_directory ${WEBUI_OUTPUT_DIR} COMMAND ${CMAKE_COMMAND} -E make_directory ${WEBUI_OUTPUT_DIR} # Generate version file COMMAND ${CMAKE_COMMAND} -E echo "{\"version\":\"${PROJECT_VERSION_FULL}\",\"commit\":\"${PROJECT_VERSION_COMMIT}\",\"branch\":\"${PROJECT_VERSION_BRANCH}\",\"buildTime\":\"${BUILD_TIMESTAMP}\",\"type\":\"${PROJECT_VERSION_TYPE}\",\"clean\":${PROJECT_VERSION_CLEAN}}" > ${WEBUI_SOURCE_DIR}/public/version.json COMMAND ${NPM_EXECUTABLE} install COMMAND ${NPM_EXECUTABLE} run build-static WORKING_DIRECTORY ${WEBUI_SOURCE_DIR} COMMENT "Building Web UI with npm (version: ${PROJECT_VERSION_FULL})" VERBATIM ) # Set a variable that can be used by the server set(WEBUI_BUILT ON) set(WEBUI_PATH ${WEBUI_OUTPUT_DIR} CACHE PATH "Path to built web UI files") message(STATUS "Web UI output directory: ${WEBUI_OUTPUT_DIR}") else() message(WARNING "npm not found. Web UI will not be built. Install Node.js to enable Web UI building.") set(BUILD_WEBUI OFF) endif() else() message(STATUS "Web UI building is disabled") endif() # Add subdirectories add_subdirectory(src) # Create an interface target for stable-diffusion.cpp add_library(sd-cpp INTERFACE) add_dependencies(sd-cpp stable-diffusion.cpp) target_include_directories(sd-cpp INTERFACE ${SD_CPP_INCLUDE_DIRS}) target_link_directories(sd-cpp INTERFACE ${SD_CPP_LIB_DIR}) # Set up libraries list based on CUDA support set(SD_LIBS stable-diffusion ggml ggml-base ggml-cpu ) if(SD_CUDA_SUPPORT) list(APPEND SD_LIBS ggml-cuda) list(APPEND SD_LIBS CUDA::cudart CUDA::cublas CUDA::cuda_driver) endif() target_link_libraries(sd-cpp INTERFACE ${SD_LIBS}) # Print configuration summary message(STATUS "Configuration Summary:") message(STATUS " Build Type: ${CMAKE_BUILD_TYPE}") message(STATUS " C++ Standard: ${CMAKE_CXX_STANDARD}") message(STATUS " CUDA Support: ${SD_CUDA_SUPPORT}") message(STATUS " Build Web UI: ${BUILD_WEBUI}") message(STATUS " PAM Authentication: ${ENABLE_PAM_AUTH}") if(BUILD_WEBUI AND WEBUI_BUILT) message(STATUS " Web UI Path: ${WEBUI_PATH}") endif()