Skip to content
Snippets Groups Projects
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
CMakeLists.txt 15.47 KiB
#
# This file is a part of the CaosDB Project.
#
# Copyright (C) 2021 Timm Fitschen <t.fitschen@indiscale.com>
# Copyright (C) 2021 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(libcaosdb_VERSION 0.0.13)
set(libcaosdb_COMPATIBLE_SERVER_VERSION_MAJOR 0)
set(libcaosdb_COMPATIBLE_SERVER_VERSION_MINOR 5)
set(libcaosdb_COMPATIBLE_SERVER_VERSION_PATCH 0)
set(libcaosdb_COMPATIBLE_SERVER_VERSION_PRE_RELEASE "GRPC${libcaosdb_VERSION}")

project(libcaosdb
    VERSION ${libcaosdb_VERSION}
    DESCRIPTION "C and C++ client libraries for CaosDB"
    LANGUAGES CXX C)

set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

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)
ENDIF()

###########################################
### DEPENDENCY MANAGEMENT with CONAN
###########################################
message(STATUS "Build directory ${CMAKE_BINARY_DIR}")
include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake)
conan_basic_setup()

# fix grpc - remove unsecure (no-op ssl implementations)
string(REGEX REPLACE "grpc\\+?\\+?_unsecure" "" CONAN_LIBS_GRPC
    "${CONAN_LIBS_GRPC}")
string(REGEX REPLACE "grpc\\+?\\+?_unsecure" "" CONAN_PKG_LIBS_GRPC
    "${CONAN_PKG_LIBS_GRPC}")
string(REGEX REPLACE "grpc\\+?\\+?_unsecure" "" CONAN_LIBS
    "${CONAN_LIBS}")
string(REGEX REPLACE "grpc\\+?\\+?_unsecure" "" CONAN_PKG_LIBS
    "${CONAN_PKG_LIBS}")

###########################################
### 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)
####################################################################

# Protobuf/Grpc source files
set(PROTO_FILES
    ${PROJECT_SOURCE_DIR}/proto/proto/caosdb/info/v1alpha1/main.proto
    ${PROJECT_SOURCE_DIR}/proto/proto/caosdb/entity/v1alpha1/main.proto
)

set(PROTO_PATH ${PROJECT_SOURCE_DIR}/proto/proto)

# compiler binaries
IF (WIN32)
    set(_PROTOBUF_PROTOC "${CMAKE_BINARY_DIR}/build_tools/protoc.exe")
    set(_GRPC_CPP_PLUGIN_EXECUTABLE "${CMAKE_BINARY_DIR}/build_tools/grpc_cpp_plugin.exe")
ELSE()
    set(_PROTOBUF_PROTOC "${CMAKE_BINARY_DIR}/build_tools/protoc")
    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})

###############################################################################
### Set up main targets
### * [caosdb_grpc] - only in Debug builds. Otherwise this library is compiled
###   into caosdb libraray
### * caosdb (links to caosdb_grpc) - The main library.
### * cxxcaosdbcli - A C++ test client.
### * ccaosdb - A C-Wrapper of the C++ caosdb library.
### * ccaosdbcli - A plain C test client.
###############################################################################

if("${CMAKE_BUILD_TYPE}" MATCHES "Debug")
  add_library(caosdb_grpc SHARED ${GRPC_GENERATED})
  add_library(caosdb SHARED ${libcaosdb_INCL} ${libcaosdb_SRC})
    target_link_libraries(caosdb caosdb_grpc)
    set(LIBCAOSDB caosdb caosdb_grpc)

    target_include_directories(caosdb_grpc PUBLIC
        $<BUILD_INTERFACE:${libcaosdb_SOURCE_DIR}/include>
        $<BUILD_INTERFACE:${libcaosdb_BINARY_DIR}/include>

        $<INSTALL_INTERFACE:include>
        ${CONAN_INCLUDE_DIRS}
    )
else()
    add_library(caosdb
        SHARED ${libcaosdb_INCL} ${libcaosdb_SRC} ${GRPC_GENERATED})
    set(LIBCAOSDB caosdb)
endif()
target_link_libraries(caosdb
    ${CONAN_LIBS}
)
target_include_directories(caosdb PUBLIC
    $<BUILD_INTERFACE:${libcaosdb_SOURCE_DIR}/include>
    $<BUILD_INTERFACE:${libcaosdb_BINARY_DIR}/include>
    $<INSTALL_INTERFACE:include>
    ${CONAN_INCLUDE_DIRS}
)

add_library(ccaosdb SHARED src/ccaosdb.cpp)
target_link_libraries(ccaosdb
    ${LIBCAOSDB}
    ${CONAN_LIBS}
)

add_executable(ccaosdbcli EXCLUDE_FROM_ALL src/ccaosdbcli.c)
target_include_directories(ccaosdbcli PUBLIC
    $<BUILD_INTERFACE:${libcaosdb_SOURCE_DIR}/include>
    $<BUILD_INTERFACE:${libcaosdb_BINARY_DIR}/include>
    $<INSTALL_INTERFACE:include>
    ${CONAN_INCLUDE_DIRS}
)
target_link_libraries(ccaosdbcli
    ccaosdb
    ${CONAN_LIBS}
)

add_executable(cxxcaosdbcli EXCLUDE_FROM_ALL src/cxxcaosdbcli.cpp)
target_include_directories(cxxcaosdbcli PUBLIC
    $<BUILD_INTERFACE:${libcaosdb_SOURCE_DIR}/include>
    $<BUILD_INTERFACE:${libcaosdb_BINARY_DIR}/include>
    $<INSTALL_INTERFACE:include>
    ${CONAN_INCLUDE_DIRS}
)
target_link_libraries(cxxcaosdbcli
    ${LIBCAOSDB}
    ${CONAN_LIBS}
)



#######################################################
### LINTING with CLANG-TIDY and INCLUDE-WHAT-YOU-USE
#######################################################
###########################################
### PARANOID COMPILER SETTINGS
###########################################
option(PARANOID_COMPILER_SETTINGS "Enable extra-paranoid compiler settings
(which may even flag errors for code in the dependencies. These only apply in
Debug BUILD_TYPE with SKIP_LINTING=Off or when LINTING=On." OFF)
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_CAOSDB_COMPILE_FLAGS "${TARGET_CAOSDB_COMPILE_FLAGS} ${PEDANTIC_CMAKE_CXX_FLAGS}")
    set(TARGET_CCAOSDB_COMPILE_FLAGS "${TARGET_CCAOSDB_COMPILE_FLAGS} ${PEDANTIC_CMAKE_C_FLAGS}")
    set(TARGET_CXXCAOSDBCLI_COMPILE_FLAGS "${TARGET_CXXCAOSDBCLI_COMPILE_FLAGS} ${PEDANTIC_CMAKE_CXX_FLAGS}")
    set(TARGET_CCAOSDBCLI_COMPILE_FLAGS "${TARGET_CCAOSDBCLI_COMPILE_FLAGS} ${PEDANTIC_CMAKE_C_FLAGS}")

    set_target_properties(caosdb PROPERTIES
        COMPILE_FLAGS "${TARGET_CAOSDB_COMPILE_FLAGS}")
    set_target_properties(ccaosdb PROPERTIES
        COMPILE_FLAGS "${TARGET_CCAOSDB_COMPILE_FLAGS}")
    set_target_properties(cxxcaosdbcli PROPERTIES
        COMPILE_FLAGS "${TARGET_CXXCAOSDBCLI_COMPILE_FLAGS}")
    set_target_properties(ccaosdbcli PROPERTIES
        COMPILE_FLAGS "${TARGET_CCAOSDBCLI_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(caosdb PROPERTIES
            CXX_INCLUDE_WHAT_YOU_USE "${_CMAKE_CXX_INCLUDE_WHAT_YOU_USE}"
            )
        set_target_properties(cxxcaosdbcli PROPERTIES
            CXX_INCLUDE_WHAT_YOU_USE "${_CMAKE_CXX_INCLUDE_WHAT_YOU_USE}"
            )
        set_target_properties(ccaosdbcli PROPERTIES
            C_INCLUDE_WHAT_YOU_USE "${_CMAKE_CXX_INCLUDE_WHAT_YOU_USE}"
            )
    endif()

    find_program(clang_tidy NAMES clang-tidy clang-tidy-11)
    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")
        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(caosdb PROPERTIES
            CXX_CLANG_TIDY "${_CMAKE_CXX_CLANG_TIDY};${_CMAKE_CXX_CLANG_TIDY_CHECKS}"
            )
        set_target_properties(cxxcaosdbcli PROPERTIES
            CXX_CLANG_TIDY "${_CMAKE_CXX_CLANG_TIDY};${_CMAKE_CXX_CLANG_TIDY_CHECKS}"
            )
        set_target_properties(ccaosdb PROPERTIES
            C_CLANG_TIDY "${_CMAKE_C_CLANG_TIDY};${_CMAKE_C_CLANG_TIDY_CHECKS}"
            )
        set_target_properties(ccaosdbcli 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(libcaosdb_INCLUDE_DEST "include/caosdb")
set(libcaosdb_LIB_DEST "lib")

set(CMAKE_INSTALL_PREFIX "$ENV{HOME}/.local/")
install(
    # targets to install
    TARGETS ${LIBCAOSDB} ccaosdb
    # name of the CMake "export group" containing the targets we want to install
    EXPORT caosdbTargets
    # Dynamic, static library and include destination locations after running
    # "make install"
    LIBRARY DESTINATION ${libcaosdb_LIB_DEST}
    ARCHIVE DESTINATION ${libcaosdb_LIB_DEST}
    INCLUDES DESTINATION ${libcaosdb_INCLUDE_DEST}
)


set(libcaosdb_CMAKE_DEST "${libcaosdb_LIB_DEST}/cmake/caosdb")
install(
    # The export we want to save (matches name defined above containing the
    # install targets)
    EXPORT caosdbTargets
    # CMake file in which to store the export's information
    FILE  caosdbTargets.cmake
    # Namespace prepends all targets in the export (when we import later, we
    # will use caosdb::caosdb)
    NAMESPACE caosdb::
    # where to place the resulting file (here, we're putting it with the library)
    DESTINATION ${libcaosdb_CMAKE_DEST}
)

install(FILES ${libcaosdb_INCL} ${PROJECT_SOURCE_DIR}/include/ccaosdb.h DESTINATION ${libcaosdb_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
        ${libcaosdb_INCLUDE_DEST}/${next_proto_module})
endforeach()

install(FILES ${PROJECT_SOURCE_DIR}/caosdbConfig.cmake
    DESTINATION ${libcaosdb_CMAKE_DEST})

#set_property(TARGET caosdb PROPERTY VERSION ${libcaosdb_VERSION})
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
    "${PROJECT_SOURCE_DIR}/caosdbConfigVersion.cmake"
  VERSION ${libcaosdb_VERSION}
  COMPATIBILITY AnyNewerVersion
)
install(FILES ${PROJECT_SOURCE_DIR}/caosdbConfigVersion.cmake
    DESTINATION ${libcaosdb_CMAKE_DEST})

#######################################################
### code formatting with clang-format
#######################################################
option(AUTOFORMATTING "call clang-format at configure time" ON)
if(AUTOFORMATTING AND NOT SKIP_LINTING)
    file(GLOB format_test_sources test/*.cpp test/*.h test/*.h.in)
    execute_process(COMMAND clang-format -i --verbose ${libcaosdb_INCL}
        ${libcaosdb_SRC} ${libcaosdb_TEST_SRC}
        ${PROJECT_SOURCE_DIR}/src/cxxcaosdbcli.cpp
        ${PROJECT_SOURCE_DIR}/src/ccaosdbcli.c
        ${PROJECT_SOURCE_DIR}/src/ccaosdb.cpp
        ${PROJECT_SOURCE_DIR}/include/ccaosdb.h
        ${format_test_sources}
        WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
endif()