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