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

project(biboumi)

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

louiz’'s avatar
louiz’ committed
9 10 11
#
## Find optional instrumentation libraries that will be used in debug only
#
12 13 14
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
15 16 17
#
## Set various debug flags (instrumentation libs, coverage, …)
#
louiz’'s avatar
louiz’ committed
18
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y -pedantic -Wall -Wextra")
19 20 21
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
  set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fprofile-arcs -ftest-coverage --coverage")
endif()
22 23 24 25 26 27 28
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()

29
#
louiz’'s avatar
louiz’ committed
30
## Set the software version, archive name, RPM name etc
31
#
louiz’'s avatar
louiz’ committed
32
set(ARCHIVE_NAME ${CMAKE_PROJECT_NAME}-${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR})
33 34
set(RPM_VERSION ${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR})

louiz’'s avatar
louiz’ committed
35
if(${PROJECT_NAME}_VERSION_SUFFIX MATCHES ".+")
36
  set(ARCHIVE_NAME ${ARCHIVE_NAME}${${PROJECT_NAME}_VERSION_SUFFIX})
37
  set(RPM_VERSION ${RPM_VERSION}${${PROJECT_NAME}_VERSION_SUFFIX})
louiz’'s avatar
louiz’ committed
38 39 40
endif()

if(${PROJECT_NAME}_VERSION_SUFFIX MATCHES "^~dev$")
41 42 43
  # 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
44
  if(GIT_FOUND AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
45 46 47 48 49
    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})")
50
      set(ARCHIVE_NAME ${ARCHIVE_NAME}${GIT_REVISION})
51
      set(RPM_VERSION ${RPM_VERSION}${GIT_REVISION})
52 53 54 55
    endif()
  endif()
endif()

56
set(SOFTWARE_VERSION
57 58
  ${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}${${PROJECT_NAME}_VERSION_SUFFIX})

59
#
louiz’'s avatar
louiz’ committed
60
## The rule that generates the documentation
61
#
62 63
execute_process(COMMAND "date" "+%Y-%m-%d" OUTPUT_VARIABLE DOC_DATE
                OUTPUT_STRIP_TRAILING_WHITESPACE)
64
set(MAN_PAGE ${CMAKE_CURRENT_BINARY_DIR}/doc/${PROJECT_NAME}.1)
65
set(DOC_PAGE ${CMAKE_CURRENT_SOURCE_DIR}/doc/${PROJECT_NAME}.1.rst)
66 67 68 69 70 71 72 73 74 75 76 77 78 79
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()
80
endif()
81
mark_as_advanced(PANDOC_EXECUTABLE)
82

louiz’'s avatar
louiz’ committed
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
#
## 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)
98 99
endif()

louiz’'s avatar
louiz’ committed
100 101 102 103 104
if(WITH_SYSTEMD)
  find_package(SYSTEMD REQUIRED)
elseif(NOT WITHOUT_SYSTEMD)
  find_package(SYSTEMD)
endif()
105

louiz’'s avatar
louiz’ committed
106 107 108 109
if(WITH_BOTAN)
  find_package(BOTAN REQUIRED)
elseif(NOT WITHOUT_BOTAN)
  find_package(BOTAN)
110 111
endif()

louiz’'s avatar
louiz’ committed
112 113 114
if(NOT BOTAN_FOUND)
  find_package(GCRYPT REQUIRED)
endif()
115

louiz’'s avatar
louiz’ committed
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
if(WITH_UDNS)
  find_package(UDNS REQUIRED)
elseif(NOT WITHOUT_UDNS)
  find_package(UDNS)
endif()

if(WITH_LITESQL)
  find_package(LITESQL REQUIRED)
elseif(NOT WITHOUT_LITESQL)
  find_package(LITESQL)
endif()

#
## 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})
134 135 136 137 138 139
if(SYSTEMD_FOUND)
  include_directories(${SYSTEMD_INCLUDE_DIRS})
endif()
if(BOTAN_FOUND)
  include_directories(SYSTEM ${BOTAN_INCLUDE_DIRS})
endif()
louiz’'s avatar
louiz’ committed
140 141
if(UDNS_FOUND)
  include_directories(${UDNS_INCLUDE_DIRS})
142
endif()
143

louiz’'s avatar
louiz’ committed
144 145 146 147
# 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}/")
148

149
#
louiz’'s avatar
louiz’ committed
150
## Define all the modules
151
#
louiz’'s avatar
louiz’ committed
152 153 154 155

file(GLOB source_utils
        src/utils/*.[hc]pp)
add_library(utils OBJECT ${source_utils})
156
add_dependencies(utils database)
louiz’'s avatar
louiz’ committed
157

158
file(GLOB source_irc
louiz’'s avatar
louiz’ committed
159 160
        src/irc/*.[hc]pp)
add_library(irc OBJECT ${source_irc})
161
add_dependencies(irc database)
162

163
file(GLOB source_xmpp
louiz’'s avatar
louiz’ committed
164 165
        src/xmpp/*.[hc]pp)
add_library(xmpp OBJECT ${source_xmpp})
166
add_dependencies(xmpp database)
167

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

172
file(GLOB source_bridge
louiz’'s avatar
louiz’ committed
173 174
        src/bridge/*.[hc]pp)
add_library(bridge OBJECT ${source_bridge})
175
add_dependencies(bridge database)
176

louiz’'s avatar
louiz’ committed
177 178 179 180 181 182 183 184 185 186 187
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})
188
add_dependencies(network database)
louiz’'s avatar
louiz’ committed
189 190 191 192 193 194 195 196 197 198 199 200

if(LITESQL_FOUND)
  LITESQL_GENERATE_CPP("database/database.xml"
          "biboudb"
          LITESQL_GENERATED_SOURCES)

  add_library(database OBJECT src/database/database.cpp
          ${LITESQL_GENERATED_SOURCES})
  set(USE_DATABASE TRUE)
else()
  add_library(database OBJECT "")
endif()
louiz’'s avatar
louiz’ committed
201

202
#
louiz’'s avatar
louiz’ committed
203
## Define the executables
204
#
louiz’'s avatar
louiz’ committed
205 206 207 208 209 210 211 212 213 214 215 216 217 218

## 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
219 220
file(GLOB source_tests
  tests/*.cpp)
louiz’'s avatar
louiz’ committed
221 222 223 224 225 226 227 228 229 230
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>)
231

louiz’'s avatar
louiz’ committed
232 233 234
#
## Link the executables with their libraries
#
235
target_link_libraries(${PROJECT_NAME}
236
        ${ICONV_LIBRARIES}
237
        ${LIBUUID_LIBRARIES}
238
        ${EXPAT_LIBRARY})
239
target_link_libraries(test_suite
240
        ${ICONV_LIBRARIES}
241
        ${LIBUUID_LIBRARIES}
242
        ${EXPAT_LIBRARY})
243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
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()
262
if(USE_DATABASE)
263 264
  target_link_libraries(${PROJECT_NAME} ${LITESQL_LIBRARIES})
  target_link_libraries(test_suite ${LITESQL_LIBRARIES})
265
endif()
266

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

#
## Add some custom rules to launch the tests
#
louiz’'s avatar
louiz’ committed
299
add_custom_target(check COMMAND "test_suite"
300
  DEPENDS test_suite biboumi)
301 302
add_custom_target(e2e COMMAND "python3" "${CMAKE_CURRENT_SOURCE_DIR}/tests/end_to_end/"
  DEPENDS biboumi)
louiz’'s avatar
louiz’ committed
303 304
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
305
if(CMAKE_BUILD_TYPE MATCHES Debug)
306
  include(CodeCoverage)
307
  SETUP_TARGET_FOR_COVERAGE(coverage_check
308 309 310 311
    ./test_suite
    coverage_test_suite)
  add_dependencies(coverage_check test_suite)

312
  SETUP_TARGET_FOR_COVERAGE(coverage_e2e
313
    python3
314
    coverage_e2e
315 316
    ${CMAKE_CURRENT_SOURCE_DIR}/tests/end_to_end/)
  add_dependencies(coverage_e2e biboumi)
317 318 319 320 321 322 323 324

  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}
    )
325
endif()
louiz’'s avatar
louiz’ committed
326

louiz’'s avatar
louiz’ committed
327 328 329
#
## Install target
#
330 331
install(TARGETS ${PROJECT_NAME} RUNTIME                     DESTINATION bin)
install(FILES   ${MAN_PAGE}                                 DESTINATION share/man/man1         OPTIONAL COMPONENT documentation)
332
install(FILES   ${CMAKE_CURRENT_BINARY_DIR}/biboumi.service DESTINATION lib/systemd/system     COMPONENT init)
333
install(FILES   conf/biboumi.cfg                            DESTINATION /etc/biboumi           COMPONENT configuration)
louiz’'s avatar
louiz’ committed
334 335 336 337 338

#
## Dist target
## Generate a release tarball from the git sources
#
339
add_custom_command(OUTPUT ${ARCHIVE_NAME}.tar.xz
340
  COMMAND git archive --prefix=${ARCHIVE_NAME}/ --format=tar HEAD^{tree}
341 342 343 344 345 346 347
          > ${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
348
  COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --cyan "${ARCHIVE_NAME}.tar.xz created."
349 350
  WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
  )
351 352 353
add_custom_target(dist
  DEPENDS ${ARCHIVE_NAME}.tar.xz
  DEPENDS catch)
354 355

add_custom_target(rpm
356
  DEPENDS dist
357 358 359
  COMMAND mkdir -p rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
  COMMAND rpmbuild --define "_topdir `pwd`/rpmbuild/" --define "_sourcedir `pwd`" -ba biboumi.spec
  )
360

louiz’'s avatar
louiz’ committed
361 362 363
#
## Set some variables that will be used in the cmake-generated files
#
364 365
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.")
366
if(SYSTEMD_FOUND)
367 368
  set(SYSTEMD_SERVICE_TYPE "notify" CACHE STRING ${SYSTEMD_SERVICE_TYPE_DOCSTRING})
  set(WATCHDOG_SEC "20" CACHE STRING ${WATCHDOG_SEC_DOCSTRING})
369
else()
370 371
  set(SYSTEMD_SERVICE_TYPE "simple" CACHE STRING ${SYSTEMD_SERVICE_TYPE_DOCSTRING})
  set(WATCHDOG_SEC "" CACHE STRING ${WATCHDOG_SEC_DOCSTRING})
372
endif()
373
set(SERVICE_USER_DOCSTRING "The value used as the User= in the systemd unit file.")
374
if(NOT DEFINED SERVICE_USER)
375
  set(SERVICE_USER "nobody" CACHE STRING ${SERVICE_USER_DOCSTRING})
376
endif()
377
set(SERVICE_GROUP_DOCSTRING "The value used as the Group= in the systemd unit file.")
378
if(NOT DEFINED SERVICE_GROUP)
379
  set(SERVICE_GROUP "nobody" CACHE STRING ${SERVICE_GROUP_DOCSTRING})
380
endif()
381

louiz’'s avatar
louiz’ committed
382
# Force the format of the date output
383
set(ENV{LANG} "C")
384 385
execute_process(COMMAND "date" "+%a %b %d %Y" OUTPUT_VARIABLE RPM_DATE
                OUTPUT_STRIP_TRAILING_WHITESPACE)
386
unset(ENV{LANG})
387

louiz’'s avatar
louiz’ committed
388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
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)
421
configure_file(packaging/biboumi.spec.cmake biboumi.spec)
louiz’'s avatar
louiz’ committed
422
configure_file(biboumi.h.cmake src/biboumi.h)