From 6755f08678ddb057befd0b217c0f6c88e6d70eef Mon Sep 17 00:00:00 2001 From: Nikolaus Demmel Date: Wed, 24 Apr 2019 14:21:24 +0200 Subject: [PATCH] ci and cmake improvements Changes along the line of https://gitlab.com/VladyslavUsenko/basalt-headers/merge_requests/1 and https://gitlab.com/VladyslavUsenko/basalt-headers/merge_requests/2, and more. Warning free builds on macos 10.11 - 10.14, Ubuntu Xenial & Bionic. (macOS 10.14 is not yet in CI, but tested locally.) Changes similar to basalt-headers: - cmake: raise minimum version to 3.10 - cmake: add workarounds to support macOS < 10.14 - cmake: set ccache only if not yet set and print info - cmake: add NDEBUG define (to disable asserts) for release build and EIGEN_INITIALIZE_MATRICES_BY_NAN for others. Add externally supplied CMAKE_CXX_FLAGS at the end to allow overriding the defaults. - tests: add enable_testing() in main CMakeLists.txt, such that we can call 'ctest' from build folder. - tests: simplify gtest / gtest_main linking - tests: use the newer gtest_discover_tests instead of add_test, which adds a separate cmake test for every gtest, even with multiple defined in a single executable. Its not only more reliable and less verbose in the CMakeLists.txt, but also allows to run 'ctest' without -V and still see status for every individual test. - ci: add build jobs for Debug/RelWithDebInfo on Bionic, as well as builds on Xenial and El Capitan. Use templates to simplify .gitlab-ci.yml - ci: clang-format job Additional changes: - cmake: unify formatting - cmake: various diagnostic warnings for situations that are unsupported (should help with gitlab issues). - cmake options to disable openmp, pass custom eigen root, compiler-launcher, additional CXX_FLAGS that can override default flags also for submodules (opengv etc), ... - cmake: moved configuration of submodule libs to `thirdparty/CMakeLists.txt`. This includes various fixes for limiatations of the thirdparty cmake definitions. In particular ensures that correct eigen is used, that opengv respects march and CXX_FLAGS passed from command line. - cmake: simplified linking of executables. Linking `basalt` is enough. - cmake: basalt sources now build with the minimal disabled warnings ("-Wall Wextra -Werror -Wno-unused-parameter -ftemplate-backtrace-limit=0", and additionally "-Wno-exceptions" for clang). Additional flags are now only set for the submodule targets in thirdparty. - tests: Running ctest in build folder now also runs the unit tests from basalt-headers. - ci: in addition to the additional compile jobs and there are now also 'test' jobs, that check that the executables in the deb's work (runs on all branches, not just master). --- .gitlab-ci.yml | 195 +++++++++++++++++++-------- CMakeLists.txt | 271 +++++++++++++++++++++++--------------- test/CMakeLists.txt | 27 ++-- thirdparty/CMakeLists.txt | 106 +++++++++++++++ 4 files changed, 425 insertions(+), 174 deletions(-) create mode 100644 thirdparty/CMakeLists.txt diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ad908c6..af4dc2c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,83 +1,173 @@ image: vladyslavusenko/b_image:latest +variables: + GIT_SUBMODULE_STRATEGY: recursive + BUILD_TYPE: Release + CXX_MARCH: native + CMAKE_INSTALL_PREFIX: /usr/ + DEB_DIR: deb + stages: - build - test - - test_results + - eval + - eval_results - deploy -compile: - stage: build - variables: - CXX_MARCH: 'corei7-avx' +# template for docker builds with ccache +.prepare_docker_template: &prepare_docker_definition + tags: + - docker before_script: - mkdir -p ccache - export CCACHE_BASEDIR=${PWD} - export CCACHE_DIR=${PWD}/ccache - tags: - - docker cache: - key: bionic paths: - ccache/ + +# template for build & unit test & make deb configurations +.compile_test_package_template: &compile_test_package_definition + stage: build script: - - ./scripts/update_submodules.sh - mkdir build - cd build - - cmake .. -DCMAKE_BUILD_TYPE=Release -DCXX_MARCH=${CXX_MARCH} -DCMAKE_INSTALL_PREFIX=/usr/ + - cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DCXX_MARCH=${CXX_MARCH} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} - make -j3 + - ctest - make package - - cd test/ - - ctest -V - - cd ../../ - - mkdir deb_bionic - - cp build/*.deb deb_bionic/ + - cd .. + - mkdir $DEB_DIR + - mv build/*.deb $DEB_DIR/ + - dpkg -i $DEB_DIR/*.deb + # smoke test to see if all executables at least start up + - basalt_calibrate --help + - basalt_calibrate_imu --help + - basalt_mapper --help + - basalt_mapper_sim --help + - basalt_mapper_sim_naive --help + - basalt_opt_flow --help + - basalt_vio --help + - basalt_vio_sim --help + +# template for build & unit test configurations (no deb) +.compile_test_template: &compile_test_definition + stage: build + script: + - mkdir build + - cd build + - cmake .. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DCXX_MARCH=${CXX_MARCH} -DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} + - make -j3 + - ctest + # smoke test to see if all executables at least start up + - ./basalt_calibrate --help + - ./basalt_calibrate_imu --help + - ./basalt_mapper --help + - ./basalt_mapper_sim --help + - ./basalt_mapper_sim_naive --help + - ./basalt_opt_flow --help + - ./basalt_vio --help + - ./basalt_vio_sim --help + +# template to test debian +.test_deb_template: &test_deb_definition + stage: test + tags: + - docker + variables: + GIT_STRATEGY: none + script: + - dpkg -i $DEB_DIR/*.deb + # smoke test to see if all executables at least start up + - basalt_calibrate --help + - basalt_calibrate_imu --help + - basalt_mapper --help + - basalt_mapper_sim --help + - basalt_mapper_sim_naive --help + - basalt_opt_flow --help + - basalt_vio --help + - basalt_vio_sim --help + +bionic-release-compile: + <<: *prepare_docker_definition + <<: *compile_test_package_definition + cache: + key: bionic-release + variables: + CXX_MARCH: 'corei7-avx' + DEB_DIR: deb_bionic artifacts: paths: - deb_bionic/*.deb - scripts/eval_full/* expire_in: 1 week -compile_16_04: - stage: build +xenial-release-compile: + <<: *prepare_docker_definition + <<: *compile_test_package_definition + image: vladyslavusenko/b_image_xenial:latest + cache: + key: xenial-release variables: CXX_MARCH: 'corei7-avx' - before_script: - - mkdir -p ccache - - export CCACHE_BASEDIR=${PWD} - - export CCACHE_DIR=${PWD}/ccache - tags: - - docker - cache: - key: xenial - paths: - - ccache/ - script: - - ./scripts/update_submodules.sh - - mkdir build - - cd build - - cmake .. -DCMAKE_BUILD_TYPE=Release -DCXX_MARCH=${CXX_MARCH} -DCMAKE_INSTALL_PREFIX=/usr/ - - make -j3 - - make package - - cd test/ - - ctest -V - - cd ../../ - - mkdir deb_xenial - - cp build/*.deb deb_xenial/ + DEB_DIR: deb_xenial artifacts: paths: - deb_xenial/*.deb expire_in: 1 week - only: - - master + +bionic-debug-compile: + <<: *prepare_docker_definition + <<: *compile_test_package_definition + cache: + key: bionic-debug + variables: + BUILD_TYPE: Debug + +bionic-relwithdebinfo-compile: + <<: *prepare_docker_definition + <<: *compile_test_package_definition + cache: + key: bionic-relwithdebinfo + variables: + BUILD_TYPE: RelWithDebInfo + +elcapitan-relwithdebinfo-compile: + <<: *compile_test_definition + tags: [macos, "10.11"] + variables: + BUILD_TYPE: RelWithDebInfo + +# check if clang-format would make any changes +clang-format: + # TODO: add clang-format version >= 8 to "vladyslavusenko/b_image" + image: nikolausdemmel/ubuntu-dev-dbatk:16.04 + tags: + - docker + stage: build + variables: + GIT_SUBMODULE_STRATEGY: none + script: + - ./scripts/clang-format-all.sh + # check if any files are now modified and error if yes + - (if git diff --name-only --diff-filter=M | grep '\..pp$'; then echo $'\n Some files are not properly formatted. You can use "./scripts/clang-format-all.sh".\n'; git diff --diff-filter=M; false; fi) + +bionic-test: + <<: *test_deb_definition + variables: + DEB_DIR: deb_bionic + +xenial-test: + <<: *test_deb_definition image: vladyslavusenko/b_image_xenial:latest + variables: + DEB_DIR: deb_xenial - +# evaluate on EuRoC sequences eval_euroc: - stage: test + stage: eval parallel: 10 - tags: - - dataset-eval + tags: [docker, dataset-eval] variables: GIT_STRATEGY: none only: @@ -91,13 +181,14 @@ eval_euroc: - cd scripts/eval_full - ./run_evaluations.sh +# aggregate results for all EuRoC sequences gen_results_euroc: - stage: test_results + stage: eval_results variables: GIT_STRATEGY: none - when: on_success tags: - docker + when: on_success only: - master artifacts: @@ -109,11 +200,15 @@ gen_results_euroc: - cat euroc_results.txt - mv euroc_results.txt ../../ - +# deploy deb packages deploy: stage: deploy + variables: + GIT_STRATEGY: none tags: - docker + only: + - master before_script: - eval $(ssh-agent -s) - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - > /dev/null @@ -121,10 +216,6 @@ deploy: - chmod 700 ~/.ssh - echo "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts - chmod 644 ~/.ssh/known_hosts - variables: - GIT_STRATEGY: none - only: - - master script: - scp $SCP_FLAGS deb_xenial/*.deb $REPOSITORY_URL/xenial/ - scp $SCP_FLAGS deb_bionic/*.deb $REPOSITORY_URL/bionic/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 8fe3c7c..209d4fe 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,9 +1,14 @@ -cmake_minimum_required(VERSION 3.8) +cmake_minimum_required(VERSION 3.10) + +include("thirdparty/basalt-headers/cmake_modules/PreProjectWorkarounds.cmake") + project(basalt) set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake_modules/" ${CMAKE_MODULE_PATH}) -set(EIGEN_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/basalt-headers/thirdparty/eigen") +if(NOT EIGEN_ROOT) + set(EIGEN_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/basalt-headers/thirdparty/eigen") +endif() string(TOLOWER "${PROJECT_NAME}" PROJECT_NAME_LOWERCASE) find_program(DPKG_PROGRAM dpkg DOC "dpkg program of Debian-based systems") @@ -11,89 +16,163 @@ if(DPKG_PROGRAM) execute_process( COMMAND ${DPKG_PROGRAM} --print-architecture OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE - OUTPUT_STRIP_TRAILING_WHITESPACE - ) + OUTPUT_STRIP_TRAILING_WHITESPACE) endif(DPKG_PROGRAM) find_program(LSB_RELEASE_PROGRAM lsb_release DOC "lsb_release program of Debian-based systems") if(LSB_RELEASE_PROGRAM) -execute_process(COMMAND ${LSB_RELEASE_PROGRAM} -rs + execute_process(COMMAND ${LSB_RELEASE_PROGRAM} -rs OUTPUT_VARIABLE LSB_RELEASE_ID_SHORT - OUTPUT_STRIP_TRAILING_WHITESPACE -) + OUTPUT_STRIP_TRAILING_WHITESPACE) -if(${LSB_RELEASE_ID_SHORT} EQUAL "18.04") + if(${LSB_RELEASE_ID_SHORT} EQUAL "18.04") set(DEBIAN_DEPENDS "libtbb2, liblz4-1, libbz2-1.0, libboost-filesystem1.65.1, libboost-date-time1.65.1, libboost-program-options1.65.1, libboost-regex1.65.1, libopencv-dev, libglew2.0, libjpeg8, libpng16-16") -elseif(${LSB_RELEASE_ID_SHORT} EQUAL "16.04") + + elseif(${LSB_RELEASE_ID_SHORT} EQUAL "16.04") set(DEBIAN_DEPENDS "libtbb2, liblz4-1, libbz2-1.0, libboost-filesystem1.58.0, libboost-date-time1.58.0, libboost-program-options1.58.0, libboost-regex1.58.0, libopencv-dev, libglew1.13, libjpeg8, libpng12-0") -endif(${LSB_RELEASE_ID_SHORT} EQUAL "18.04") + endif() endif(LSB_RELEASE_PROGRAM) string(TIMESTAMP PROJECT_VERSION_REVISION "%Y%m%d%H%M") -SET(CPACK_GENERATOR "DEB") -SET(CPACK_DEBIAN_PACKAGE_MAINTAINER "Vladyslav Usenko ") -SET(CPACK_PACKAGE_VERSION_MAJOR "0") -SET(CPACK_PACKAGE_VERSION_MINOR "1") -SET(CPACK_PACKAGE_VERSION_PATCH "0-${PROJECT_VERSION_REVISION}~${LSB_RELEASE_ID_SHORT}") -SET(CPACK_DEBIAN_PACKAGE_DEPENDS ${DEBIAN_DEPENDS}) -SET(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME_LOWERCASE}_${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}") -SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") +set(CPACK_GENERATOR "DEB") +set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Vladyslav Usenko ") +set(CPACK_PACKAGE_VERSION_MAJOR "0") +set(CPACK_PACKAGE_VERSION_MINOR "1") +set(CPACK_PACKAGE_VERSION_PATCH "0-${PROJECT_VERSION_REVISION}~${LSB_RELEASE_ID_SHORT}") +set(CPACK_DEBIAN_PACKAGE_DEPENDS ${DEBIAN_DEPENDS}) +set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME_LOWERCASE}_${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}") +set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") include(CPack) # Configure CCache if available -find_program(CCACHE_PROGRAM ccache) -if(CCACHE_PROGRAM) - message(STATUS "Found ccache: ${CCACHE_PROGRAM}") - set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_PROGRAM}) - set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_PROGRAM}) -endif(CCACHE_PROGRAM) +if (NOT CMAKE_C_COMPILER_LAUNCHER AND NOT CMAKE_CXX_COMPILER_LAUNCHER) + find_program(CCACHE_PROGRAM ccache) + if(CCACHE_PROGRAM) + message(STATUS "Found ccache: ${CCACHE_PROGRAM}") + set(CMAKE_C_COMPILER_LAUNCHER ${CCACHE_PROGRAM}) + set(CMAKE_CXX_COMPILER_LAUNCHER ${CCACHE_PROGRAM}) + else() + message(STATUS "Dind't find ccache") + endif() +else() + message(STATUS "Compiler launcher already set. Not configuring ccache.") + message(STATUS "CMAKE_C_COMPILER_LAUNCHER: ${CMAKE_C_COMPILER_LAUNCHER}") + message(STATUS "CMAKE_CXX_COMPILER_LAUNCHER: ${CMAKE_CXX_COMPILER_LAUNCHER}") +endif() -IF( NOT CMAKE_BUILD_TYPE ) - SET( CMAKE_BUILD_TYPE Release) -ENDIF() +if( NOT CMAKE_BUILD_TYPE ) + set( CMAKE_BUILD_TYPE Release) +endif() + +if(NOT CXX_MARCH) + set(CXX_MARCH native) +endif() -IF(NOT CXX_MARCH) - SET(CXX_MARCH native) -ENDIF() set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) set(CMAKE_POSITION_INDEPENDENT_CODE ON) + # Flags used for CHECK_CXX_SOURCE_COMPILES -set(CMAKE_REQUIRED_FLAGS "-Wno-unused-variable -Wno-unused-value") +set(CMAKE_REQUIRED_FLAGS "-Wno-error") -IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") - SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") - SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -ftree-vectorize -march=${CXX_MARCH}") - SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g -ftree-vectorize -march=${CXX_MARCH}") - SET(CMAKE_CXX_FLAGS "-Wall -Werror -Wextra -Wno-deprecated-register -Qunused-arguments -fcolor-diagnostics -fopenmp") -ELSEIF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") - SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") - SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -ftree-vectorize -march=${CXX_MARCH}") - SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g -ftree-vectorize -march=${CXX_MARCH}") - SET(CMAKE_CXX_FLAGS "-Wall -Wextra -Wno-deprecated-register -Wno-deprecated-declarations -Wno-sign-compare -Wno-exceptions -Wno-missing-field-initializers -Wno-unused-parameter -Wno-unused-private-field -Qunused-arguments -fcolor-diagnostics -nostdinc++") - include_directories(/usr/local/opt/llvm/include/c++/v1) - link_directories(/usr/local/opt/llvm/lib) - SET(STD_CXX_FS c++fs) -ELSEIF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") - SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g") - SET(CMAKE_CXX_FLAGS_RELEASE "-O3 -ftree-vectorize -march=${CXX_MARCH}") - SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g -ftree-vectorize -march=${CXX_MARCH}") - SET(CMAKE_CXX_FLAGS "-Wall -Werror -Wextra -std=c++11 -Wno-misleading-indentation -Wno-sign-compare -Wno-maybe-uninitialized -Wno-int-in-bool-context -Wno-implicit-fallthrough -Wno-unused-parameter -Wno-deprecated-declarations -ftemplate-backtrace-limit=0 -fopenmp") - SET(STD_CXX_FS stdc++fs) -ENDIF() +# save flags passed by user +set(BASALT_PASSED_CXX_FLAGS "${CMAKE_CXX_FLAGS}") + +set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g -DEIGEN_INITIALIZE_MATRICES_BY_NAN") # cmake default: "-g" +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g -DEIGEN_INITIALIZE_MATRICES_BY_NAN") # cmake default: "-O2 -g -DNDEBUG" +set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG") # cmake default: "-O3 -DNDEBUG" + +# base set of compile flags +set(BASALT_CXX_FLAGS "-Wall -Wextra -Werror -Wno-unused-parameter -ftemplate-backtrace-limit=0") + +# clang-specific compile flags +if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") + set(BASALT_CXX_FLAGS "${BASALT_CXX_FLAGS} -Wno-exceptions -fcolor-diagnostics") +endif() + + +# Set platform / compiler specific compile flags and checks +if(APPLE) + # Need to investigate how to reliably detect and use OpenMP on macOS... + set(USE_OPENMP_DEFAULT Off) + + # Among others, setting CMAKE_FIND_FRAMEWORK to LAST fixed issues + # with installed Mono that contains old headers (libpng, ...). + # See: https://github.com/openMVG/openMVG/issues/1349#issuecomment-401492811 + set(CMAKE_FIND_FRAMEWORK LAST) + + # use brewed llvm's libc++ + add_compile_options("-nostdinc++") + include_directories("/usr/local/opt/llvm/include/c++/v1") + link_directories("/usr/local/opt/llvm/lib") + set(STD_CXX_FS c++fs) + + if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + message(STATUS "Detected macOS with non-Apple clang") + + elseif(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") + message(STATUS "Detected macOS with Apple clang") + # Apple clang on macOS < 10.14 Mojave is too old + if(CMAKE_SYSTEM_VERSION VERSION_LESS 18.0.0) + message(WARNING "Detected Darwin version ${CMAKE_SYSTEM_VERSION}, which is earlier than macos 10.14 Mojave. Apple clang is too old and not supported. Use clang from homebrew.") + endif() + + else() + message(WARNING "Detected macOS with unsupported compiler ${CMAKE_CXX_COMPILER_ID}") + endif() + +elseif(UNIX) + set(USE_OPENMP_DEFAULT On) + + # assume libstdc++ + set(STD_CXX_FS stdc++fs) + + if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + set(LINUX_CLANG 1) + message(STATUS "Detected Linux with clang.") + message(WARNING "Clang on Linux is currently not fully supported. You'll likely need to get a recent version of TBB.") + + elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + message(STATUS "Detected Linux with gcc.") + + else() + message(WARNING "Detected Linux with unsupported compiler ${CMAKE_CXX_COMPILER_ID}") + endif() + +else() + message(WARNING "Only Linux and macOS are currently supported") +endif() + + +# OpenMP option and compile flags +option(USE_OPENMP "Use OpenMP (e.g. for parallel computation in Eigen)" ${USE_OPENMP_DEFAULT}) +if(USE_OPENMP) + message(STATUS "OpenMP Enabled") + set(BASALT_CXX_FLAGS "${BASALT_CXX_FLAGS} -fopenmp") +else() + message(STATUS "OpenMP Disabled") +endif() + + +# setup combined compiler flags +set(CMAKE_CXX_FLAGS "${BASALT_CXX_FLAGS} -march=${CXX_MARCH} ${BASALT_PASSED_CXX_FLAGS}") + set(EIGEN_INCLUDE_DIR_HINTS ${EIGEN_ROOT}) find_package(Eigen3 3.3.7 REQUIRED) include_directories(${EIGEN3_INCLUDE_DIR}) message(STATUS "Found Eigen headers in: ${EIGEN3_INCLUDE_DIR}") +if(NOT EIGEN3_INCLUDE_DIR MATCHES "^${EIGEN_ROOT}") + message(WARNING "Found Eigen headers are outside of specified EIGEN_ROOT '${EIGEN_ROOT}'") +endif() find_package(TBB REQUIRED) include_directories(${TBB_INCLUDE_DIR}) @@ -103,26 +182,9 @@ include_directories(${OpenCV_INCLUDE_DIR}) message(STATUS "Found OpenCV headers in: ${OpenCV_INCLUDE_DIR}") message(STATUS "Found OpenCV_LIBS: ${OpenCV_LIBS}") -add_subdirectory(thirdparty/ros) -add_subdirectory(thirdparty/apriltag) -add_subdirectory(thirdparty/DBoW3) +add_subdirectory(thirdparty) -set(BUILD_SHARED_LIBS OFF CACHE BOOL "Enable BUILD_SHARED_LIBS") -set(BUILD_TESTS OFF CACHE BOOL "Enable BUILD_TESTS") - -set(BUILD_PANGOLIN_LIBOPENEXR OFF CACHE BOOL "Enable BUILD_PANGOLIN_LIBOPENEXR") -set(BUILD_PANGOLIN_PYTHON OFF CACHE BOOL "Enable BUILD_PANGOLIN_PYTHON") -set(BUILD_EXAMPLES OFF CACHE BOOL "Enable BUILD_EXAMPLES") -add_subdirectory(thirdparty/opengv EXCLUDE_FROM_ALL) - -# Hack to disable CPack in Pangolin. -macro(include) - if(NOT ${ARGV0} STREQUAL "CPack") - _include(${ARGN}) - endif() -endmacro() -add_subdirectory(thirdparty/Pangolin EXCLUDE_FROM_ALL) include_directories(thirdparty/basalt-headers/thirdparty/Sophus) include_directories(thirdparty/basalt-headers/thirdparty/cereal/include) @@ -135,76 +197,71 @@ include_directories(include) add_library(basalt SHARED - src/io/dataset_io.cpp - src/io/marg_data_io.cpp - src/calibration/cam_calib.cpp - src/calibration/cam_imu_calib.cpp - src/calibration/calibraiton_helper.cpp - src/calibration/vignette.cpp - src/utils/vio_config.cpp - src/optical_flow/optical_flow.cpp - src/vi_estimator/keypoint_vio.cpp - src/vi_estimator/keypoint_vio_linearize.cpp - src/vi_estimator/vio_estimator.cpp - src/vi_estimator/ba_base.cpp - src/vi_estimator/nfr_mapper.cpp - src/utils/keypoints.cpp) + src/io/dataset_io.cpp + src/io/marg_data_io.cpp + src/calibration/cam_calib.cpp + src/calibration/cam_imu_calib.cpp + src/calibration/calibraiton_helper.cpp + src/calibration/vignette.cpp + src/utils/vio_config.cpp + src/optical_flow/optical_flow.cpp + src/vi_estimator/keypoint_vio.cpp + src/vi_estimator/keypoint_vio_linearize.cpp + src/vi_estimator/vio_estimator.cpp + src/vi_estimator/ba_base.cpp + src/vi_estimator/nfr_mapper.cpp + src/utils/keypoints.cpp) -target_link_libraries(basalt rosbag pangolin apriltag ${OPENGV_LIBS} ${TBB_LIBRARIES} ${OpenCV_LIBS} opengv ${STD_CXX_FS} DBoW3) +target_link_libraries(basalt PUBLIC ${TBB_LIBRARIES} ${STD_CXX_FS} ${OpenCV_LIBS} pangolin PRIVATE rosbag apriltag opengv DBoW3) add_executable(basalt_calibrate src/calibrate.cpp) -target_link_libraries(basalt_calibrate ${Pangolin_LIBRARIES} apriltag ${OPENGV_LIBS} ${TBB_LIBRARIES} ${rosbag_LIBRARIES} basalt) +target_link_libraries(basalt_calibrate basalt) add_executable(basalt_calibrate_imu src/calibrate_imu.cpp) -target_link_libraries(basalt_calibrate_imu ${Pangolin_LIBRARIES} apriltag ${OPENGV_LIBS} ${TBB_LIBRARIES} ${rosbag_LIBRARIES} basalt) +target_link_libraries(basalt_calibrate_imu basalt) -add_executable(basalt_vio_sim src/vio_sim.cpp ) -target_link_libraries(basalt_vio_sim ${Pangolin_LIBRARIES} opengv ${STD_CXX_FS} ${TBB_LIBRARIES} basalt) +add_executable(basalt_vio_sim src/vio_sim.cpp) +target_link_libraries(basalt_vio_sim basalt) -add_executable(basalt_mapper_sim src/mapper_sim.cpp ) -target_link_libraries(basalt_mapper_sim ${Pangolin_LIBRARIES} opengv ${TBB_LIBRARIES} basalt) +add_executable(basalt_mapper_sim src/mapper_sim.cpp) +target_link_libraries(basalt_mapper_sim basalt) add_executable(basalt_mapper_sim_naive src/mapper_sim_naive.cpp) -target_link_libraries(basalt_mapper_sim_naive ${Pangolin_LIBRARIES} opengv ${TBB_LIBRARIES} basalt) +target_link_libraries(basalt_mapper_sim_naive basalt) add_executable(basalt_mapper src/mapper.cpp) -target_link_libraries(basalt_mapper ${Pangolin_LIBRARIES} opengv ${STD_CXX_FS} ${TBB_LIBRARIES} basalt) +target_link_libraries(basalt_mapper basalt) add_executable(basalt_opt_flow src/opt_flow.cpp) -target_link_libraries(basalt_opt_flow ${Pangolin_LIBRARIES} opengv ${STD_CXX_FS} basalt) +target_link_libraries(basalt_opt_flow basalt) add_executable(basalt_vio src/vio.cpp) -target_link_libraries(basalt_vio ${Pangolin_LIBRARIES} opengv ${STD_CXX_FS} basalt) - +target_link_libraries(basalt_vio basalt) install(TARGETS basalt_calibrate basalt_calibrate_imu basalt_vio_sim basalt_mapper_sim basalt_mapper_sim_naive basalt_mapper basalt_opt_flow basalt_vio basalt - EXPORT BasaltTargets - RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin - LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib - ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib -) + EXPORT BasaltTargets + RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin + LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib + ARCHIVE DESTINATION ${CMAKE_INSTALL_PREFIX}/lib) file(GLOB CONFIG_FILES "${CMAKE_CURRENT_SOURCE_DIR}/data/*.json") -INSTALL(FILES ${CONFIG_FILES} ${CMAKE_CURRENT_SOURCE_DIR}/data/basalt-data/orbvoc.dbow3 - DESTINATION ${CMAKE_INSTALL_PREFIX}/etc/basalt -) +install(FILES ${CONFIG_FILES} ${CMAKE_CURRENT_SOURCE_DIR}/data/basalt-data/orbvoc.dbow3 + DESTINATION ${CMAKE_INSTALL_PREFIX}/etc/basalt) # Replace install() to do-nothing macro. macro(install) endmacro() # Include subproject (or any other CMake code) with "disabled" install(). +enable_testing() add_subdirectory(thirdparty/basalt-headers/test) add_subdirectory(test) # Restore original install() behavior. macro(install) - _install(${ARGN}) + _install(${ARGN}) endmacro() - - - diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 26d576a..b7fe4a4 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -1,31 +1,28 @@ -cmake_minimum_required(VERSION 3.2) - -find_package(TBB REQUIRED) -include_directories(${TBB_INCLUDE_DIR}) - -set(GTEST_MAIN_LIBRARY gtest_main) -set(GTEST_LIBRARY gtest) +cmake_minimum_required(VERSION 3.10) +# Note: add_subdirectory(googletest ...) is called in basalt-headers include_directories(../thirdparty/basalt-headers/test/include) add_executable(test_image src/test_image.cpp) -target_link_libraries(test_image ${GTEST_LIBRARY} ${GTEST_MAIN_LIBRARY} ${OpenCV_LIBS} basalt) +target_link_libraries(test_image gtest gtest_main basalt) add_executable(test_spline_opt src/test_spline_opt.cpp) -target_link_libraries(test_spline_opt ${GTEST_LIBRARY} ${GTEST_MAIN_LIBRARY} ${TBB_LIBRARIES} opengv basalt) +target_link_libraries(test_spline_opt gtest gtest_main basalt) add_executable(test_vio src/test_vio.cpp) -target_link_libraries(test_vio ${GTEST_LIBRARY} ${GTEST_MAIN_LIBRARY} ${TBB_LIBRARIES} opengv basalt) +target_link_libraries(test_vio gtest gtest_main basalt) add_executable(test_nfr src/test_nfr.cpp) -target_link_libraries(test_nfr ${GTEST_LIBRARY} ${GTEST_MAIN_LIBRARY} ${TBB_LIBRARIES} opengv basalt) +target_link_libraries(test_nfr gtest gtest_main basalt) enable_testing() -add_test(test_image test_image COMMAND Test) -add_test(test_spline_opt test_spline_opt COMMAND Test) -add_test(test_vio test_vio COMMAND Test) -add_test(test_nfr test_nfr COMMAND Test) +include(GoogleTest) + +gtest_discover_tests(test_image DISCOVERY_TIMEOUT 30) +gtest_discover_tests(test_spline_opt DISCOVERY_TIMEOUT 30) +gtest_discover_tests(test_vio DISCOVERY_TIMEOUT 30) +gtest_discover_tests(test_nfr DISCOVERY_TIMEOUT 30) diff --git a/thirdparty/CMakeLists.txt b/thirdparty/CMakeLists.txt new file mode 100644 index 0000000..f796651 --- /dev/null +++ b/thirdparty/CMakeLists.txt @@ -0,0 +1,106 @@ +cmake_minimum_required(VERSION 3.10) + +add_subdirectory(ros EXCLUDE_FROM_ALL) +add_subdirectory(apriltag EXCLUDE_FROM_ALL) +add_subdirectory(DBoW3 EXCLUDE_FROM_ALL) + + +set(BUILD_SHARED_LIBS OFF CACHE BOOL "Enable BUILD_SHARED_LIBS") +set(BUILD_TESTS OFF CACHE BOOL "Enable BUILD_TESTS") +set(BUILD_TOOLS OFF CACHE BOOL "Enable BUILD_TOOLS") +set(CMAKE_EXPORT_NO_PACKAGE_REGISTRY ON) + +set(BUILD_PANGOLIN_LIBOPENEXR OFF CACHE BOOL "Enable BUILD_PANGOLIN_LIBOPENEXR") +set(BUILD_PANGOLIN_PYTHON OFF CACHE BOOL "Enable BUILD_PANGOLIN_PYTHON") +set(BUILD_EXAMPLES OFF CACHE BOOL "Enable BUILD_EXAMPLES") + +set(EIGEN_INCLUDE_DIR "${EIGEN3_INCLUDE_DIR}") +set(EIGEN_INCLUDE_DIRS "${EIGEN3_INCLUDE_DIR}") + +add_subdirectory(opengv EXCLUDE_FROM_ALL) + +# Hack to disable CPack in Pangolin. +macro(include) + if(NOT ${ARGV0} STREQUAL "CPack") + _include(${ARGN}) + endif() +endmacro() +add_subdirectory(Pangolin EXCLUDE_FROM_ALL) + + +# fix aprilgrid +target_compile_options(apriltag PRIVATE "-Wno-unused-private-field") + +# fix opengv: c++17 and debug postfix +set_target_properties(opengv PROPERTIES + CXX_STANDARD 17 + DEBUG_POSTFIX "") + +# fix opengv: compile options (CMAKE_CXX_FLAGS is overwritten by Opengv) +target_compile_options(opengv PRIVATE + -Wno-unused-private-field + -march=${CXX_MARCH} + ${BASALT_PASSED_CXX_FLAGS}) + +# TODO: enable once mpark issue is fixed upstream pangolin +#set_target_properties(pangolin PROPERTIES +# CXX_STANDARD 17) + +# fix pangolin: gcc +if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + target_compile_options(pangolin PRIVATE "-Wno-implicit-fallthrough") +endif() + +# fix pangolin: macOS +if(APPLE) + target_compile_options(pangolin PRIVATE "-Wno-objc-missing-super-calls") +endif() + +# fix pangolin: macOS >= 10.14 Mojave +if(APPLE AND CMAKE_SYSTEM_VERSION VERSION_GREATER_EQUAL 18.0.0) + target_compile_options(pangolin PRIVATE "-Wno-deprecated-declarations") +endif() + +# fix pangolin: clang +if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") + target_compile_options(pangolin PRIVATE "-Wno-null-pointer-arithmetic") +endif() + +# fix pangolin: clang >= 8.0 +if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 8.0.0) + target_compile_options(pangolin PRIVATE "-Wno-defaulted-function-deleted") +endif() + +# check here the directories for the pangolin and opengv targets, and +# confirm that the eigen-related include dirs match. +foreach(_target opengv pangolin) + get_target_property(_include_dirs ${_target} INTERFACE_INCLUDE_DIRECTORIES) + foreach(_dir IN LISTS _include_dirs) + if("${_dir}" MATCHES ".*/eigen3?(/unsupported)?$") + if(NOT _dir MATCHES "^${EIGEN3_INCLUDE_DIR}.*") + endif() + endif() + endforeach() +endforeach() + +# opengv and pangolin assume that eigen is found outside the source +# directory and thus include it in INTERFACE_INCLUDE_DIRECTORIES, +# which makes cmake complain that that property contains paths in the +# source folder. Thus, we update the property to only include these +# eigen paths in the "BUILD_INTERFACE" (not "INSTALL"). +if (EIGEN3_INCLUDE_DIR MATCHES "^${CMAKE_SOURCE_DIR}.*") + foreach(_target opengv pangolin) + get_target_property(_include_dirs ${_target} INTERFACE_INCLUDE_DIRECTORIES) + set(_include_dirs_new "") + foreach(_dir IN LISTS _include_dirs) + if(_dir MATCHES ".*/eigen(/unsupported)?$") + string(REGEX REPLACE "(^${CMAKE_SOURCE_DIR}.*$)" "$" _dir "${_dir}") + endif() + list(APPEND _include_dirs_new "${_dir}") + endforeach() + set_target_properties(${_target} PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${_include_dirs_new}") + endforeach() +endif() + + +