CMakeLists.txt 13.6 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 18 19
find_library(LIBASAN NAMES asan libasan.so.3 libasan.so.2 libasan.so.1)
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})

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

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

208
#
louiz’'s avatar
louiz’ committed
209
## Define the executables
210
#
louiz’'s avatar
louiz’ committed
211 212 213 214 215 216 217 218 219 220 221 222 223 224

## 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
225 226
file(GLOB source_tests
  tests/*.cpp)
louiz’'s avatar
louiz’ committed
227 228 229 230 231 232 233 234 235 236
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>)
237
set_target_properties(test_suite PROPERTIES EXCLUDE_FROM_ALL TRUE)
238

louiz’'s avatar
louiz’ committed
239 240 241
#
## Link the executables with their libraries
#
242
target_link_libraries(${PROJECT_NAME}
243
        ${ICONV_LIBRARIES}
244
        ${LIBUUID_LIBRARIES}
245
        ${EXPAT_LIBRARY})
246
target_link_libraries(test_suite
247
        ${ICONV_LIBRARIES}
248
        ${LIBUUID_LIBRARIES}
249
        ${EXPAT_LIBRARY})
250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268
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()
269
if(USE_DATABASE)
louiz’'s avatar
louiz’ committed
270
  target_link_libraries(${PROJECT_NAME} ${SQLITE3_LIBRARIES})
louiz’'s avatar
louiz’ committed
271
  target_link_libraries(${PROJECT_NAME} ${PQ_LIBRARIES})
louiz’'s avatar
louiz’ committed
272
  target_link_libraries(test_suite ${SQLITE3_LIBRARIES})
louiz’'s avatar
louiz’ committed
273
  target_link_libraries(test_suite ${PQ_LIBRARIES})
274
endif()
275

276 277 278 279 280 281 282 283
# 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
284 285 286
#
## Add a rule to download the catch unit test framework
#
louiz’'s avatar
louiz’ committed
287 288
include(ExternalProject)
ExternalProject_Add(catch
289
  GIT_REPOSITORY "https://lab.louiz.org/louiz/Catch.git"
louiz’'s avatar
louiz’ committed
290 291 292 293 294
  PREFIX "external"
  UPDATE_COMMAND ""
  CONFIGURE_COMMAND ""
  BUILD_COMMAND ""
  INSTALL_COMMAND ""
295
  )
296
set_target_properties(catch PROPERTIES EXCLUDE_FROM_ALL TRUE)
louiz’'s avatar
louiz’ committed
297
ExternalProject_Get_Property(catch SOURCE_DIR)
298 299 300 301 302 303
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
304 305 306 307

#
## Add some custom rules to launch the tests
#
louiz’'s avatar
louiz’ committed
308
add_custom_target(check COMMAND "test_suite"
309
  DEPENDS test_suite biboumi)
310
set_target_properties(check PROPERTIES EXCLUDE_FROM_ALL TRUE)
311 312
add_custom_target(e2e COMMAND "python3" "${CMAKE_CURRENT_SOURCE_DIR}/tests/end_to_end/"
  DEPENDS biboumi)
313
set_target_properties(e2e PROPERTIES EXCLUDE_FROM_ALL TRUE)
louiz’'s avatar
louiz’ committed
314 315
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
316
if(CMAKE_BUILD_TYPE MATCHES Debug)
317
  include(CodeCoverage)
318
  SETUP_TARGET_FOR_COVERAGE(coverage_check
319 320 321 322
    ./test_suite
    coverage_test_suite)
  add_dependencies(coverage_check test_suite)

323
  SETUP_TARGET_FOR_COVERAGE(coverage_e2e
324
    python3
325
    coverage_e2e
326 327
    ${CMAKE_CURRENT_SOURCE_DIR}/tests/end_to_end/)
  add_dependencies(coverage_e2e biboumi)
328 329 330 331 332 333 334 335

  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}
    )
336
endif()
337
add_custom_target(everything DEPENDS test_suite biboumi)
louiz’'s avatar
louiz’ committed
338

louiz’'s avatar
louiz’ committed
339 340 341
#
## Install target
#
342 343
install(TARGETS ${PROJECT_NAME} RUNTIME                     DESTINATION bin)
install(FILES   ${MAN_PAGE}                                 DESTINATION share/man/man1         OPTIONAL COMPONENT documentation)
344
install(FILES   ${CMAKE_CURRENT_BINARY_DIR}/biboumi.service DESTINATION lib/systemd/system     COMPONENT init)
345 346
file(GLOB policy_files conf/*policy.txt)
install(FILES   ${policy_files}                             DESTINATION /etc/biboumi           COMPONENT configuration)
louiz’'s avatar
louiz’ committed
347 348 349 350 351

#
## Dist target
## Generate a release tarball from the git sources
#
352
add_custom_command(OUTPUT ${ARCHIVE_NAME}.tar.xz
353
  COMMAND git archive --prefix=${ARCHIVE_NAME}/ --format=tar HEAD^{tree}
354 355 356 357 358 359 360
          > ${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
361
  COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --cyan "${ARCHIVE_NAME}.tar.xz created."
362 363
  WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
  )
364 365 366
add_custom_target(dist
  DEPENDS ${ARCHIVE_NAME}.tar.xz
  DEPENDS catch)
367 368

add_custom_target(rpm
369
  DEPENDS dist
370 371 372
  COMMAND mkdir -p rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
  COMMAND rpmbuild --define "_topdir `pwd`/rpmbuild/" --define "_sourcedir `pwd`" -ba biboumi.spec
  )
373

louiz’'s avatar
louiz’ committed
374 375 376
#
## Set some variables that will be used in the cmake-generated files
#
377 378
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.")
379
if(SYSTEMD_FOUND)
380 381
  set(SYSTEMD_SERVICE_TYPE "notify" CACHE STRING ${SYSTEMD_SERVICE_TYPE_DOCSTRING})
  set(WATCHDOG_SEC "20" CACHE STRING ${WATCHDOG_SEC_DOCSTRING})
382
else()
383 384
  set(SYSTEMD_SERVICE_TYPE "simple" CACHE STRING ${SYSTEMD_SERVICE_TYPE_DOCSTRING})
  set(WATCHDOG_SEC "" CACHE STRING ${WATCHDOG_SEC_DOCSTRING})
385
endif()
386
set(SERVICE_USER_DOCSTRING "The value used as the User= in the systemd unit file.")
387
if(NOT DEFINED SERVICE_USER)
388
  set(SERVICE_USER "nobody" CACHE STRING ${SERVICE_USER_DOCSTRING})
389
endif()
390
set(SERVICE_GROUP_DOCSTRING "The value used as the Group= in the systemd unit file.")
391
if(NOT DEFINED SERVICE_GROUP)
392
  set(SERVICE_GROUP "nobody" CACHE STRING ${SERVICE_GROUP_DOCSTRING})
393
endif()
394

louiz’'s avatar
louiz’ committed
395
# Force the format of the date output
396
set(ENV{LANG} "C")
397 398
execute_process(COMMAND "date" "+%a %b %d %Y" OUTPUT_VARIABLE RPM_DATE
                OUTPUT_STRIP_TRAILING_WHITESPACE)
399
unset(ENV{LANG})
400

louiz’'s avatar
louiz’ committed
401 402 403 404 405 406 407 408 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
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)
434
configure_file(packaging/biboumi.spec.cmake biboumi.spec)
435
configure_file(src/biboumi.h.cmake src/biboumi.h)