CMakeLists.txt 13.7 KB
Newer Older
1
cmake_minimum_required(VERSION 3.0)
2
3
4

project(biboumi)

5
set(${PROJECT_NAME}_VERSION_MAJOR 6)
louiz’'s avatar
louiz’ committed
6
set(${PROJECT_NAME}_VERSION_MINOR 1)
louiz’'s avatar
louiz’ committed
7
set(${PROJECT_NAME}_VERSION_SUFFIX "")
8

9
10
11
12
13
if(NOT CMAKE_BUILD_TYPE)
  set(CMAKE_BUILD_TYPE "Debug" CACHE STRING
      "Build type (Release/Debug/RelWithDebInfo/MinSizeRel)" FORCE)
endif()

louiz’'s avatar
louiz’ committed
14
15
16
#
## Find optional instrumentation libraries that will be used in debug only
#
17
find_library(LIBASAN NAMES asan libasan.so.4 libasan.so.3 libasan.so.2 libasan.so.1)
18
19
find_library(LIBUBSAN NAMES ubsan libubsan.so.0)

louiz’'s avatar
louiz’ committed
20
21
22
#
## Set various debug flags (instrumentation libs, coverage, …)
#
23
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y -pedantic -Wall -Wextra -Wconversion -fvisibility=hidden -fvisibility-inlines-hidden")
24
25
26
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
  set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fprofile-arcs -ftest-coverage --coverage")
endif()
27
28
29
30
31
32
33
if(LIBASAN)
  set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=address")
endif()
if(LIBUBSAN)
  set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fsanitize=undefined")
endif()

34
#
louiz’'s avatar
louiz’ committed
35
## Set the software version, archive name, RPM name etc
36
#
louiz’'s avatar
louiz’ committed
37
set(ARCHIVE_NAME ${CMAKE_PROJECT_NAME}-${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR})
38
39
set(RPM_VERSION ${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR})

louiz’'s avatar
louiz’ committed
40
if(${PROJECT_NAME}_VERSION_SUFFIX MATCHES ".+")
41
  set(ARCHIVE_NAME ${ARCHIVE_NAME}${${PROJECT_NAME}_VERSION_SUFFIX})
42
  set(RPM_VERSION ${RPM_VERSION}${${PROJECT_NAME}_VERSION_SUFFIX})
louiz’'s avatar
louiz’ committed
43
44
45
endif()

if(${PROJECT_NAME}_VERSION_SUFFIX MATCHES "^~dev$")
46
47
48
  # If we are on a dev version, append the hash of the current git HEAD to
  # the version
  include(FindGit)
louiz’'s avatar
louiz’ committed
49
  if(GIT_FOUND AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
50
51
52
53
54
    execute_process(COMMAND git --git-dir=${CMAKE_SOURCE_DIR}/.git rev-parse --short HEAD
      OUTPUT_VARIABLE GIT_REVISION
      OUTPUT_STRIP_TRAILING_WHITESPACE)
    if(GIT_REVISION)
      set(${PROJECT_NAME}_VERSION_SUFFIX "${${PROJECT_NAME}_VERSION_SUFFIX} (${GIT_REVISION})")
55
      set(ARCHIVE_NAME ${ARCHIVE_NAME}${GIT_REVISION})
56
      set(RPM_VERSION ${RPM_VERSION}${GIT_REVISION})
57
58
59
60
    endif()
  endif()
endif()

61
set(SOFTWARE_VERSION
62
63
  ${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}${${PROJECT_NAME}_VERSION_SUFFIX})

64
#
louiz’'s avatar
louiz’ committed
65
## The rule that generates the documentation
66
#
67
68
execute_process(COMMAND "date" "+%Y-%m-%d" OUTPUT_VARIABLE DOC_DATE
                OUTPUT_STRIP_TRAILING_WHITESPACE)
69
set(MAN_PAGE ${CMAKE_CURRENT_BINARY_DIR}/doc/${PROJECT_NAME}.1)
70
set(DOC_PAGE ${CMAKE_CURRENT_SOURCE_DIR}/doc/${PROJECT_NAME}.1.rst)
71
72
73
74
75
76
77
78
79
80
81
82
83
84
if (NOT PANDOC_EXECUTABLE)
  find_program(PANDOC_EXECUTABLE NAMES pandoc
    DOC "The pandoc software, to build the man page from the rst documentation")
  if(PANDOC_EXECUTABLE)
    message(STATUS "Found Pandoc: ${PANDOC_EXECUTABLE}")
    set(WITH_DOC true)
    file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/doc/)
    add_custom_command(OUTPUT ${MAN_PAGE}
      COMMAND ${PANDOC_EXECUTABLE} -M date="${DOC_DATE}" -s -t man ${DOC_PAGE} -o ${MAN_PAGE}
      DEPENDS ${DOC_PAGE})
    add_custom_target(doc ALL DEPENDS ${MAN_PAGE})
  else()
    message(STATUS "Pandoc not found, documentation cannot be built")
  endif()
85
endif()
86
mark_as_advanced(PANDOC_EXECUTABLE)
87

louiz’'s avatar
louiz’ committed
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
#
## Set this search path for cmake, to find our custom search modules
#
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/")
find_package(ICONV REQUIRED)
find_package(LIBUUID REQUIRED)
find_package(EXPAT REQUIRED)

#
## Find all the libraries (optional or not)
#
if(WITH_LIBIDN)
  find_package(LIBIDN REQUIRED)
elseif(NOT WITHOUT_LIBIDN)
  find_package(LIBIDN)
103
104
endif()

louiz’'s avatar
louiz’ committed
105
106
107
108
109
if(WITH_SYSTEMD)
  find_package(SYSTEMD REQUIRED)
elseif(NOT WITHOUT_SYSTEMD)
  find_package(SYSTEMD)
endif()
110

louiz’'s avatar
louiz’ committed
111
112
113
114
if(WITH_BOTAN)
  find_package(BOTAN REQUIRED)
elseif(NOT WITHOUT_BOTAN)
  find_package(BOTAN)
115
116
endif()

louiz’'s avatar
louiz’ committed
117
118
119
if(NOT BOTAN_FOUND)
  find_package(GCRYPT REQUIRED)
endif()
120

louiz’'s avatar
louiz’ committed
121
122
123
124
125
126
if(WITH_UDNS)
  find_package(UDNS REQUIRED)
elseif(NOT WITHOUT_UDNS)
  find_package(UDNS)
endif()

louiz’'s avatar
louiz’ committed
127
128
129
130
if(WITH_SQLITE3)
  find_package(SQLITE3 REQUIRED)
elseif(NOT WITHOUT_SQLITE3)
  find_package(SQLITE3)
louiz’'s avatar
louiz’ committed
131
132
endif()

louiz’'s avatar
louiz’ committed
133
134
135
136
137
138
if(WITH_POSTGRESQL)
  find_package(PQ REQUIRED)
elseif(NOT WITHOUT_POSTGRESQL)
  find_package(PQ)
endif()

louiz’'s avatar
louiz’ committed
139
140
141
142
143
144
#
## Set all the include directories, depending on what libraries are used
#
include_directories(${EXPAT_INCLUDE_DIRS})
include_directories(${ICONV_INCLUDE_DIRS})
include_directories(${LIBUUID_INCLUDE_DIRS})
145
146
147
148
149
150
if(SYSTEMD_FOUND)
  include_directories(${SYSTEMD_INCLUDE_DIRS})
endif()
if(BOTAN_FOUND)
  include_directories(SYSTEM ${BOTAN_INCLUDE_DIRS})
endif()
louiz’'s avatar
louiz’ committed
151
152
if(UDNS_FOUND)
  include_directories(${UDNS_INCLUDE_DIRS})
153
endif()
154

louiz’'s avatar
louiz’ committed
155
156
157
158
# To be able to include the config.h and other files generated by cmake
include_directories("${CMAKE_CURRENT_BINARY_DIR}/src/")
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/src/")
include_directories("${CMAKE_CURRENT_BINARY_DIR}/")
159

160
#
louiz’'s avatar
louiz’ committed
161
## Define all the modules
162
#
louiz’'s avatar
louiz’ committed
163
164
165
166
167

file(GLOB source_utils
        src/utils/*.[hc]pp)
add_library(utils OBJECT ${source_utils})

168
file(GLOB source_irc
louiz’'s avatar
louiz’ committed
169
170
        src/irc/*.[hc]pp)
add_library(irc OBJECT ${source_irc})
171

172
file(GLOB source_xmpp
louiz’'s avatar
louiz’ committed
173
174
        src/xmpp/*.[hc]pp)
add_library(xmpp OBJECT ${source_xmpp})
175

louiz’'s avatar
louiz’ committed
176
file(GLOB source_identd
louiz’'s avatar
louiz’ committed
177
178
        src/identd/*.[hc]pp)
add_library(identd OBJECT ${source_identd})
louiz’'s avatar
louiz’ committed
179

180
file(GLOB source_bridge
louiz’'s avatar
louiz’ committed
181
182
        src/bridge/*.[hc]pp)
add_library(bridge OBJECT ${source_bridge})
183

louiz’'s avatar
louiz’ committed
184
185
186
187
188
189
190
191
192
193
194
195
file(GLOB source_config
        src/config/*.[hc]pp)
add_library(config OBJECT ${source_config})

file(GLOB source_logger
        src/logger/*.[hc]pp)
add_library(logger OBJECT ${source_logger})

file(GLOB source_network
        src/network/*.[hc]pp)
add_library(network OBJECT ${source_network})

196
if(SQLITE3_FOUND OR PQ_FOUND)
louiz’'s avatar
louiz’ committed
197
198
199
  file(GLOB source_database
          src/database/*.[hc]pp)
  add_library(database OBJECT ${source_database})
200

201
202
203
204
205
206
  if(SQLITE3_FOUND)
    include_directories(database ${SQLITE3_INCLUDE_DIRS})
  endif()
  if(PQ_FOUND)
    include_directories(database ${PQ_INCLUDE_DIRS})
  endif()
louiz’'s avatar
louiz’ committed
207
208
209
210
  set(USE_DATABASE TRUE)
else()
  add_library(database OBJECT "")
endif()
louiz’'s avatar
louiz’ committed
211

212
#
louiz’'s avatar
louiz’ committed
213
## Define the executables
214
#
louiz’'s avatar
louiz’ committed
215
216
217
218
219
220
221
222
223
224
225
226
227
228

## main
add_executable(${PROJECT_NAME} src/main.cpp
        $<TARGET_OBJECTS:utils>
        $<TARGET_OBJECTS:config>
        $<TARGET_OBJECTS:logger>
        $<TARGET_OBJECTS:network>
        $<TARGET_OBJECTS:xmpp>
        $<TARGET_OBJECTS:bridge>
        $<TARGET_OBJECTS:irc>
        $<TARGET_OBJECTS:identd>
        $<TARGET_OBJECTS:database>)

## test_suite
louiz’'s avatar
louiz’ committed
229
230
file(GLOB source_tests
  tests/*.cpp)
louiz’'s avatar
louiz’ committed
231
232
233
234
235
236
237
238
239
240
add_executable(test_suite ${source_tests}
        $<TARGET_OBJECTS:utils>
        $<TARGET_OBJECTS:config>
        $<TARGET_OBJECTS:logger>
        $<TARGET_OBJECTS:network>
        $<TARGET_OBJECTS:xmpp>
        $<TARGET_OBJECTS:bridge>
        $<TARGET_OBJECTS:irc>
        $<TARGET_OBJECTS:identd>
        $<TARGET_OBJECTS:database>)
241
set_target_properties(test_suite PROPERTIES EXCLUDE_FROM_ALL TRUE)
242

louiz’'s avatar
louiz’ committed
243
244
245
#
## Link the executables with their libraries
#
246
target_link_libraries(${PROJECT_NAME}
247
        ${ICONV_LIBRARIES}
248
        ${LIBUUID_LIBRARIES}
249
        ${EXPAT_LIBRARY})
250
target_link_libraries(test_suite
251
        ${ICONV_LIBRARIES}
252
        ${LIBUUID_LIBRARIES}
253
        ${EXPAT_LIBRARY})
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
if(SYSTEMD_FOUND)
  target_link_libraries(${PROJECT_NAME} ${SYSTEMD_LIBRARIES})
  target_link_libraries(test_suite ${SYSTEMD_LIBRARIES})
endif()
if(BOTAN_FOUND)
  target_link_libraries(${PROJECT_NAME} ${BOTAN_LIBRARIES})
  target_link_libraries(test_suite ${BOTAN_LIBRARIES})
elseif(GCRYPT_FOUND)
  target_link_libraries(${PROJECT_NAME} ${GCRYPT_LIBRARIES})
  target_link_libraries(test_suite ${GCRYPT_LIBRARIES})
endif()
if(UDNS_FOUND)
  target_link_libraries(${PROJECT_NAME} ${UDNS_LIBRARIES})
  target_link_libraries(test_suite ${UDNS_LIBRARIES})
endif()
if(LIBIDN_FOUND)
  target_link_libraries(${PROJECT_NAME} ${LIBIDN_LIBRARIES})
  target_link_libraries(test_suite ${LIBIDN_LIBRARIES})
endif()
273
if(USE_DATABASE)
274
275
276
277
278
279
280
281
  if(SQLITE3_FOUND)
    target_link_libraries(${PROJECT_NAME} ${SQLITE3_LIBRARIES})
    target_link_libraries(test_suite ${SQLITE3_LIBRARIES})
  endif()
  if(PQ_FOUND)
    target_link_libraries(${PROJECT_NAME} ${PQ_LIBRARIES})
    target_link_libraries(test_suite ${PQ_LIBRARIES})
endif()
282
endif()
283

284
285
286
287
288
289
290
291
# Define a __FILENAME__ macro with the relative path (from the base project directory)
# of each source file
file(GLOB_RECURSE source_all src/*.[hc]pp tests/*.[hc]pp)
foreach(file ${source_all})
  file(RELATIVE_PATH shorter_file ${CMAKE_CURRENT_SOURCE_DIR} ${file})
  set_property(SOURCE ${file} APPEND PROPERTY COMPILE_DEFINITIONS __FILENAME__="${shorter_file}")
endforeach()

louiz’'s avatar
louiz’ committed
292
293
294
#
## Add a rule to download the catch unit test framework
#
louiz’'s avatar
louiz’ committed
295
296
include(ExternalProject)
ExternalProject_Add(catch
297
  GIT_REPOSITORY "https://lab.louiz.org/louiz/Catch.git"
louiz’'s avatar
louiz’ committed
298
299
300
301
302
  PREFIX "external"
  UPDATE_COMMAND ""
  CONFIGURE_COMMAND ""
  BUILD_COMMAND ""
  INSTALL_COMMAND ""
303
  )
304
set_target_properties(catch PROPERTIES EXCLUDE_FROM_ALL TRUE)
louiz’'s avatar
louiz’ committed
305
ExternalProject_Get_Property(catch SOURCE_DIR)
306
307
308
309
310
311
if(NOT EXISTS ${CMAKE_SOURCE_DIR}/tests/catch.hpp)
  target_include_directories(test_suite
    PUBLIC "${SOURCE_DIR}/include/"
    )
  add_dependencies(test_suite catch)
endif()
louiz’'s avatar
louiz’ committed
312
313
314
315

#
## Add some custom rules to launch the tests
#
louiz’'s avatar
louiz’ committed
316
add_custom_target(check COMMAND "test_suite"
317
  DEPENDS test_suite biboumi)
318
set_target_properties(check PROPERTIES EXCLUDE_FROM_ALL TRUE)
319
320
add_custom_target(e2e COMMAND "python3" "${CMAKE_CURRENT_SOURCE_DIR}/tests/end_to_end/"
  DEPENDS biboumi)
321
set_target_properties(e2e PROPERTIES EXCLUDE_FROM_ALL TRUE)
louiz’'s avatar
louiz’ committed
322
323
add_custom_target(e2e_valgrind COMMAND "E2E_BIBOUMI_SUPP_DIR=${CMAKE_CURRENT_SOURCE_DIR}/tests/end_to_end/" "E2E_BIBOUMI_VALGRIND=1" "python3" "${CMAKE_CURRENT_SOURCE_DIR}/tests/end_to_end/"
    DEPENDS biboumi)
louiz’'s avatar
louiz’ committed
324
if(CMAKE_BUILD_TYPE MATCHES Debug)
325
  include(CodeCoverage)
326
  SETUP_TARGET_FOR_COVERAGE(coverage_check
327
328
329
330
    ./test_suite
    coverage_test_suite)
  add_dependencies(coverage_check test_suite)

331
  SETUP_TARGET_FOR_COVERAGE(coverage_e2e
332
    python3
333
    coverage_e2e
334
335
    ${CMAKE_CURRENT_SOURCE_DIR}/tests/end_to_end/)
  add_dependencies(coverage_e2e biboumi)
336
337
338
339
340
341
342
343

  ADD_CUSTOM_TARGET(coverage
    COMMAND ${LCOV_PATH} -a coverage_e2e.info -a coverage_test_suite.info -o coverage_total.info

    COMMAND ${GENHTML_PATH} -o coverage_total coverage_total.info

    WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
    )
344
endif()
345
add_custom_target(everything DEPENDS test_suite biboumi)
louiz’'s avatar
louiz’ committed
346

louiz’'s avatar
louiz’ committed
347
348
349
#
## Install target
#
350
351
install(TARGETS ${PROJECT_NAME} RUNTIME                     DESTINATION bin)
install(FILES   ${MAN_PAGE}                                 DESTINATION share/man/man1         OPTIONAL COMPONENT documentation)
352
install(FILES   ${CMAKE_CURRENT_BINARY_DIR}/biboumi.service DESTINATION lib/systemd/system     COMPONENT init)
353
354
file(GLOB policy_files conf/*policy.txt)
install(FILES   ${policy_files}                             DESTINATION /etc/biboumi           COMPONENT configuration)
louiz’'s avatar
louiz’ committed
355
356
357
358
359

#
## Dist target
## Generate a release tarball from the git sources
#
360
add_custom_command(OUTPUT ${ARCHIVE_NAME}.tar.xz
361
  COMMAND git archive --prefix=${ARCHIVE_NAME}/ --format=tar HEAD^{tree}
362
363
364
365
366
367
368
          > ${CMAKE_CURRENT_BINARY_DIR}/${ARCHIVE_NAME}.tar
  # Append this specific file that is not part of the git repo
  COMMAND tar -rf ${CMAKE_CURRENT_BINARY_DIR}/${ARCHIVE_NAME}.tar -P ${SOURCE_DIR}/single_include/catch.hpp --xform 's|/.*/|${ARCHIVE_NAME}/tests/|g'
  # Remove a potential existing archive
  COMMAND rm -f ${CMAKE_CURRENT_BINARY_DIR}/${ARCHIVE_NAME}.tar.xz
  # Compress the archive
  COMMAND xz ${CMAKE_CURRENT_BINARY_DIR}/${ARCHIVE_NAME}.tar
369
  COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --cyan "${ARCHIVE_NAME}.tar.xz created."
370
371
  WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
  )
372
373
374
add_custom_target(dist
  DEPENDS ${ARCHIVE_NAME}.tar.xz
  DEPENDS catch)
375
376

add_custom_target(rpm
377
  DEPENDS dist
378
379
380
  COMMAND mkdir -p rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
  COMMAND rpmbuild --define "_topdir `pwd`/rpmbuild/" --define "_sourcedir `pwd`" -ba biboumi.spec
  )
381

louiz’'s avatar
louiz’ committed
382
383
384
#
## Set some variables that will be used in the cmake-generated files
#
385
386
set(SYSTEMD_SERVICE_TYPE_DOCSTRING "The value used as the Type= in the systemd unit file.")
set(WATCHDOG_SEC_DOCSTRING "The value used as WatchdogSec= in the systemd unit file.")
387
if(SYSTEMD_FOUND)
388
389
  set(SYSTEMD_SERVICE_TYPE "notify" CACHE STRING ${SYSTEMD_SERVICE_TYPE_DOCSTRING})
  set(WATCHDOG_SEC "20" CACHE STRING ${WATCHDOG_SEC_DOCSTRING})
390
else()
391
392
  set(SYSTEMD_SERVICE_TYPE "simple" CACHE STRING ${SYSTEMD_SERVICE_TYPE_DOCSTRING})
  set(WATCHDOG_SEC "" CACHE STRING ${WATCHDOG_SEC_DOCSTRING})
393
endif()
394
set(SERVICE_USER_DOCSTRING "The value used as the User= in the systemd unit file.")
395
if(NOT DEFINED SERVICE_USER)
396
  set(SERVICE_USER "nobody" CACHE STRING ${SERVICE_USER_DOCSTRING})
397
endif()
398
set(SERVICE_GROUP_DOCSTRING "The value used as the Group= in the systemd unit file.")
399
if(NOT DEFINED SERVICE_GROUP)
400
  set(SERVICE_GROUP "nobody" CACHE STRING ${SERVICE_GROUP_DOCSTRING})
401
endif()
402

louiz’'s avatar
louiz’ committed
403
# Force the format of the date output
404
set(ENV{LANG} "C")
405
406
execute_process(COMMAND "date" "+%a %b %d %Y" OUTPUT_VARIABLE RPM_DATE
                OUTPUT_STRIP_TRAILING_WHITESPACE)
407
unset(ENV{LANG})
408

louiz’'s avatar
louiz’ committed
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
set(POLLER_DOCSTRING "Choose the poller between POLL and EPOLL (Linux-only)")
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
  set(POLLER "EPOLL" CACHE STRING ${POLLER_DOCSTRING})
else()
  set(POLLER "POLL" CACHE STRING ${POLLER_DOCSTRING})
endif()
if((NOT ${POLLER} MATCHES "POLL") AND
(NOT ${POLLER} MATCHES "EPOLL"))
  message(FATAL_ERROR "POLLER must be either POLL or EPOLL")
endif()

#
## Check if we have std::get_time and put_time
#
include(CheckCXXSourceCompiles)

check_cxx_source_compiles("
  #include <iomanip>
  int main()
  { std::get_time(nullptr, \"\"); }"
        HAS_GET_TIME)

mark_as_advanced(HAS_GET_TIME)

check_cxx_source_compiles("
  #include <iomanip>
  int main()
  { std::put_time(nullptr, \"\"); }"
        HAS_PUT_TIME)

mark_as_advanced(HAS_PUT_TIME)

configure_file(unit/biboumi.service.cmake biboumi.service)
442
configure_file(packaging/biboumi.spec.cmake biboumi.spec)
443
configure_file(src/biboumi.h.cmake src/biboumi.h)