# Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT license. cmake_minimum_required(VERSION 3.16) ################################################### # Project APSI includes the following components: # # 1. APSI C++ library that includes # # 1) common API # # 2) sender API # # 3) receiver API # # 2. APSI unit tests # # 3. APSI integration tests # # 4. APSI command line interface # ################################################### # [option] CMAKE_BUILD_TYPE (default: "Release") # Build in one of the following modes: Release, Debug, MiniSizeRel, or RelWithDebInfo. # Most generators recognize these and can set the compiler flags accordingly. We set # the build type here before creating the project to prevent the CMake generator from # overriding our default of "Release". if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Build type" FORCE) set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Release" "Debug" "MinSizeRel" "RelWithDebInfo") endif() message(STATUS "Build type (CMAKE_BUILD_TYPE): ${CMAKE_BUILD_TYPE}") project(APSI VERSION 0.12.0 LANGUAGES CXX C) # This policy was introduced in CMake 3.13; OLD by default until CMake 3.21 cmake_policy(SET CMP0077 NEW) ######################## # Global configuration # ######################## # CMake modules include(CMakeDependentOption) include(CheckCXXCompilerFlag) include(CheckCXXSourceRuns) include(CheckLanguage) # Extra modules list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake) include(APSIMacros) # Always build position-independent-code set(CMAKE_POSITION_INDEPENDENT_CODE ON) # Make the install target depend on the all target (required by vcpkg) set(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY OFF) # In Debug mode, define APSI_DEBUG if(CMAKE_BUILD_TYPE STREQUAL "Debug") set(APSI_DEBUG ON) # In Debug mode, enable extra compiler flags. include(EnableCXXCompilerFlags) else() set(APSI_DEBUG OFF) endif() message(STATUS "APSI debug mode: ${APSI_DEBUG}") # [option] APSI_USE_CXX17_OPTION_STR (default: ON) # Use C++17, use C++14 otherwise. An error will be thrown if SEAL_USE_CXX17 is ON but APSI_USE_CXX17 is OFF. set(APSI_USE_CXX17_OPTION_STR "Use C++17") option(APSI_USE_CXX17 ${APSI_USE_CXX17_OPTION_STR} ON) message(STATUS "APSI_USE_CXX17: ${APSI_USE_CXX17}") # Enable security-related compile options (MSVC only) set(APSI_SECURE_COMPILE_OPTIONS_OPTION_STR "Enable Control Flow Guard and Spectre mitigations (MSVC only)") option(APSI_SECURE_COMPILE_OPTIONS ${APSI_SECURE_COMPILE_OPTIONS_OPTION_STR} OFF) mark_as_advanced(APSI_SECURE_COMPILE_OPTIONS) # Enable AVX implementation set(APSI_USE_AVX_OPTION_STR "Use AVX extensions if available") option(APSI_USE_AVX ${APSI_USE_AVX_OPTION_STR} ON) mark_as_advanced(APSI_USE_AVX) # Enable AVX2 implementation set(APSI_USE_AVX2_OPTION_STR "Use AVX2 extensions if available") option(APSI_USE_AVX2 ${APSI_USE_AVX2_OPTION_STR} ON) mark_as_advanced(APSI_USE_AVX2) # Enable ASM implementation set(APSI_USE_ASM_OPTION_STR "Use ASM implementation (static UNIX builds only)") option(APSI_USE_ASM ${APSI_USE_ASM_OPTION_STR} ON) mark_as_advanced(APSI_USE_ASM) # Path for output set(OUTLIB_PATH "lib") # Required files and directories include(GNUInstallDirs) # Source tree # set(APSI_CONFIG_IN_FILENAME ${CMAKE_CURRENT_LIST_DIR}/cmake/APSIConfig.cmake.in) set(APSI_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}) # set(APSI_CONFIG_H_IN_FILENAME ${CMAKE_CURRENT_LIST_DIR}/common/apsi/config.h.in) # Build tree # set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${OUTLIB_PATH}) # set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${OUTLIB_PATH}) # set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/bin) # set(APSI_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}) # set(APSI_TARGETS_FILENAME ${CMAKE_CURRENT_BINARY_DIR}/cmake/APSITargets.cmake) # set(APSI_CONFIG_FILENAME ${CMAKE_CURRENT_BINARY_DIR}/cmake/APSIConfig.cmake) # set(APSI_CONFIG_VERSION_FILENAME ${CMAKE_CURRENT_BINARY_DIR}/cmake/APSIConfigVersion.cmake) # set(APSI_CONFIG_H_FILENAME ${CMAKE_CURRENT_BINARY_DIR}/common/apsi/config.h) # Install # set(APSI_CONFIG_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/APSI-${APSI_VERSION_MAJOR}.${APSI_VERSION_MINOR}) # set(APSI_INCLUDES_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR}/APSI-${APSI_VERSION_MAJOR}.${APSI_VERSION_MINOR}) set(APSI_INCLUDES_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR}/fourq) # pkg-config # TODO: not provided yet ######################### # External Dependencies # ######################### # All dependencies are assumed pre-installed. # find_package might throw a FATAL_ERROR before"xxx: not found", e.g. with vcpkg.cmake. # Microsoft SEAL # find_package(SEAL 4.1 QUIET REQUIRED) # if(NOT SEAL_FOUND) # message(FATAL_ERROR "Microsoft SEAL: not found") # else() # message(STATUS "Microsoft SEAL: found") # endif() if(NOT APSI_USE_CXX17 AND SEAL_USE_CXX17) message(FATAL_ERROR "CXX standards mismatch: APSI_USE_CXX17 is OFF, SEAL_USE_CXX17 is ON") endif() # Microsoft Kuku # find_package(Kuku 2.1 QUIET REQUIRED) # if(NOT Kuku_FOUND) # message(FATAL_ERROR "Microsoft Kuku: not found") # else() # message(STATUS "Microsoft Kuku: found") # endif() # Flatbuffers # find_package(Flatbuffers REQUIRED) # if(NOT Flatbuffers_FOUND) # message(FATAL_ERROR "Flatbuffers: not found") # else() # message(STATUS "Flatbuffers: found") # get_target_property(FLATBUFFERS_FLATC_PATH flatbuffers::flatc IMPORTED_LOCATION_RELEASE) # message(STATUS "flatc path: ${FLATBUFFERS_FLATC_PATH}") # include(CompileSchemaCXX) # endif() # jsoncpp: for parameter configuration # find_package(jsoncpp REQUIRED) # if (NOT jsoncpp_FOUND) # message(FATAL_ERROR "jsoncpp: not found") # else() # message(STATUS "jsoncpp: found") # endif() # [Option] APSI_USE_LOG4CPLUS (default: ON) # set(APSI_USE_LOG4CPLUS_OPTION_STR "Use Log4cplus for logging") # option(APSI_USE_LOG4CPLUS ${APSI_USE_LOG4CPLUS_OPTION_STR} ON) # if(APSI_USE_LOG4CPLUS) # # Log4cplus # find_package(log4cplus REQUIRED) # if(NOT log4cplus_FOUND) # message(FATAL_ERROR "log4cplus: not found") # else() # message(STATUS "log4cplus: found") # endif() # endif() # [Option] APSI_USE_ZMQ (default: ON) # set(APSI_USE_ZMQ_OPTION_STR "Use ZeroMQ for networking") # option(APSI_USE_ZMQ ${APSI_USE_ZMQ_OPTION_STR} ON) # if(APSI_USE_ZMQ) # # ZeroMQ base # find_package(ZeroMQ REQUIRED) # if(NOT ZeroMQ_FOUND) # message(FATAL_ERROR "ZeroMQ: not found") # else() # message(STATUS "ZeroMQ: found") # endif() # # cppzmq wrapper # find_package(cppzmq REQUIRED) # if(NOT cppzmq_FOUND) # message(FATAL_ERROR "cppzmq: not found") # else() # message(STATUS "cppzmq: found") # endif() # endif() # [Option] APSI_BUILD_TESTS (default: OFF) # set(APSI_BUILD_TESTS_OPTION_STR "Build unit and integration tests for APSI") # option(APSI_BUILD_TESTS ${APSI_BUILD_TESTS_OPTION_STR} OFF) # if(APSI_BUILD_TESTS) # # Google Test # find_package(GTest CONFIG REQUIRED) # if(NOT GTest_FOUND) # message(FATAL_ERROR "GTest: not found") # else() # message(STATUS "GTest: found") # endif() # endif() # [Option] APSI_BUILD_CLI (default: OFF) # set(APSI_BUILD_CLI_OPTION_STR "Build example command line interface applications") # cmake_dependent_option(APSI_BUILD_CLI ${APSI_BUILD_CLI_OPTION_STR} OFF "APSI_USE_ZMQ;APSI_USE_LOG4CPLUS" OFF) # if (APSI_BUILD_CLI) # # TCLAP # find_path(TCLAP_INCLUDE_DIRS "tclap/Arg.h") # if(TCLAP_INCLUDE_DIRS STREQUAL "TCLAP_INCLUDE_DIRS-NOTFOUND") # message(FATAL_ERROR "TCLAP: not found") # else() # message(STATUS "TCLAP: found") # message(STATUS "TCLAP_INCLUDE_DIRS: ${TCLAP_INCLUDE_DIRS}") # endif() # endif() #################### # APSI C++ library # #################### # [option] BUILD_SHARED_LIBS (default: OFF) # Build a shared library if set to ON. Build a static library regardlessly. set(BUILD_SHARED_LIBS_STR "Build shared library") option(BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_STR} OFF) # TODO: consider building shared in future if(BUILD_SHARED_LIBS) message(FATAL_ERROR "Only static build is supported; set `BUILD_SHARED_LIBS=OFF`") endif() # Create the config file # configure_file(${APSI_CONFIG_H_IN_FILENAME} ${APSI_CONFIG_H_FILENAME}) # install( # FILES ${APSI_CONFIG_H_FILENAME} # DESTINATION ${APSI_INCLUDES_INSTALL_DIR}/apsi) # Create a single library "apsi" for common, sender, and receiver add_library(apsi STATIC) # apsi_set_version_filename(apsi) # apsi_set_language(apsi) # target_include_directories(apsi PUBLIC # $ # $) # target_include_directories(apsi PUBLIC # $ # $) # target_include_directories(apsi PUBLIC # $ # $) # target_include_directories(apsi PUBLIC # $ # $) # target_include_directories(apsi PUBLIC # $ # $) # apsi_set_version(apsi) # apsi_link_threads(apsi) # apsi_install_target(apsi APSITargets) target_include_directories(apsi PUBLIC ${CMAKE_CURRENT_LIST_DIR}) # target_link_libraries(apsi # PUBLIC SEAL::seal # PUBLIC Kuku::kuku # PUBLIC flatbuffers::flatbuffers # PUBLIC jsoncpp_static) # if(APSI_USE_LOG4CPLUS) # target_link_libraries(apsi PUBLIC log4cplus::log4cplus) # endif() # if(APSI_USE_ZMQ) # target_link_libraries(apsi PUBLIC libzmq-static cppzmq-static) # endif() # Configurations for FourQlib: system, arch, SIMD, and assembler target_compile_options(apsi PUBLIC -DHAVE_CONFIG) target_compile_options(apsi PUBLIC -DUSE_SECURE_SEED) target_compile_options(apsi PUBLIC -DUSE_ENDO=true) # Set system if(MSVC) target_compile_options(apsi PUBLIC -D__WINDOWS__) elseif (UNIX) target_compile_options(apsi PUBLIC -D__LINUX__) endif() # Detect architecture include(DetectArch) if(APSI_FOURQ_ARM64) # _ARM64_ needs to be set if the ARM64 optimizations are used # (in UNIX) or the generic implementation is used (Windows) target_compile_options(apsi PUBLIC -D_ARM64_) set(_ARM64_ ON) endif() if(CMAKE_SYSTEM_PROCESSOR STREQUAL x86) target_compile_options(apsi PUBLIC -D_X86_) set(_X86_ ON) endif() if(APSI_FOURQ_AMD64) target_compile_options(apsi PUBLIC -D_AMD64_) set(_AMD64_ ON) message(STATUS "FourQlib optimization: arch=AMD64") elseif(APSI_FOURQ_ARM64 AND UNIX) message(STATUS "FourQlib optimization: arch=ARM64") else() target_compile_options(apsi PUBLIC -D_GENERIC_) set(_GENERIC_ ON) message(STATUS "FourQlib optimization: arch=GENERIC") endif() # Detect AVX instructions if(APSI_FOURQ_AMD64 AND (APSI_USE_AVX OR APSI_USE_AVX2)) include(FindAVX) check_for_avx(apsi) if(HAVE_AVX2_EXTENSIONS AND APSI_USE_AVX2) target_compile_options(apsi PUBLIC -D_AVX2_) set(_AVX2_ ON) set(APSI_USE_AVX OFF CACHE BOOL ${APSI_USE_AVX_OPTION_STR} FORCE) message(STATUS "FourQlib optimization: simd=AVX2") elseif(HAVE_AVX_EXTENSIONS AND APSI_USE_AVX) target_compile_options(apsi PUBLIC -D_AVX_) set(_AVX_ ON) set(APSI_USE_AVX2 OFF CACHE BOOL ${APSI_USE_AVX2_OPTION_STR} FORCE) message(STATUS "FourQlib optimization: simd=AVX") else() set(APSI_USE_AVX OFF CACHE BOOL ${APSI_USE_AVX_OPTION_STR} FORCE) set(APSI_USE_AVX2 OFF CACHE BOOL ${APSI_USE_AVX2_OPTION_STR} FORCE) message(STATUS "FourQlib optimization: simd=OFF") endif() else() set(APSI_USE_AVX OFF CACHE BOOL ${APSI_USE_AVX_OPTION_STR} FORCE) set(APSI_USE_AVX2 OFF CACHE BOOL ${APSI_USE_AVX2_OPTION_STR} FORCE) message(STATUS "FourQlib optimization: simd=OFF") endif() # Use optimized assembly on UNIX if(APSI_USE_ASM AND UNIX AND NOT APPLE AND NOT CYGWIN AND NOT MINGW) check_language(ASM) if(CMAKE_ASM_COMPILER) enable_language(ASM) target_compile_options(apsi PUBLIC -D_ASM_) set(_ASM_ ON) message(STATUS "FourQlib optimization: asm=ON") endif() else() set(APSI_USE_ASM OFF CACHE BOOL ${APSI_USE_ASM_OPTION_STR} FORCE) message(STATUS "FourQlib optimization: asm=OFF") endif() # Add source files to library and header files to install # Must follow configurations for FourQlib set(APSI_SOURCE_FILES "") # add_subdirectory(common/apsi) # add_subdirectory(receiver/apsi) # add_subdirectory(sender/apsi) add_subdirectory(fourq) message(STATUS ${CMAKE_CXX_COMPILER_ID}) if(MSVC) set(__WINDOWS__ ON) endif() if(UNIX) set(__LINUX__ ON) endif() if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC") set(_MSC_VER ON) endif() if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") set(__GNUC__ ON) endif() if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") set(__clang__ ON) endif() configure_file(${CMAKE_CURRENT_LIST_DIR}/fourq/FourQ_define.h.in ${CMAKE_CURRENT_LIST_DIR}/fourq/FourQ_define.h) target_sources(apsi PRIVATE ${APSI_SOURCE_FILES}) ################################# # Installation and CMake config # ################################# # Create the CMake config file # include(CMakePackageConfigHelpers) # configure_package_config_file( # ${APSI_CONFIG_IN_FILENAME} ${APSI_CONFIG_FILENAME} # INSTALL_DESTINATION ${APSI_CONFIG_INSTALL_DIR} # ) # Install the export # install( # EXPORT APSITargets # NAMESPACE APSI:: # DESTINATION ${APSI_CONFIG_INSTALL_DIR}) # Version file; we require exact version match for downstream # write_basic_package_version_file( # ${APSI_CONFIG_VERSION_FILENAME} # VERSION ${APSI_VERSION} # COMPATIBILITY SameMinorVersion) # Install config and module files # install( # FILES # ${APSI_CONFIG_FILENAME} # ${APSI_CONFIG_VERSION_FILENAME} # DESTINATION ${APSI_CONFIG_INSTALL_DIR}) # We export SEALTargets from the build tree so it can be used by other projects # without requiring an install. # export( # EXPORT APSITargets # NAMESPACE APSI:: # FILE ${APSI_TARGETS_FILENAME}) ################### # APSI unit tests # ################### # if(APSI_BUILD_TESTS) # add_executable(unit_tests) # add_subdirectory(tests/unit/src) # target_link_libraries(unit_tests apsi GTest::gtest) # endif() ########################## # APSI integration tests # ########################## # if(APSI_BUILD_TESTS) # add_executable(integration_tests) # add_subdirectory(tests/integration/src) # target_link_libraries(integration_tests apsi GTest::gtest) # endif() ########################## # Command Line Interface # ########################## # if(APSI_BUILD_CLI) # add_library(common_cli OBJECT) # add_subdirectory(cli/common) # target_include_directories(common_cli PUBLIC cli) # target_include_directories(common_cli PUBLIC ${TCLAP_INCLUDE_DIRS}) # target_link_libraries(common_cli PUBLIC apsi) # if (NOT MSVC AND NOT APPLE) # target_link_libraries(common_cli PUBLIC stdc++fs) # endif() # if(NOT APSI_USE_CXX17) # message(STATUS "Command line interface is built with C++17 regardless of APSI_USE_CXX17") # endif() # target_compile_features(common_cli PUBLIC cxx_std_17) # # Ensure PDB is generated even in Release mode # if(MSVC) # target_link_options(common_cli PUBLIC /DEBUG) # endif() # add_executable(sender_cli) # add_subdirectory(cli/sender) # target_link_libraries(sender_cli PUBLIC common_cli apsi) # if (APPLE) # target_compile_options(common_cli PUBLIC -DHAVE_LONG_LONG) # endif() # add_executable(receiver_cli) # add_subdirectory(cli/receiver) # target_link_libraries(receiver_cli PUBLIC common_cli apsi) # add_executable(pd_tool) # add_subdirectory(cli/pd_tool) # target_include_directories(pd_tool PRIVATE cli) # target_include_directories(pd_tool PRIVATE ${TCLAP_INCLUDE_DIRS}) # target_link_libraries(pd_tool apsi) # endif()