-
Notifications
You must be signed in to change notification settings - Fork 52
/
CMakeLists.txt
330 lines (294 loc) · 9.85 KB
/
CMakeLists.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
cmake_minimum_required(VERSION 3.16)
project(small_gicp VERSION 1.0.0 LANGUAGES C CXX)
set(CMAKE_CXX_STANDARD 17)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build." FORCE)
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
option(CMAKE_POSITION_INDEPENDENT_CODE "Generate position-independent code" ON)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
# Build options
option(BUILD_HELPER "Build helper library" ON)
option(BUILD_TESTS "Build tests" OFF)
option(BUILD_EXAMPLES "Build examples" OFF)
option(BUILD_BENCHMARKS "Build benchmarks" OFF)
option(BUILD_PYTHON_BINDINGS "Build python bindings" OFF)
option(ENABLE_COVERAGE "Enable coverage" OFF)
# Dependency options
set(BUILD_WITH_OPENMP "auto" CACHE STRING "Build with OpenMP")
option(BUILD_WITH_TBB "Build with TBB" OFF)
option(BUILD_WITH_PCL "Build with PCL (required for benchmark and test only)" OFF)
option(BUILD_WITH_FAST_GICP "Build with fast_gicp (required for benchmark and test only)" OFF)
option(BUILD_WITH_IRIDESCENCE "Build with Iridescence (required for benchmark)" OFF)
option(BUILD_WITH_MARCH_NATIVE "Build with -march=native" OFF)
# Set mandatory dependencies of optional features
if(BUILD_TESTS OR BUILD_EXAMPLES OR BUILD_BENCHMARKS)
find_package(fmt REQUIRED)
endif()
if(BUILD_TESTS OR BUILD_EXAMPLES)
set(BUILD_HELPER ON CACHE BOOL "Helper library is required" FORCE)
set(BUILD_WITH_TBB ON CACHE BOOL "TBB is required" FORCE)
set(BUILD_WITH_PCL ON CACHE BOOL "PCL is required" FORCE)
endif()
# Eigen is the sole mandatory dependency
find_package(Eigen3 CONFIG)
if(NOT Eigen3_FOUND)
message(STATUS "System Eigen not found. Download Eigen 3.4.0.")
include(FetchContent)
FetchContent_Populate(
Eigen3
URL https://gitlab.com/libeigen/eigen/-/archive/3.4.0/eigen-3.4.0.tar.gz
)
add_library(Eigen3::Eigen INTERFACE IMPORTED GLOBAL)
set_target_properties(Eigen3::Eigen PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${eigen3_SOURCE_DIR}"
)
endif()
if(BUILD_WITH_OPENMP STREQUAL "auto")
find_package(OpenMP)
set(BUILD_WITH_OPENMP ${OpenMP_FOUND})
elseif(BUILD_WITH_OPENMP)
find_package(OpenMP REQUIRED)
endif()
if (BUILD_WITH_TBB)
find_package(TBB REQUIRED)
add_compile_definitions(BUILD_WITH_TBB)
endif()
if (BUILD_WITH_PCL)
find_package(PCL REQUIRED)
add_compile_definitions(BUILD_WITH_PCL)
if (NOT TARGET PCL::PCL)
add_library(PCL::PCL INTERFACE IMPORTED)
set_target_properties(PCL::PCL PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${PCL_INCLUDE_DIRS}"
INTERFACE_LINK_LIBRARIES "${PCL_LIBRARIES}"
)
endif()
endif()
if (BUILD_WITH_IRIDESCENCE)
find_package(Iridescence REQUIRED)
add_compile_definitions(BUILD_WITH_IRIDESCENCE)
endif()
if (BUILD_WITH_FAST_GICP)
if (NOT FAST_GICP_INCLUDE_DIR)
set(FAST_GICP_INCLUDE_DIR $ENV{FAST_GICP_INCLUDE_DIR} CACHE PATH "Path to fast_gicp include directory")
endif()
add_compile_definitions(BUILD_WITH_FAST_GICP)
endif()
if(BUILD_WITH_MARCH_NATIVE)
add_compile_options(-march=native)
endif()
if(MSVC)
add_compile_definitions(_USE_MATH_DEFINES)
# add_compile_options(/openmp:llvm)
endif()
##############
## Coverage ##
##############
if(ENABLE_COVERAGE)
# https://danielsieger.com/blog/2022/03/06/code-coverage-for-cpp.html
set(CMAKE_CXX_FLAGS "-O0 -coverage")
find_program(LCOV lcov REQUIRED)
find_program(GENHTML genhtml REQUIRED)
add_custom_target(coverage
COMMAND ${LCOV} --directory . --capture --output-file coverage.info
COMMAND ${LCOV} --remove coverage.info -o coverage.info '/usr/*'
COMMAND ${GENHTML} --demangle-cpp -o coverage coverage.info
WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
endif()
###########
## Build ##
###########
include_directories(include)
# Helper library
if(BUILD_HELPER)
add_library(small_gicp
src/small_gicp/registration/registration.cpp
src/small_gicp/registration/registration_helper.cpp
)
target_include_directories(small_gicp PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
target_link_libraries(small_gicp PUBLIC
Eigen3::Eigen
$<TARGET_NAME_IF_EXISTS:OpenMP::OpenMP_CXX>
)
endif()
# Python bindings
if(BUILD_PYTHON_BINDINGS)
find_package(Python COMPONENTS Interpreter Development)
find_package(pybind11 CONFIG REQUIRED)
pybind11_add_module(small_gicp_python
src/small_gicp/registration/registration.cpp
src/small_gicp/registration/registration_helper.cpp
src/python/pointcloud.cpp
src/python/kdtree.cpp
src/python/voxelmap.cpp
src/python/preprocess.cpp
src/python/result.cpp
src/python/align.cpp
src/python/factors.cpp
src/python/misc.cpp
src/python/python.cpp
)
target_include_directories(small_gicp_python PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
target_link_libraries(small_gicp_python PUBLIC
Eigen3::Eigen
$<TARGET_NAME_IF_EXISTS:OpenMP::OpenMP_CXX>
)
set_target_properties(small_gicp_python PROPERTIES OUTPUT_NAME small_gicp)
endif()
###############
## Benchmark ##
###############
if(BUILD_BENCHMARKS)
# Odometry benchmark
add_executable(odometry_benchmark
src/small_gicp/benchmark/benchmark_odom.cpp
src/benchmark/odometry_benchmark_pcl.cpp
src/benchmark/odometry_benchmark_fast_gicp.cpp
src/benchmark/odometry_benchmark_fast_vgicp.cpp
src/benchmark/odometry_benchmark_small_gicp.cpp
src/benchmark/odometry_benchmark_small_gicp_pcl.cpp
src/benchmark/odometry_benchmark_small_gicp_omp.cpp
src/benchmark/odometry_benchmark_small_vgicp_omp.cpp
src/benchmark/odometry_benchmark_small_gicp_tbb.cpp
src/benchmark/odometry_benchmark_small_vgicp_tbb.cpp
src/benchmark/odometry_benchmark_small_gicp_model_tbb.cpp
src/benchmark/odometry_benchmark_small_gicp_model_omp.cpp
src/benchmark/odometry_benchmark_small_vgicp_model_tbb.cpp
src/benchmark/odometry_benchmark_small_vgicp_model_omp.cpp
src/benchmark/odometry_benchmark_small_gicp_tbb_flow.cpp
src/benchmark/odometry_benchmark.cpp
)
target_include_directories(odometry_benchmark PUBLIC
${FAST_GICP_INCLUDE_DIR}
)
target_link_libraries(odometry_benchmark PRIVATE
fmt::fmt
Eigen3::Eigen
$<TARGET_NAME_IF_EXISTS:OpenMP::OpenMP_CXX>
$<TARGET_NAME_IF_EXISTS:Iridescence::Iridescence>
$<TARGET_NAME_IF_EXISTS:TBB::tbb>
$<TARGET_NAME_IF_EXISTS:TBB::tbbmalloc>
$<TARGET_NAME_IF_EXISTS:PCL::PCL>
)
# KdTree construction benchmark
add_executable(kdtree_benchmark
src/benchmark/kdtree_benchmark.cpp
)
target_link_libraries(kdtree_benchmark PRIVATE
fmt::fmt
Eigen3::Eigen
$<TARGET_NAME_IF_EXISTS:OpenMP::OpenMP_CXX>
$<TARGET_NAME_IF_EXISTS:TBB::tbb>
$<TARGET_NAME_IF_EXISTS:TBB::tbbmalloc>
)
# Downsampling benchmark
add_executable(downsampling_benchmark
src/benchmark/downsampling_benchmark.cpp
)
target_link_libraries(downsampling_benchmark PRIVATE
fmt::fmt
Eigen3::Eigen
$<TARGET_NAME_IF_EXISTS:OpenMP::OpenMP_CXX>
$<TARGET_NAME_IF_EXISTS:TBB::tbb>
$<TARGET_NAME_IF_EXISTS:TBB::tbbmalloc>
$<TARGET_NAME_IF_EXISTS:PCL::PCL>
)
endif()
#############
## Example ##
#############
if(BUILD_EXAMPLES)
file(GLOB EXAMPLE_SOURCES "src/example/*.cpp")
foreach(EXAMPLE_SOURCE ${EXAMPLE_SOURCES})
get_filename_component(EXAMPLE_NAME ${EXAMPLE_SOURCE} NAME_WE)
add_executable(${EXAMPLE_NAME} ${EXAMPLE_SOURCE})
target_link_libraries(${EXAMPLE_NAME} PRIVATE
small_gicp
fmt::fmt
TBB::tbb
TBB::tbbmalloc
PCL::PCL
)
endforeach()
endif()
##########
## Test ##
##########
if(BUILD_TESTS)
find_package(GTest REQUIRED)
enable_testing()
file(GLOB TEST_SOURCES "src/test/*.cpp")
# Generate test target for each test source file
foreach(TEST_SOURCE ${TEST_SOURCES})
get_filename_component(TEST_NAME ${TEST_SOURCE} NAME_WE)
add_executable(${TEST_NAME} ${TEST_SOURCE})
target_link_libraries(${TEST_NAME} PRIVATE
small_gicp
fmt::fmt
GTest::gtest_main
TBB::tbb
TBB::tbbmalloc
PCL::PCL
OpenMP::OpenMP_CXX
)
gtest_discover_tests(${TEST_NAME} WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
endforeach()
endif()
#############
## Install ##
#############
include(GNUInstallDirs)
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
if(BUILD_HELPER)
install(TARGETS small_gicp
EXPORT small_gicp-targets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
set(CMAKE_CONFIG_INSTALL_DIR
"${CMAKE_INSTALL_LIBDIR}/cmake/small_gicp"
CACHE PATH "Install directory for CMake config files"
)
include(CMakePackageConfigHelpers)
install(EXPORT small_gicp-targets
FILE small_gicp-targets.cmake
NAMESPACE small_gicp::
DESTINATION ${CMAKE_CONFIG_INSTALL_DIR}
)
configure_package_config_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/small_gicp-config.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/small_gicp-config.cmake"
INSTALL_DESTINATION ${CMAKE_CONFIG_INSTALL_DIR}
)
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/small_gicp-config-version.cmake"
VERSION ${VERSION}
COMPATIBILITY SameMajorVersion
)
install(FILES
"${CMAKE_CURRENT_BINARY_DIR}/small_gicp-config.cmake"
"${CMAKE_CURRENT_BINARY_DIR}/small_gicp-config-version.cmake"
DESTINATION ${CMAKE_CONFIG_INSTALL_DIR}
)
endif()
if(BUILD_PYTHON_BINDINGS)
if(DEFINED SKBUILD_PROJECT_NAME)
set(PYTHON_INSTALL_DIR .)
elseif(NOT DEFINED PYTHON_INSTALL_DIR)
set(PYTHON_INSTALL_DIR lib/python${Python_VERSION_MAJOR}.${Python_VERSION_MINOR}/site-packages)
endif()
install(TARGETS small_gicp_python
LIBRARY DESTINATION ${PYTHON_INSTALL_DIR}
COMPONENT python
)
endif()