cmake_minimum_required(VERSION 3.0) project(biboumi) set(${PROJECT_NAME}_VERSION_MAJOR 5) set(${PROJECT_NAME}_VERSION_MINOR 0) set(${PROJECT_NAME}_VERSION_SUFFIX "~dev") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++1y -pedantic -Wall -Wextra") if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fprofile-arcs -ftest-coverage --coverage") endif() # ## Look for external libraries # set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/Modules/") # ## Get the software version # set(ARCHIVE_NAME ${CMAKE_PROJECT_NAME}-${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}) set(RPM_VERSION ${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}) if(${PROJECT_NAME}_VERSION_SUFFIX MATCHES ".+") set(ARCHIVE_NAME ${ARCHIVE_NAME}${${PROJECT_NAME}_VERSION_SUFFIX}) set(RPM_VERSION ${RPM_VERSION}${${PROJECT_NAME}_VERSION_SUFFIX}) endif() if(${PROJECT_NAME}_VERSION_SUFFIX MATCHES "^~dev$") # If we are on a dev version, append the hash of the current git HEAD to # the version include(FindGit) if(GIT_FOUND AND EXISTS "${CMAKE_SOURCE_DIR}/.git") 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})") set(ARCHIVE_NAME ${ARCHIVE_NAME}${GIT_REVISION}) set(RPM_VERSION ${RPM_VERSION}${GIT_REVISION}) endif() endif() endif() set(SOFTWARE_VERSION ${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}${${PROJECT_NAME}_VERSION_SUFFIX}) include(CheckFunctionExists) check_function_exists(ppoll HAVE_PPOLL_FUNCTION) # 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}/") # ## Documentation # execute_process(COMMAND "date" "+%Y-%m-%d" OUTPUT_VARIABLE DOC_DATE OUTPUT_STRIP_TRAILING_WHITESPACE) set(MAN_PAGE ${CMAKE_CURRENT_BINARY_DIR}/doc/${PROJECT_NAME}.1) set(DOC_PAGE ${CMAKE_CURRENT_SOURCE_DIR}/doc/${PROJECT_NAME}.1.rst) 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() endif() mark_as_advanced(PANDOC_EXECUTABLE) # Look for litesql and enable the database if found if(WITH_LITESQL) find_package(LITESQL REQUIRED) elseif(NOT WITHOUT_LITESQL) find_package(LITESQL) endif() if(LITESQL_FOUND) LITESQL_GENERATE_CPP("database/database.xml" "biboudb" LITESQL_GENERATED_SOURCES) add_library(database STATIC src/database/database.cpp ${LITESQL_GENERATED_SOURCES}) target_link_libraries(database ${LITESQL_LIBRARIES} utils) if(BOTAN_FOUND) target_link_libraries(database ${BOTAN_LIBRARIES}) endif() set(USE_DATABASE TRUE) endif() add_subdirectory("louloulibs") include_directories("louloulibs") include_directories(${EXPAT_INCLUDE_DIRS}) include_directories(${ICONV_INCLUDE_DIRS}) include_directories(${LIBUUID_INCLUDE_DIRS}) # If they are found in louloulibs CMakeLists.txt, we inherite these values if(SYSTEMD_FOUND) include_directories(${SYSTEMD_INCLUDE_DIRS}) endif() if(BOTAN_FOUND) include_directories(SYSTEM ${BOTAN_INCLUDE_DIRS}) endif() if(CARES_FOUND) include_directories(${CARES_INCLUDE_DIRS}) endif() # ## utils # file(GLOB source_src_utils src/utils/*.[hc]pp) # Todo, switch to target_sources(utils) when we go cmake >=3.1 only add_library(src_utils STATIC ${source_src_utils}) target_link_libraries(src_utils logger config) if(USE_DATABASE) target_link_libraries(src_utils database) endif() # ## irclib # file(GLOB source_irc src/irc/*.[hc]pp) add_library(irc STATIC ${source_irc}) target_link_libraries(irc network utils logger) # ## xmpp # file(GLOB source_xmpp src/xmpp/*.[hc]pp) add_library(xmpp STATIC ${source_xmpp}) target_link_libraries(xmpp xmpplib bridge network utils src_utils logger) if(USE_DATABASE) target_link_libraries(xmpp database) target_link_libraries(irc database) endif() # ## identd # file(GLOB source_identd src/identd/*.[hc]pp) add_library(identd STATIC ${source_identd}) target_link_libraries(identd bridge network utils src_utils logger) # ## bridge # file(GLOB source_bridge src/bridge/*.[hc]pp) add_library(bridge STATIC ${source_bridge}) target_link_libraries(bridge xmpp irc utils logger) # ## Main executable # add_executable(${PROJECT_NAME} src/main.cpp) target_link_libraries(${PROJECT_NAME} xmpp irc bridge utils src_utils identd config) if(SYSTEMD_FOUND) target_link_libraries(xmpp ${SYSTEMD_LIBRARIES}) endif() # ## Tests # file(GLOB source_tests tests/*.cpp) add_executable(test_suite EXCLUDE_FROM_ALL ${source_tests}) target_link_libraries(test_suite xmpplib xmpp irc bridge utils config logger network) if(USE_DATABASE) target_link_libraries(test_suite database) endif() # 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() include(ExternalProject) ExternalProject_Add(catch GIT_REPOSITORY "https://lab.louiz.org/louiz/Catch.git" PREFIX "external" UPDATE_COMMAND "" CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" ) set_target_properties(catch PROPERTIES EXCLUDE_FROM_ALL TRUE) ExternalProject_Get_Property(catch SOURCE_DIR) if(NOT EXISTS ${CMAKE_SOURCE_DIR}/tests/catch.hpp) target_include_directories(test_suite PUBLIC "${SOURCE_DIR}/include/" ) add_dependencies(test_suite catch) endif() add_custom_target(check COMMAND "test_suite" DEPENDS test_suite biboumi) add_custom_target(e2e COMMAND "python3" "${CMAKE_CURRENT_SOURCE_DIR}/tests/end_to_end/" DEPENDS biboumi) 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) # ## Code coverage # if(CMAKE_BUILD_TYPE MATCHES Debug) include(CodeCoverage) SETUP_TARGET_FOR_COVERAGE(coverage test_suite coverage ) SETUP_TARGET_FOR_COVERAGE(coverage_e2e make coverage_e2e e2e) endif() # ## Install target # install(TARGETS ${PROJECT_NAME} RUNTIME DESTINATION bin) install(FILES ${MAN_PAGE} DESTINATION share/man/man1 OPTIONAL COMPONENT documentation) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/biboumi.service DESTINATION lib/systemd/system COMPONENT init) install(FILES conf/biboumi.cfg DESTINATION /etc/biboumi COMPONENT configuration) # ## Dist target ## Generate a release tarball from the git sources # add_custom_command(OUTPUT ${ARCHIVE_NAME}.tar.xz COMMAND git archive --prefix=${ARCHIVE_NAME}/ --format=tar HEAD^{tree} > ${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 COMMAND ${CMAKE_COMMAND} -E cmake_echo_color --cyan "${ARCHIVE_NAME}.tar.xz created." WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} ) add_custom_target(dist DEPENDS ${ARCHIVE_NAME}.tar.xz DEPENDS catch) add_custom_target(rpm DEPENDS dist COMMAND mkdir -p rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS} COMMAND rpmbuild --define "_topdir `pwd`/rpmbuild/" --define "_sourcedir `pwd`" -ba biboumi.spec ) if(BOTAN_FOUND) set(STR_WITH_BOTAN "Botan: yes") else() set(STR_WITH_BOTAN "Botan: no") endif() if(CARES_FOUND) set(STR_WITH_CARES "c-ares: yes") else() set(STR_WITH_CARES "c-ares: no") endif() add_custom_target(PrintBuildParameters ALL ${CMAKE_COMMAND} -E cmake_echo_color --cyan "Compiling ${PROJECT_NAME} with ${STR_WITH_BOTAN}, ${STR_WITH_CARES}") configure_file(biboumi.h.cmake src/biboumi.h) 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.") if(SYSTEMD_FOUND) set(SYSTEMD_SERVICE_TYPE "notify" CACHE STRING ${SYSTEMD_SERVICE_TYPE_DOCSTRING}) set(WATCHDOG_SEC "20" CACHE STRING ${WATCHDOG_SEC_DOCSTRING}) else() set(SYSTEMD_SERVICE_TYPE "simple" CACHE STRING ${SYSTEMD_SERVICE_TYPE_DOCSTRING}) set(WATCHDOG_SEC "" CACHE STRING ${WATCHDOG_SEC_DOCSTRING}) endif() set(SERVICE_USER_DOCSTRING "The value used as the User= in the systemd unit file.") if(NOT DEFINED SERVICE_USER) set(SERVICE_USER "nobody" CACHE STRING ${SERVICE_USER_DOCSTRING}) endif() set(SERVICE_GROUP_DOCSTRING "The value used as the Group= in the systemd unit file.") if(NOT DEFINED SERVICE_GROUP) set(SERVICE_GROUP "nobody" CACHE STRING ${SERVICE_GROUP_DOCSTRING}) endif() configure_file(unit/biboumi.service.cmake biboumi.service) # The date MUST be in english format set(ENV{LANG} "en_US.utf-8") execute_process(COMMAND "date" "+%a %b %d %Y" OUTPUT_VARIABLE RPM_DATE OUTPUT_STRIP_TRAILING_WHITESPACE) unset(ENV{LANG}) configure_file(packaging/biboumi.spec.cmake biboumi.spec)