# # 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) project(OctaveCaosDB DESCRIPTION "GNU/Octave wrapper for libcaosdb, the C++ client library of the CaosDB project." LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # dependency management with conan 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}") ####################################################### ### code formatting with clang-format ####################################################### option(AUTOFORMATTING "call clang-format at configure time" ON) if(AUTOFORMATTING) find_program(clang_format NAMES clang-format-11 clang-format) file(GLOB_RECURSE format_sources src/*.cpp) execute_process(COMMAND ${clang_format} -i --verbose ${format_sources} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) endif() ####################################################### ### Build utility library "maoxdb" ####################################################### # The library will be called maoxdb until we find a better name. The name is not very important # though, since the library is used only internally. # OCTINCLUDEDIR execute_process(COMMAND mkoctfile -p OCTINCLUDEDIR OUTPUT_VARIABLE OCTINCLUDEDIR ) string(REGEX REPLACE "\n" "" OCTINCLUDEDIR "${OCTINCLUDEDIR}") # OCTLIBDIR execute_process(COMMAND mkoctfile -p OCTLIBDIR OUTPUT_VARIABLE OCTLIBDIR ) string(REGEX REPLACE "\n" "" OCTLIBDIR "${OCTLIBDIR}") # OCTLIBS execute_process(COMMAND mkoctfile -p OCTAVE_LIBS OUTPUT_VARIABLE OCTLIBS ) string(REGEX REPLACE "\n" "" OCTLIBS "${OCTLIBS}") string(REGEX REPLACE " " ";" OCTLIBS "${OCTLIBS}") set(MAOXDB_DIR "${PROJECT_SOURCE_DIR}/src/lib") add_library(maoxdb STATIC "${MAOXDB_DIR}/maoxdb.cpp") set_target_properties(maoxdb PROPERTIES PUBLIC_HEADER "${MAOXDB_DIR}/maoxdb.hpp") target_compile_options(maoxdb PRIVATE "-I${OCTINCLUDEDIR}" "-fPIC") get_property(_MAOX_LIB_DIR TARGET maoxdb PROPERTY LIBRARY_OUTPUT_DIRECTORY) # message("_MAOX_LIB_DIR: ${_MAOX_LIB_DIR}") ####################################################### ### Compile into *.mex files ####################################################### # Only files in src/private will be compiled. This is to separate the non-mex files in src/lib; if # this is to change, the GLOB_RECURSE code needs to be changed. # Absolute paths to the cpp files. file(GLOB_RECURSE OCTAVE_CAOSDB_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/private/*.cpp) message("OCTAVE_CAOSDB_SRC: ${OCTAVE_CAOSDB_SRC}") set(PKG_INST_DIR "${PROJECT_SOURCE_DIR}/inst") file(MAKE_DIRECTORY ${PKG_INST_DIR}) # Options for mex compilation string(REGEX REPLACE ";" ";-I" _MKOCTFILE_INCLUDES "-I${CONAN_INCLUDE_DIRS};${MAOXDB_DIR}") string(REGEX REPLACE ";" ";-L" _MKOCTFILE_LIB_DIRS "-L${CONAN_LIB_DIRS};${_MAOX_LIB_DIR}") string(REGEX REPLACE ";" ";-l" _MKOCTFILE_LIBS "-l${CONAN_LIBS};maoxdb") string(REGEX REPLACE ";" ":" _MKOCTFILE_RPATH "${CONAN_LIB_DIRS}") set(_MKOCTFILE_OPTIONS "-Wl,-rpath,${_MKOCTFILE_RPATH}" "--mex" "-std=gnu++17" "-L/usr/local/lib" ${_MKOCTFILE_INCLUDES} ${_MKOCTFILE_LIB_DIRS} ${_MKOCTFILE_LIBS}) add_custom_target(mex ALL DEPENDS maoxdb) file(GLOB_RECURSE _CPP_SOURCES RELATIVE "${PROJECT_SOURCE_DIR}/src" src/private/*.cpp) foreach(sourcefile ${_CPP_SOURCES}) string(REGEX REPLACE ".cpp$" ".mex" _mex_ext_file ${sourcefile}) string(REGEX REPLACE "/" "__" _target_name "${sourcefile}") set(_mex_ext_file "${PKG_INST_DIR}/${_mex_ext_file}") set(_mkoct_output "-o;${_mex_ext_file}") set(_abs_source "${PROJECT_SOURCE_DIR}/src/${sourcefile}") add_custom_command(OUTPUT ${_mex_ext_file} COMMAND mkoctfile ARGS ${_MKOCTFILE_OPTIONS} ${_mkoct_output} ${_abs_source} MAIN_DEPENDENCY ${_abs_source} ) add_custom_target(${_target_name} DEPENDS ${_mex_ext_file}) add_dependencies(mex ${_target_name}) endforeach(sourcefile) ####################################################### ### Linting with clang-tidy and include-what-you-use ####################################################### option(LINTING "clang-tidy and iwyu" OFF) if(LINTING) find_program(clang_tidy NAMES clang-tidy-11 clang-tidy) if(NOT clang_tidy) message(WARNING "clang-tidy: Not found") else() message(STATUS "clang-tidy: ${clang_tidy}") set(_CMAKE_CXX_CLANG_TIDY "--warnings-as-errors=*" "--fix") set(_CMAKE_CXX_CLANG_TIDY_CHECKS "--checks=*,-fuchsia-*,-llvmlibc-*,-llvm-else-after-return,-readability-else-after-return,-cppcoreguidelines-pro-type-vararg,-hicpp-vararg,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-cert-err58-cpp") add_custom_command( TARGET mex COMMAND ${clang_tidy} ARGS ${_CMAKE_CXX_CLANG_TIDY} ${_CMAKE_CXX_CLANG_TIDY_CHECKS} ${OCTAVE_CAOSDB_SRC} "--" ${_MKOCTFILE_INCLUDES} "-I/usr/include" "-I${OCTINCLUDEDIR}" "-std=c++17" DEPENDS ${OCTAVE_CAOSDB_SRC}) endif() 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 "-Xiwyu" "--no_fwd_decls" "-Xiwyu" "--cxx17ns") add_custom_command( TARGET mex COMMAND ${iwyu} ARGS ${_CMAKE_CXX_INCLUDE_WHAT_YOU_USE} "-I${OCTINCLUDEDIR}" "-std=c++17" "-I/usr/include" ${_MKOCTFILE_INCLUDES} ${OCTAVE_CAOSDB_SRC} "||" "true" DEPENDS ${OCTAVE_CAOSDB_SRC}) endif() else() message(STATUS "LINTING is OFF") endif() ############################################################################### # Tests # ############################################################################### option(TEST "Unit test with gtest" OFF) if(TEST) # cmake tests suffers from not being able to define dependencies, see # https://stackoverflow.com/questions/733475, so we disable it for now. # enable_testing() add_custom_target(test echo "[EE] \\`make test\\` does not exist, did you mean \\`make test_detailed\\`?" COMMAND exit 1) # append all the test cases here (file name without the ".cpp" suffix) set(test_cases test_utilities ) # add special cmake functions for gtest, (although they are not used yet, see above) include(GoogleTest) # `make testfiles` just builds the tests, `make test_detailed` builds and runs the tests add_custom_target(testfiles) add_custom_target(test_detailed DEPENDS testfiles) # loop over all test cases and add them to the test runner list(LENGTH test_cases len_test_cases) math(EXPR len_test_cases "${len_test_cases} - 1") foreach (i RANGE "${len_test_cases}") list(GET test_cases ${i} test_case_name) # Once cmake 3.14 is available everywhere, use the new `foreach` instead. # foreach (test_case_name "${test_cases}") message(STATUS "test_case_name: ${test_case_name}") add_executable(${test_case_name} EXCLUDE_FROM_ALL test/${test_case_name}.cpp) add_custom_target("test_${test_case_name}" "${test_case_name}" DEPENDS "${test_case_name}") add_dependencies(test_detailed "test_${test_case_name}") # set(libcaosdb_TEST_SRC # "${CMAKE_CURRENT_SOURCE_DIR}/${test_case_name}.cpp ${libcaosdb_TEST_SRC}") target_include_directories(${test_case_name} PUBLIC ${OCTINCLUDEDIR} ${MAOXDB_DIR}) target_link_libraries(${test_case_name} PUBLIC maoxdb ${CONAN_LIBS_CAOSDB} ${CONAN_LIBS_GTEST} ${CONAN_LIBS_BOOST}) target_link_directories(${test_case_name} PUBLIC ${OCTLIBDIR}) target_link_options(${test_case_name} PUBLIC ${OCTLIBS}) message(STATUS "CMAKE_CURRENT_BINARY_DIR: ${CMAKE_CURRENT_BINARY_DIR}") gtest_discover_tests(${test_case_name} WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}" TEST_LIST test_list ) message(STATUS "tests for ${test_case_name}: ${test_list}") add_dependencies(testfiles ${test_case_name}) endforeach () else() message(STATUS "TEST is OFF") endif(TEST)