Skip to content
Snippets Groups Projects
Select Git revision
  • 6d639beb3bd205e85d4ca2145a2bda416c6574a2
  • main default protected
  • f-add-cmake-fetchcontent
  • f-sss4grpc
  • dev
  • 108-implement-rpc-call-for-server-side-scripting
  • f-windows-conan-create
  • f-to-string
  • f-update-requirements
  • f-related-projects
  • f-role
  • f-remote-path
  • f-rel-path
  • f-consol-message
  • v0.3.0
  • v0.2.2
  • v0.2.1
  • v0.2.0
  • v0.1.2
  • v0.1.1
  • v0.1
  • v0.0.19
  • v0.0.18
  • v0.0.16
  • v0.0.15
  • v0.0.10
  • v0.0.9
  • v0.0.8
  • v0.0.7
  • v0.0.6
  • v0.0.5
  • v0.0.4
  • v0.0.3
  • v0.0.2
34 results

CMakeLists.txt

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    CMakeLists.txt 16.91 KiB
    #
    # This file is a part of the LinkAhead Project.
    #
    # Copyright (C) 2021 Timm Fitschen <t.fitschen@indiscale.com>
    # Copyright (C) 2024 Joscha Schmiedt <joscha@schmiedt.dev>
    # Copyright (C) 2021-2024 IndiScale GmbH <info@indiscale.com>
    #
    #
    # This program is free software: you can redistribute it and/or modify
    # it under the terms of the GNU Affero General Public License as
    # published by the Free Software Foundation, either version 3 of the
    # License, or (at your option) any later version.
    #
    # This program is distributed in the hope that it will be useful,
    # but WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    # GNU Affero General Public License for more details.
    #
    # You should have received a copy of the GNU Affero General Public License
    # along with this program. If not, see <https://www.gnu.org/licenses/>.
    #
    
    cmake_minimum_required(VERSION 3.13)
    
    set(liblinkahead_VERSION 0.3.0)
    set(liblinkahead_COMPATIBLE_SERVER_VERSION_MAJOR 0)
    set(liblinkahead_COMPATIBLE_SERVER_VERSION_MINOR 9)
    set(liblinkahead_COMPATIBLE_SERVER_VERSION_PATCH 0)
    set(liblinkahead_COMPATIBLE_SERVER_VERSION_PRE_RELEASE "")
    
    project(liblinkahead
        VERSION ${liblinkahead_VERSION}
        DESCRIPTION "C and C++ client libraries for LinkAhead"
        LANGUAGES CXX C)
    
    set(CMAKE_C_STANDARD 11)
    set(CMAKE_CXX_STANDARD 17)
    set(CMAKE_POSITION_INDEPENDENT_CODE ON)
    set(CMAKE_C_EXTENSIONS OFF)
    set(CMAKE_C_STANDARD_REQUIRED ON)
    set(CMAKE_CXX_EXTENSIONS OFF)
    set(CMAKE_CXX_STANDARD_REQUIRED ON)
    set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
    
    set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
    
    IF (WIN32)
        set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
        add_compile_definitions(_CRT_SECURE_NO_WARNINGS) # suppress warnings for fopen, strcpy, etc.
    endif()
    
    
    IF (BUILD_ACM)
        message(STATUS "BUILD_ACM")
        add_compile_definitions("BUILD_ACM")
    ENDIF()
    
    message(STATUS "Build directory ${CMAKE_BINARY_DIR}")
    
    ###########################################
    ### GENERAL SETUP of SOURCES
    ###########################################
    set(PROJECT_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/include")
    add_subdirectory(src)
    add_subdirectory(include)
    add_subdirectory(doc)
    
    ####################################################################
    ### CODE GENERATION (WITH GRPC)
    ####################################################################
    
    find_package(protobuf CONFIG REQUIRED)
    
    # Protobuf/Grpc source files
    set(PROTO_FILES
        ${PROJECT_SOURCE_DIR}/proto/proto/caosdb/info/v1/main.proto
        ${PROJECT_SOURCE_DIR}/proto/proto/caosdb/entity/v1/main.proto
    )
    
    IF (BUILD_ACM)
        list(APPEND PROTO_FILES
             ${PROJECT_SOURCE_DIR}/proto/proto/caosdb/acm/v1alpha1/main.proto
             )
    ENDIF()
    
    set(PROTO_PATH ${PROJECT_SOURCE_DIR}/proto/proto)
    
    set(_PROTOBUF_PROTOC ${Protobuf_PROTOC_EXECUTABLE})
    # compiler binaries
    IF (WIN32)
        set(_GRPC_CPP_PLUGIN_EXECUTABLE "${CMAKE_BINARY_DIR}/build_tools/grpc_cpp_plugin.exe")
    ELSE()
        set(_GRPC_CPP_PLUGIN_EXECUTABLE "${CMAKE_BINARY_DIR}/build_tools/grpc_cpp_plugin")
    ENDIF()
    
    # Generated sources
    list(LENGTH PROTO_FILES len_proto_files)
    math(EXPR len_proto_files "${len_proto_files} - 1")
    foreach(i RANGE "${len_proto_files}")
        list(GET PROTO_FILES ${i} next_proto_file)
    
        # strip away the prefix path and the ".proto" suffix
        string(REPLACE
            "${PROJECT_SOURCE_DIR}/proto/proto/caosdb/"
            ""
            next_proto_module
            "${next_proto_file}")
        string(REPLACE
            ".proto"
            ""
            next_proto_module
            "${next_proto_module}")
        set(next_proto_src
            "${CMAKE_CURRENT_BINARY_DIR}/include/caosdb/${next_proto_module}.pb.cc")
        set(next_proto_hdr
            "${CMAKE_CURRENT_BINARY_DIR}/include/caosdb/${next_proto_module}.pb.h")
        set(next_grpc_src
            "${CMAKE_CURRENT_BINARY_DIR}/include/caosdb/${next_proto_module}.grpc.pb.cc")
        set(next_grpc_hdr
            "${CMAKE_CURRENT_BINARY_DIR}/include/caosdb/${next_proto_module}.grpc.pb.h")
        list(APPEND GRPC_GENERATED_HEADERS "${next_proto_hdr}" "${next_grpc_hdr}")
        list(APPEND GRPC_GENERATED_SOURCES "${next_proto_src}" "${next_grpc_src}")
    endforeach()
    
    set(GRPC_GENERATED
        ${GRPC_GENERATED_SOURCES}
        ${GRPC_GENERATED_HEADERS})
    add_custom_command(
          OUTPUT ${GRPC_GENERATED}
          COMMAND ${_PROTOBUF_PROTOC}
          ARGS --grpc_out "${CMAKE_CURRENT_BINARY_DIR}/include"
            --cpp_out "${CMAKE_CURRENT_BINARY_DIR}/include"
            -I "${PROTO_PATH}"
            --plugin=protoc-gen-grpc="${_GRPC_CPP_PLUGIN_EXECUTABLE}"
            ${PROTO_FILES}
          DEPENDS ${PROTO_FILES})
    
    # add generated files to include path
    include_directories(${CMAKE_CURRENT_BINARY_DIR}/include)
    
    ###############################################################################
    ### Set up main targets
    ### * linkahead - The main library including the protobuf and grpc generated files.
    ### * cxxlinkaheadcli - A C++ test client.
    ### * clinkahead - A C-Wrapper of the C++ linkahead library.
    ### * clinkaheadcli - A plain C test client.
    ###############################################################################
    
    find_package(gRPC CONFIG REQUIRED)
    
    # boost
    find_package(Boost REQUIRED COMPONENTS json filesystem log thread system log_setup)
    # find_package(Boost REQUIRED COMPONENTS filesystem )
    # find_package(Boost REQUIRED COMPONENTS log )
    # find_package(Boost REQUIRED COMPONENTS thread )
    # find_package(Boost REQUIRED COMPONENTS system )
    
    # Boost settings
    set(Boost_USE_STATIC_LIBS        ON)  # only find static libs
    set(Boost_USE_DEBUG_LIBS        OFF)  # ignore debug libs and
    set(Boost_USE_RELEASE_LIBS       ON)  # only find release libs
    set(Boost_USE_MULTITHREADED      ON)
    set(Boost_USE_STATIC_RUNTIME     ON)  # link Boost Static libraries
    
    
    find_package(GTest REQUIRED)
    
    # print include directories for debugging
    message(DEBUG "CMAKE_INCLUDE_PATH: ${CMAKE_INCLUDE_PATH}")
    message(DEBUG "PROTOBUF_INCLUDE_DIRS: ${PROTOBUF_INCLUDE_DIRS}")
    message(DEBUG "gRPC_INCLUDE_DIRS: ${gRPC_INCLUDE_DIRS}")
    message(DEBUG "Boost_INCLUDE_DIRS: ${Boost_INCLUDE_DIRS}")
    message(DEBUG "GTest_INCLUDE_DIRS: ${GTest_INCLUDE_DIRS}")
    message(DEBUG "CMAKE_CXX_FLAGS: ${CMAKE_CXX_FLAGS}")
    message(DEBUG "liblinkahead_SOURCE_DIR: ${liblinkahead_SOURCE_DIR}")
    message(DEBUG "liblinkahead_BINARY_DIR: ${liblinkahead_BINARY_DIR}")
    
    # libcaosdb_grpc
    # --------------
    add_library(caosdb_grpc STATIC ${GRPC_GENERATED})
    target_link_libraries(caosdb_grpc 
    	gRPC::grpc gRPC::grpc++ protobuf::libprotobuf
    )
    
    # liblinkahead
    # ---------
    add_library(linkahead SHARED
         ${liblinkahead_INCL} ${liblinkahead_SRC})
    target_link_libraries(linkahead PUBLIC
        caosdb_grpc gRPC::grpc gRPC::grpc++ protobuf::libprotobuf ${Boost_LIBRARIES}
    )
    set(liblinkahead linkahead)
    
    target_include_directories(linkahead PUBLIC
        $<BUILD_INTERFACE:${liblinkahead_SOURCE_DIR}/include>
        $<BUILD_INTERFACE:${liblinkahead_BINARY_DIR}/include>
        $<BUILD_INTERFACE:${liblinkahead_SOURCE_DIR}/src>
        $<INSTALL_INTERFACE:include>
    )
    
    # libclinkahead
    # ----------
    add_library(clinkahead SHARED src/clinkahead.cpp)
    target_link_libraries(clinkahead PUBLIC
        linkahead caosdb_grpc gRPC::grpc gRPC::grpc++ protobuf::libprotobuf ${Boost_LIBRARIES}
    )
    target_include_directories(clinkahead PUBLIC
        $<BUILD_INTERFACE:${liblinkahead_SOURCE_DIR}/include>
        $<BUILD_INTERFACE:${liblinkahead_BINARY_DIR}/include>
        $<INSTALL_INTERFACE:include>
    )
    
    
    # clinkaheadcli
    # ----------
    add_executable(clinkaheadcli EXCLUDE_FROM_ALL src/clinkaheadcli.c)
    target_include_directories(clinkaheadcli PUBLIC
        $<BUILD_INTERFACE:${liblinkahead_SOURCE_DIR}/include>
        $<BUILD_INTERFACE:${liblinkahead_BINARY_DIR}/include>
        $<INSTALL_INTERFACE:include>
    )
    target_link_libraries(clinkaheadcli PRIVATE
        caosdb_grpc clinkahead
        gRPC::grpc protobuf::libprotobuf ${Boost_LIBRARIES}    
    )
    
    # cxxlinkaheadcli
    # ------------
    add_executable(cxxlinkaheadcli EXCLUDE_FROM_ALL src/cxxlinkaheadcli.cpp)
    target_include_directories(cxxlinkaheadcli PUBLIC
        $<BUILD_INTERFACE:${liblinkahead_SOURCE_DIR}/include>
        $<BUILD_INTERFACE:${liblinkahead_BINARY_DIR}/include>
        $<INSTALL_INTERFACE:include>
    )
    target_link_libraries(cxxlinkaheadcli PRIVATE
        linkahead caosdb_grpc  gRPC::grpc++ protobuf::libprotobuf ${Boost_LIBRARIES}
    )
    
    
    
    #######################################################
    ### LINTING with CLANG-TIDY and INCLUDE-WHAT-YOU-USE
    #######################################################
    
    include(CheckCXXCompilerFlag)
    include(CheckCCompilerFlag)
    
    function(add_compiler_flag flag)
        string(FIND "${CMAKE_CXX_FLAGS}" "${flag}" cxx_present)
        if(cxx_present EQUAL -1)
            check_cxx_compiler_flag("${flag}" flag_supported)
            if(flag_supported)
                set(PEDANTIC_CMAKE_CXX_FLAGS "${PEDANTIC_CMAKE_CXX_FLAGS} ${flag}" PARENT_SCOPE)
            endif()
            unset(flag_supported CACHE)
        endif()
        unset(cxx_present CACHE)
    
        string(FIND "${CMAKE_C_FLAGS}" "${flag}" c_present)
        if(c_present EQUAL -1)
            check_cxx_compiler_flag("${flag}" flag_supported)
            if(flag_supported)
                set(PEDANTIC_CMAKE_C_FLAGS "${PEDANTIC_CMAKE_C_FLAGS} ${flag}" PARENT_SCOPE)
            endif()
            unset(flag_supported CACHE)
        endif()
        unset(c_present CACHE)
    endfunction()
    
    
    
    option(LINTING "Enable linting with clang-tidy and iwyu when in non-Debug build-type" OFF)
    if("${CMAKE_BUILD_TYPE}" MATCHES "Debug" OR LINTING)
        set(_LINTING ON)
    endif()
    option(SKIP_LINTING "Skip linting even when in Debug build-type" OFF)
    if("${CMAKE_BUILD_TYPE}" MATCHES "Debug" AND SKIP_LINTING)
        message(WARNING "Skipping linting due to SKIP_LINTING option")
        set(_LINTING OFF)
    endif()
    if(_LINTING)
    
        ### set paranoid compiler flags
        add_compiler_flag("-Wall")
        add_compiler_flag("-Wextra")
        add_compiler_flag("-pedantic")
        add_compiler_flag("-Werror")
    
        message(STATUS "PEDANTIC_CMAKE_CXX_FLAGS: [${PEDANTIC_CMAKE_CXX_FLAGS}]")
        set(TARGET_LINKAHEAD_COMPILE_FLAGS "${TARGET_LINKAHEAD_COMPILE_FLAGS} ${PEDANTIC_CMAKE_CXX_FLAGS}")
        set(TARGET_CLINKAHEAD_COMPILE_FLAGS "${TARGET_CLINKAHEAD_COMPILE_FLAGS} ${PEDANTIC_CMAKE_C_FLAGS}")
        set(TARGET_CXXLINKAHEADCLI_COMPILE_FLAGS "${TARGET_CXXLINKAHEADCLI_COMPILE_FLAGS} ${PEDANTIC_CMAKE_CXX_FLAGS}")
        set(TARGET_CLINKAHEADCLI_COMPILE_FLAGS "${TARGET_CLINKAHEADCLI_COMPILE_FLAGS} ${PEDANTIC_CMAKE_C_FLAGS}")
    
        set_target_properties(linkahead PROPERTIES
            COMPILE_FLAGS "${TARGET_LINKAHEAD_COMPILE_FLAGS}")
        set_target_properties(clinkahead PROPERTIES
            COMPILE_FLAGS "${TARGET_CLINKAHEAD_COMPILE_FLAGS}")
        set_target_properties(cxxlinkaheadcli PROPERTIES
            COMPILE_FLAGS "${TARGET_CXXLINKAHEADCLI_COMPILE_FLAGS}")
        set_target_properties(clinkaheadcli PROPERTIES
            COMPILE_FLAGS "${TARGET_CLINKAHEADCLI_COMPILE_FLAGS}")
    
        find_program(iwyu
            NAMES include-what-you-use iwyu
            PATHS ${CMAKE_SOURCE_DIR}/tools/include-what-you-use/${iwyu_os}/bin)
        if(NOT iwyu)
            message(WARNING "include-what-you-use: Not found")
        else()
            message(STATUS "include-what-you-use: ${iwyu}")
            set(_CMAKE_CXX_INCLUDE_WHAT_YOU_USE ${iwyu}
                "-Xiwyu" "--cxx17ns" "-Xiwyu" "--no_fwd_decls")
    
            set_target_properties(linkahead PROPERTIES
                CXX_INCLUDE_WHAT_YOU_USE "${_CMAKE_CXX_INCLUDE_WHAT_YOU_USE}"
                )
            set_target_properties(cxxlinkaheadcli PROPERTIES
                CXX_INCLUDE_WHAT_YOU_USE "${_CMAKE_CXX_INCLUDE_WHAT_YOU_USE}"
                )
            set_target_properties(clinkaheadcli PROPERTIES
                C_INCLUDE_WHAT_YOU_USE "${_CMAKE_CXX_INCLUDE_WHAT_YOU_USE}"
                )
        endif()
    
        find_program(clang_tidy NAMES clang-tidy clang-tidy-16)
        if(NOT clang_tidy)
            message(WARNING "clang-tidy: Not found")
        else()
            message(STATUS "clang-tidy: ${clang_tidy}")
            set(_CMAKE_CXX_CLANG_TIDY_CHECKS
                "--checks=*,-fuchsia-*,-llvmlibc-*,-readability-convert-member-functions-to-static,-cppcoreguidelines-pro-bounds-array-to-pointer-decay,-hicpp-no-array-decay,-llvm-else-after-return,-readability-else-after-return,-modernize-use-trailing-return-type,-bugprone-branch-clone,-altera-*,-misc-include-cleaner,-readability-identifier-*,-llvm-include-order,-misc-const-correctness")
            set(_CMAKE_C_CLANG_TIDY_CHECKS "${_CMAKE_CXX_CLANG_TIDY_CHECKS}")
            set(_CMAKE_CXX_CLANG_TIDY "${clang_tidy}"
                "--header-filter=caosdb/.*[^\(\.pb\.h\)]$")
                # "--warnings-as-errors=*")
            set(_CMAKE_C_CLANG_TIDY "${_CMAKE_CXX_CLANG_TIDY}")
            option(AUTO_FIX_LINTING "Append --fix option to clang-tidy" OFF)
            if(AUTO_FIX_LINTING)
                set(_CMAKE_CXX_CLANG_TIDY "${_CMAKE_CXX_CLANG_TIDY};--fix")
            endif()
            message(STATUS "Using clang-tidy with
                '${_CMAKE_CXX_CLANG_TIDY};${_CMAKE_CXX_CLANG_TIDY_CHECKS}'")
            set_target_properties(linkahead PROPERTIES
                CXX_CLANG_TIDY "${_CMAKE_CXX_CLANG_TIDY};${_CMAKE_CXX_CLANG_TIDY_CHECKS}"
                )
            set_target_properties(cxxlinkaheadcli PROPERTIES
                CXX_CLANG_TIDY "${_CMAKE_CXX_CLANG_TIDY};${_CMAKE_CXX_CLANG_TIDY_CHECKS}"
                )
            set_target_properties(clinkahead PROPERTIES
                C_CLANG_TIDY "${_CMAKE_C_CLANG_TIDY};${_CMAKE_C_CLANG_TIDY_CHECKS}"
                )
            set_target_properties(clinkaheadcli PROPERTIES
                C_CLANG_TIDY "${_CMAKE_C_CLANG_TIDY};${_CMAKE_C_CLANG_TIDY_CHECKS}"
                )
        endif()
    endif()
    
    
    #######################################################
    ### UNIT TEST
    #######################################################
    
    #if("${CMAKE_BUILD_TYPE}" MATCHES "Debug")
        enable_testing()
        add_subdirectory(test)
    #endif()
    
    # ###############################################
    # ############ INSTALLATION #####################
    # ###############################################
    
    set(liblinkahead_INCLUDE_DEST "include/linkahead")
    set(liblinkahead_LIB_DEST "lib")
    
    if (WIN32)
        set(CMAKE_INSTALL_PREFIX "$ENV{APPDATA}/LinkAhead")
    else()
        set(CMAKE_INSTALL_PREFIX "$ENV{HOME}/.local/")
    endif()
    
    install(
        # targets to install
        TARGETS linkahead clinkahead caosdb_grpc
        # name of the CMake "export group" containing the targets we want to install
        EXPORT linkaheadTargets
        # Dynamic, static library and include destination locations after running
        # "make install"
        LIBRARY DESTINATION ${liblinkahead_LIB_DEST}
        ARCHIVE DESTINATION ${liblinkahead_LIB_DEST}
        RUNTIME DESTINATION ${liblinkahead_LIB_DEST} # This line ensures DLLs are copied on Windows
        INCLUDES DESTINATION ${liblinkahead_INCLUDE_DEST}
    )
    
    
    set(liblinkahead_CMAKE_DEST "${liblinkahead_LIB_DEST}/cmake/linkahead")
    install(
        # The export we want to save (matches name defined above containing the
        # install targets)
        EXPORT linkaheadTargets
        # CMake file in which to store the export's information
        FILE  linkaheadTargets.cmake
        # Namespace prepends all targets in the export (when we import later, we
        # will use linkahead::linkahead)
        NAMESPACE linkahead::
        # where to place the resulting file (here, we're putting it with the library)
        DESTINATION ${liblinkahead_CMAKE_DEST}
    )
    
    install(FILES ${liblinkahead_INCL} ${PROJECT_SOURCE_DIR}/include/clinkahead.h DESTINATION ${liblinkahead_INCLUDE_DEST})
    foreach(i RANGE "${len_proto_files}")
        list(GET PROTO_FILES ${i} next_proto_file)
    
        # strip away the prefix path and the ".proto" suffix
        string(REPLACE
            "${PROJECT_SOURCE_DIR}/proto/proto/caosdb/"
            ""
            next_proto_module
            "${next_proto_file}")
        string(REPLACE
            "/main.proto"
            ""
            next_proto_module
            "${next_proto_module}")
        set(next_proto_hdr
            "${CMAKE_CURRENT_BINARY_DIR}/include/caosdb/${next_proto_module}/main.pb.h")
        set(next_grpc_hdr
            "${CMAKE_CURRENT_BINARY_DIR}/include/caosdb/${next_proto_module}/main.grpc.pb.h")
        install(FILES ${next_proto_hdr} ${next_grpc_hdr} DESTINATION
            ${liblinkahead_INCLUDE_DEST}/${next_proto_module})
    endforeach()
    
    install(FILES ${PROJECT_SOURCE_DIR}/linkaheadConfig.cmake
        DESTINATION ${liblinkahead_CMAKE_DEST})
    
    #set_property(TARGET caosdb PROPERTY VERSION ${liblinkahead_VERSION})
    include(CMakePackageConfigHelpers)
    write_basic_package_version_file(
        "${PROJECT_SOURCE_DIR}/linkaheadConfigVersion.cmake"
      VERSION ${liblinkahead_VERSION}
      COMPATIBILITY AnyNewerVersion
    )
    install(FILES ${PROJECT_SOURCE_DIR}/linkaheadConfigVersion.cmake
        DESTINATION ${liblinkahead_CMAKE_DEST})
    
    #######################################################
    ### code formatting with clang-format
    #######################################################
    option(AUTOFORMATTING "call clang-format at configure time" ON)
    if(AUTOFORMATTING AND NOT SKIP_LINTING)
        find_program(clang_format NAMES clang-format-16 clang-format)
        file(GLOB format_test_sources test/*.cpp test/*.h test/*.h.in)
        execute_process(COMMAND ${clang_format} -i --verbose ${liblinkahead_INCL}
            ${liblinkahead_SRC} ${liblinkahead_TEST_SRC}
            ${PROJECT_SOURCE_DIR}/src/cxxlinkaheadcli.cpp
            ${PROJECT_SOURCE_DIR}/src/clinkaheadcli.c
            ${PROJECT_SOURCE_DIR}/src/clinkahead.cpp
            ${PROJECT_SOURCE_DIR}/include/clinkahead.h
            ${format_test_sources}
            WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
    endif()