CMakeLists.txt 12.9 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 156

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

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

161
file(GLOB source_xmpp
louiz’'s avatar
louiz’ committed
162 163
        src/xmpp/*.[hc]pp)
add_library(xmpp OBJECT ${source_xmpp})
164

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

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

louiz’'s avatar
louiz’ committed
173 174 175 176 177 178 179 180 181 182 183 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})

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
196

197
#
louiz’'s avatar
louiz’ committed
198
## Define the executables
199
#
louiz’'s avatar
louiz’ committed
200 201 202 203 204 205 206 207 208 209 210 211 212 213

## 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
214 215
file(GLOB source_tests
  tests/*.cpp)
louiz’'s avatar
louiz’ committed
216 217 218 219 220 221 222 223 224 225
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>)
226

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

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

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

307
  SETUP_TARGET_FOR_COVERAGE(coverage_e2e
308
    python3
309
    coverage_e2e
310 311
    ${CMAKE_CURRENT_SOURCE_DIR}/tests/end_to_end/)
  add_dependencies(coverage_e2e biboumi)
312 313 314 315 316 317 318 319

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

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

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

add_custom_target(rpm
351
  DEPENDS dist
352 353 354
  COMMAND mkdir -p rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
  COMMAND rpmbuild --define "_topdir `pwd`/rpmbuild/" --define "_sourcedir `pwd`" -ba biboumi.spec
  )
355

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

louiz’'s avatar
louiz’ committed
377
# Force the format of the date output
378
set(ENV{LANG} "C")
379 380
execute_process(COMMAND "date" "+%a %b %d %Y" OUTPUT_VARIABLE RPM_DATE
                OUTPUT_STRIP_TRAILING_WHITESPACE)
381
unset(ENV{LANG})
382

louiz’'s avatar
louiz’ committed
383 384 385 386 387 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
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)
416
configure_file(packaging/biboumi.spec.cmake biboumi.spec)
louiz’'s avatar
louiz’ committed
417
configure_file(biboumi.h.cmake src/biboumi.h)