Commit 02844e598f7b93c7b40eeeb8da7b5b37b29980a0
1 parent
3894f4d8
Added test to library
Showing
28 changed files
with
1773 additions
and
0 deletions
.gitignore
0 → 100644
| 1 | +/build/ | ... | ... |
CMakeLists.txt
0 → 100644
| 1 | +cmake_minimum_required(VERSION 3.30) | |
| 2 | +project(daemonbase VERSION 0.1 LANGUAGES CXX) | |
| 3 | +include_guard(GLOBAL) | |
| 4 | + | |
| 5 | +if(EXISTS ${CMAKE_SOURCE_DIR}/cmake) | |
| 6 | + # Use the cmake directives for compilers etc... | |
| 7 | + LIST(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake) | |
| 8 | +else() | |
| 9 | + message("Cmake source dir : ${CMAKE_SOURCE_DIR}") | |
| 10 | +endif() | |
| 11 | + | |
| 12 | +include_directories( SYSTEM | |
| 13 | + ${CMAKE_CURRENT_SOURCE_DIR}/include | |
| 14 | +) | |
| 15 | + | |
| 16 | +include(compiler) | |
| 17 | + | |
| 18 | +set(SRC_LIST | |
| 19 | + ${CMAKE_CURRENT_SOURCE_DIR}/include/daemonbase.h | |
| 20 | + ${CMAKE_CURRENT_SOURCE_DIR}/include/daemonconfig.h | |
| 21 | + ${CMAKE_CURRENT_SOURCE_DIR}/include/daemonlog.h | |
| 22 | +) | |
| 23 | + | |
| 24 | +include(library) | |
| 25 | +add_libraries() | |
| 26 | + | |
| 27 | +include(installation) | |
| 28 | +install_component() | |
| 29 | + | |
| 30 | +include(packaging) | |
| 31 | +package_component() | |
| 32 | + | |
| 33 | +link_directories( | |
| 34 | + ${CMAKE_BINARY_DIR}/lib | |
| 35 | +) | |
| 36 | + | |
| 37 | +set_target_properties(${PROJECT_NAME} PROPERTIES LINKER_LANGUAGE CXX) | |
| 38 | + | |
| 39 | +add_subdirectory(test) | |
| 0 | 40 | \ No newline at end of file | ... | ... |
cmake/COPYING.OSDEV
0 → 100644
| 1 | +/* **************************************************************************** | |
| 2 | + * Copyright 2019 Open Systems Development BV * | |
| 3 | + * * | |
| 4 | + * Permission is hereby granted, free of charge, to any person obtaining a * | |
| 5 | + * copy of this software and associated documentation files (the "Software"), * | |
| 6 | + * to deal in the Software without restriction, including without limitation * | |
| 7 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, * | |
| 8 | + * and/or sell copies of the Software, and to permit persons to whom the * | |
| 9 | + * Software is furnished to do so, subject to the following conditions: * | |
| 10 | + * * | |
| 11 | + * The above copyright notice and this permission notice shall be included in * | |
| 12 | + * all copies or substantial portions of the Software. * | |
| 13 | + * * | |
| 14 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * | |
| 15 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * | |
| 16 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * | |
| 17 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * | |
| 18 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * | |
| 19 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * | |
| 20 | + * DEALINGS IN THE SOFTWARE. * | |
| 21 | + * ***************************************************************************/ | |
| 0 | 22 | \ No newline at end of file | ... | ... |
cmake/FindGMock.cmake
0 → 100644
| 1 | +#.rst: | |
| 2 | +# FindGMock | |
| 3 | +# --------- | |
| 4 | +# | |
| 5 | +# Locate the Google C++ Mocking Framework. | |
| 6 | +# | |
| 7 | +# Defines the following variables: | |
| 8 | +# | |
| 9 | +# :: | |
| 10 | +# | |
| 11 | +# GMOCK_FOUND - Found the Google Testing framework | |
| 12 | +# GMOCK_INCLUDE_DIRS - Include directories | |
| 13 | +# | |
| 14 | +# | |
| 15 | +# | |
| 16 | +# Also defines the gmock source path | |
| 17 | +# | |
| 18 | +# :: | |
| 19 | +# | |
| 20 | +# GMOCK_SOURCE_DIR - directory containing the gmock sources | |
| 21 | +# | |
| 22 | +# | |
| 23 | +# | |
| 24 | +# Accepts the following variables as input: | |
| 25 | +# | |
| 26 | +# :: | |
| 27 | +# | |
| 28 | +# GMOCK_ROOT - (as a CMake or environment variable) | |
| 29 | +# The root directory of the gmock install prefix | |
| 30 | +# | |
| 31 | +# | |
| 32 | +# | |
| 33 | +# | |
| 34 | +# Example Usage: | |
| 35 | +# | |
| 36 | +# :: | |
| 37 | +# | |
| 38 | +# enable_testing() | |
| 39 | +# find_package(GMock REQUIRED) | |
| 40 | +# include_directories(${GMOCK_INCLUDE_DIRS}) | |
| 41 | +# | |
| 42 | +# | |
| 43 | +# | |
| 44 | +# :: | |
| 45 | +# | |
| 46 | +# add_executable(foo ${GMOCK_SOURCE_DIR}/gmock-all.cc foo.cc) | |
| 47 | +# target_link_libraries(foo) | |
| 48 | +# | |
| 49 | +# | |
| 50 | + | |
| 51 | +find_path(GMOCK_INCLUDE_DIR gmock/gmock.h | |
| 52 | + HINTS | |
| 53 | + $ENV{GMOCK_ROOT}/include | |
| 54 | + ${GMOCK_ROOT}/include | |
| 55 | +) | |
| 56 | +mark_as_advanced(GMOCK_INCLUDE_DIR) | |
| 57 | + | |
| 58 | +find_path(GMOCK_SOURCE_DIR gmock-all.cc | |
| 59 | + HINTS | |
| 60 | + $ENV{GMOCK_ROOT}/src/gmock | |
| 61 | + ${GMOCK_ROOT}/src/gmock | |
| 62 | + PATHS | |
| 63 | + ${GMOCK_INCLUDE_DIR}/../src/gmock | |
| 64 | +) | |
| 65 | +mark_as_advanced(GMOCK_SOURCE_DIR) | |
| 66 | + | |
| 67 | +FIND_PACKAGE_HANDLE_STANDARD_ARGS(GMock DEFAULT_MSG GMOCK_INCLUDE_DIR GMOCK_SOURCE_DIR) | |
| 68 | + | |
| 69 | +if(GMOCK_FOUND) | |
| 70 | + set(GMOCK_INCLUDE_DIRS ${GMOCK_INCLUDE_DIR}) | |
| 71 | +endif() | |
| 72 | + | ... | ... |
cmake/FindJsoncpp.cmake
0 → 100644
| 1 | +# Locate jsoncpp | |
| 2 | +# | |
| 3 | +# This module defines | |
| 4 | +# JSONCPP_FOUND, if false, do not try to link to jsoncpp | |
| 5 | +# JSONCPP_LIBRARY, where to find jsoncpp | |
| 6 | +# JSONCPP_INCLUDE_DIR, where to find json.h | |
| 7 | +# | |
| 8 | +# By default, the dynamic libraries of jsoncpp will be found. To find the static ones instead, | |
| 9 | +# you must set the JSONCPP_STATIC_LIBRARY variable to TRUE before calling find_package(Jsoncpp ...). | |
| 10 | +# | |
| 11 | +# If jsoncpp is not installed in a standard path, you can use the JSONCPP_DIR CMake variable | |
| 12 | +# to tell CMake where jsoncpp is. | |
| 13 | + | |
| 14 | +set(JSONCPP_FOUND 0) | |
| 15 | + | |
| 16 | +# attempt to find static library first if this is set | |
| 17 | +if(JSONCPP_STATIC_LIBRARY) | |
| 18 | + set(JSONCPP_STATIC libjsoncpp.a) | |
| 19 | +endif() | |
| 20 | + | |
| 21 | +# find the jsoncpp include directory | |
| 22 | +find_path(JSONCPP_INCLUDE_DIR json/json.h | |
| 23 | + PATHS | |
| 24 | + ~/Library/Frameworks/jsoncpp/include/ | |
| 25 | + /Library/Frameworks/jsoncpp/include/ | |
| 26 | + /usr/local/include/ | |
| 27 | + /usr/include/ | |
| 28 | + /sw/jsoncpp/ # Fink | |
| 29 | + /opt/local/jsoncpp/ # DarwinPorts | |
| 30 | + /opt/csw/jsoncpp/ # Blastwave | |
| 31 | + /opt/jsoncpp/ | |
| 32 | + ${JSONCPP_DIR}/include/ | |
| 33 | + PATH_SUFFIXES jsoncpp) | |
| 34 | + | |
| 35 | +# find the jsoncpp library | |
| 36 | +find_library(JSONCPP_LIBRARY | |
| 37 | + NAMES ${JSONCPP_STATIC} jsoncpp | |
| 38 | + PATH_SUFFIXES lib64 lib | |
| 39 | + PATHS ~/Library/Frameworks | |
| 40 | + /Library/Frameworks | |
| 41 | + /usr/local | |
| 42 | + /usr | |
| 43 | + /sw | |
| 44 | + /opt/local | |
| 45 | + /opt/csw | |
| 46 | + /opt | |
| 47 | + ${JSONCPP_DIR}/lib) | |
| 48 | + | |
| 49 | +# handle the QUIETLY and REQUIRED arguments and set JSONCPP_FOUND to TRUE if all listed variables are TRUE | |
| 50 | +include(FindPackageHandleStandardArgs) | |
| 51 | +FIND_PACKAGE_HANDLE_STANDARD_ARGS(JSONCPP DEFAULT_MSG JSONCPP_INCLUDE_DIR JSONCPP_LIBRARY) | |
| 52 | +mark_as_advanced(JSONCPP_INCLUDE_DIR JSONCPP_LIBRARY) | |
| 53 | +message("JSONCPP_FOUND = ${JSONCPP_FOUND}, includedir = ${JSONCPP_INCLUDE_DIR}, lib = ${JSONCPP_LIBRARY}") | ... | ... |
cmake/FindYamlCpp.cmake
0 → 100644
| 1 | +# Locate yaml-cpp | |
| 2 | +# | |
| 3 | +# This module defines | |
| 4 | +# YAMLCPP_FOUND, if false, do not try to link to yaml-cpp | |
| 5 | +# YAMLCPP_LIBRARY, where to find yaml-cpp | |
| 6 | +# YAMLCPP_INCLUDE_DIR, where to find yaml.h | |
| 7 | +# | |
| 8 | +# By default, the dynamic libraries of yaml-cpp will be found. To find the static ones instead, | |
| 9 | +# you must set the YAMLCPP_STATIC_LIBRARY variable to TRUE before calling find_package(YamlCpp ...). | |
| 10 | +# | |
| 11 | +# If yaml-cpp is not installed in a standard path, you can use the YAMLCPP_DIR CMake variable | |
| 12 | +# to tell CMake where yaml-cpp is. | |
| 13 | + | |
| 14 | +# attempt to find static library first if this is set | |
| 15 | +if(YAMLCPP_STATIC_LIBRARY) | |
| 16 | + set(YAMLCPP_STATIC libyaml-cpp.a) | |
| 17 | +endif() | |
| 18 | + | |
| 19 | +# find the yaml-cpp include directory | |
| 20 | +find_path(YAMLCPP_INCLUDE_DIR yaml-cpp/yaml.h | |
| 21 | + PATH_SUFFIXES include | |
| 22 | + PATHS | |
| 23 | + ~/Library/Frameworks/yaml-cpp/include/ | |
| 24 | + /Library/Frameworks/yaml-cpp/include/ | |
| 25 | + /usr/local/include/ | |
| 26 | + /usr/include/ | |
| 27 | + /sw/yaml-cpp/ # Fink | |
| 28 | + /opt/local/yaml-cpp/ # DarwinPorts | |
| 29 | + /opt/csw/yaml-cpp/ # Blastwave | |
| 30 | + /opt/yaml-cpp/ | |
| 31 | + ${YAMLCPP_DIR}/include/) | |
| 32 | + | |
| 33 | +# find the yaml-cpp library | |
| 34 | +find_library(YAMLCPP_LIBRARY | |
| 35 | + NAMES ${YAMLCPP_STATIC} yaml-cpp | |
| 36 | + PATH_SUFFIXES lib64 lib | |
| 37 | + PATHS ~/Library/Frameworks | |
| 38 | + /Library/Frameworks | |
| 39 | + /usr/local | |
| 40 | + /usr | |
| 41 | + /sw | |
| 42 | + /opt/local | |
| 43 | + /opt/csw | |
| 44 | + /opt | |
| 45 | + ${YAMLCPP_DIR}/lib) | |
| 46 | + | |
| 47 | +# handle the QUIETLY and REQUIRED arguments and set YAMLCPP_FOUND to TRUE if all listed variables are TRUE | |
| 48 | +include(FindPackageHandleStandardArgs) | |
| 49 | +FIND_PACKAGE_HANDLE_STANDARD_ARGS(YAMLCPP DEFAULT_MSG YAMLCPP_INCLUDE_DIR YAMLCPP_LIBRARY) | |
| 50 | +mark_as_advanced(YAMLCPP_INCLUDE_DIR YAMLCPP_LIBRARY) | ... | ... |
cmake/application.cmake
0 → 100644
| 1 | +# @brief Adds an executable target and performs related actions, | |
| 2 | +# such as verioning, binary dir and configuration. | |
| 3 | +# @note The default binary directory is PROJECT_BINARY_DIR, but can be overridden by specifying the ${PROJECT_NAME}_CURRENT_BINARY_DIR. | |
| 4 | +function(add_application) | |
| 5 | + | |
| 6 | +message( STATUS "${PROJECT_NAME} linking libraries : ${ARGN}") | |
| 7 | + | |
| 8 | +# Use PROJECT_BINARY_DIR by default, but override if necessary. | |
| 9 | +set(CURRENT_PROJECT_BINARY_DIR ${PROJECT_BINARY_DIR}) | |
| 10 | +if (${PROJECT_NAME}_CURRENT_BINARY_DIR) | |
| 11 | + set(CURRENT_PROJECT_BINARY_DIR ${${PROJECT_NAME}_CURRENT_BINARY_DIR}) | |
| 12 | +endif() | |
| 13 | +message(STATUS "CURRENT_PROJECT_BINARY_DIR : ${CURRENT_PROJECT_BINARY_DIR}") | |
| 14 | + | |
| 15 | +include_directories(${HSOA_VERSION_INCLUDE_DIR}) | |
| 16 | + | |
| 17 | +add_executable( ${PROJECT_NAME} | |
| 18 | + ${HSOA_VERSION_SRC_FILE} | |
| 19 | + ${SRC_LIST} | |
| 20 | +) | |
| 21 | + | |
| 22 | +target_link_libraries( ${PROJECT_NAME} | |
| 23 | + ${ARGN} | |
| 24 | +) | |
| 25 | + | |
| 26 | +set_target_properties( ${PROJECT_NAME} | |
| 27 | + PROPERTIES | |
| 28 | + VERSION ${PROJECT_VERSION} | |
| 29 | + RUNTIME_OUTPUT_DIRECTORY ${CURRENT_PROJECT_BINARY_DIR}/bin | |
| 30 | +) | |
| 31 | + | |
| 32 | +# Copy the testconfig to the build dir, so the binaries are testable from the build dir. | |
| 33 | +# The created packages will not contain the testconfig but the production config instead. See installation.cmake. | |
| 34 | +if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/testconfig/) | |
| 35 | + file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/testconfig/" DESTINATION "${CURRENT_PROJECT_BINARY_DIR}/etc") | |
| 36 | +endif() | |
| 37 | + | |
| 38 | +endfunction() | ... | ... |
cmake/application.post_install.inc.cmake.in
0 → 100644
| 1 | +# Make sure the mLogic group exists | |
| 2 | +MLOGIC_GROUP=mlogic | |
| 3 | +groupadd --force $MLOGIC_GROUP | |
| 4 | +# Create the user | |
| 5 | +appuserid=$(id -u @PROJECT_NAME@) | |
| 6 | +if [ ! $appuserid ] ; then | |
| 7 | + useradd --groups $MLOGIC_GROUP --no-create-home @PROJECT_NAME@ | |
| 8 | +fi | |
| 9 | +# Prevent direct login | |
| 10 | +passwd --lock @PROJECT_NAME@ | |
| 11 | +# Change group ownership of log folder | |
| 12 | +chgrp $MLOGIC_GROUP @PROJCOMP_LOG_INSTALL_DIR@ | |
| 13 | +# Change group ownership of run folder | |
| 14 | +chgrp $MLOGIC_GROUP @PROJCOMP_RUN_INSTALL_DIR@ | ... | ... |
cmake/application.post_uninstall.inc.cmake.in
0 → 100644
cmake/artifacts.cmake
0 → 100644
| 1 | +# @brief Tries to find the module with find_package, and uses CMAKE_INSTALL_PREFIX (see documentation). | |
| 2 | +# If the module can't be found, includes the directory by the specified module path. | |
| 3 | +# @param module The name of the module on which a dependency is added | |
| 4 | +# @param modulepath The relative path of the module wrt the current project | |
| 5 | +# @param moduleincludepath [optional] The relative path to the include directory | |
| 6 | +# @note Needs to be a macro because of the scope of the variables that are set by find_package. | |
| 7 | +macro(depend_module module modulepath) | |
| 8 | + message(STATUS "module : ${module}") | |
| 9 | + message(STATUS "modulepath : ${modulepath}") | |
| 10 | + | |
| 11 | + set ( optional_macro_args ${ARGN} ) | |
| 12 | + list ( LENGTH optional_macro_args num_optional_args ) | |
| 13 | + if ( ${num_optional_args} GREATER 0 ) | |
| 14 | + list ( GET optional_macro_args 0 moduleincludepath ) | |
| 15 | + else() | |
| 16 | + set ( moduleincludepath include ) | |
| 17 | + endif() | |
| 18 | + message(STATUS "moduleincludepath : ${moduleincludepath}") | |
| 19 | + | |
| 20 | + find_package(${module} CONFIG QUIET) | |
| 21 | + message( STATUS "${module}_FOUND: ${${module}_FOUND}" ) | |
| 22 | + | |
| 23 | + string( TOUPPER ${module} MODULE_NAME_UPPER ) | |
| 24 | + | |
| 25 | + # check if the constructed variable name exists and if so check also the content. | |
| 26 | + if ( NOT ${${module}_FOUND} ) | |
| 27 | + if ( NOT TARGET ${module} ) | |
| 28 | + message( STATUS "Adding subdirectory ${modulepath}/${module} as subdirectory ${CMAKE_CURRENT_LIST_DIR}/staging/${module}." ) | |
| 29 | + add_subdirectory(${modulepath}/${module} staging/${module}) | |
| 30 | + endif() | |
| 31 | + | |
| 32 | + set( ${MODULE_NAME_UPPER}_INCLUDE_DIR ${modulepath}/${module}/${moduleincludepath} CACHE STRING "${module} include path" FORCE ) | |
| 33 | + set( ${MODULE_NAME_UPPER}_LIB_DIR "${CMAKE_CURRENT_BINARY_DIR}" CACHE STRING "${module} library path" FORCE ) | |
| 34 | + set( ${MODULE_NAME_UPPER}_LIB_NAME "${module}" CACHE STRING "${module} library name" FORCE ) | |
| 35 | + endif() | |
| 36 | + | |
| 37 | + message( STATUS "${MODULE_NAME_UPPER}_INCLUDE_DIR: ${${MODULE_NAME_UPPER}_INCLUDE_DIR}" ) | |
| 38 | + message( STATUS "${MODULE_NAME_UPPER}_LIB_DIR: ${${MODULE_NAME_UPPER}_LIB_DIR}" ) | |
| 39 | + message( STATUS "${MODULE_NAME_UPPER}_LIB_NAME: ${${MODULE_NAME_UPPER}_LIB_NAME}" ) | |
| 40 | +endmacro() | ... | ... |
cmake/compiler.cmake
0 → 100644
| 1 | +include(CheckCXXCompilerFlag) | |
| 2 | + | |
| 3 | +set(PLATFORM_RELEASE "") | |
| 4 | +function(platformRelease) | |
| 5 | + set(PR, "") | |
| 6 | + execute_process(COMMAND /bin/bash -c "if [ -e /etc/redhat-release ]; then cat /etc/redhat-release | tr -d '\n'; fi" OUTPUT_VARIABLE PR) | |
| 7 | + message(STATUS "Platform is ${PR}") | |
| 8 | + set(PLATFORM_RELEASE "${PR}" PARENT_SCOPE) | |
| 9 | +endfunction(platformRelease) | |
| 10 | + | |
| 11 | +# The target architecture (-march, -mtune) is assumed to be the architecture that was used to build gcc. | |
| 12 | +# If cross-compilation is required, this should be specified as cmake arguments. | |
| 13 | + | |
| 14 | +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic -Wshadow" ) | |
| 15 | +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wnon-virtual-dtor -Woverloaded-virtual -Winit-self -Wuninitialized -Wunused -Wcast-qual" ) | |
| 16 | +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-long-long" ) | |
| 17 | +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wold-style-cast" ) | |
| 18 | +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror=return-type" ) | |
| 19 | + | |
| 20 | +if(CMAKE_SYSTEM_PROCESSOR MATCHES "^x86_64") | |
| 21 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-noexcept-type" ) | |
| 22 | +endif() | |
| 23 | + | |
| 24 | +if(CMAKE_COMPILER_IS_GNUCC | |
| 25 | + AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9 | |
| 26 | + AND NOT APPLE) | |
| 27 | + # Mac OSX doesn't seem to honour -isystem, so not for Mac. | |
| 28 | + # Also, GCC 4.8 complains about boost | |
| 29 | + MESSAGE(STATUS "Don't treat warnings as errors") | |
| 30 | +else() | |
| 31 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror" ) | |
| 32 | +endif() | |
| 33 | +if(BUILD_WITH_PROFILING) | |
| 34 | + message(STATUS "Profiling enabled") | |
| 35 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pg" ) | |
| 36 | +else() | |
| 37 | + message(STATUS "Profiling disabled") | |
| 38 | +endif() | |
| 39 | + | |
| 40 | +# Allow linking into a dynamic library | |
| 41 | +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC" ) | |
| 42 | + | |
| 43 | +# Use RelWithDebInfo as default build type | |
| 44 | +if (NOT CMAKE_BUILD_TYPE) | |
| 45 | + set(CMAKE_BUILD_TYPE "RelWithDebInfo") | |
| 46 | +endif() | |
| 47 | +message(STATUS "CMAKE_BUILD_TYPE: ${CMAKE_BUILD_TYPE}") | |
| 48 | + | |
| 49 | +if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") | |
| 50 | + set(NOASSERTS 1) # Disable asserts as well | |
| 51 | + # -O3 causes weird crashes on win32 so we force -O2 for release builds also for linux builds | |
| 52 | + string(REGEX REPLACE "-O3" "-O2" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}") | |
| 53 | + string(REGEX REPLACE "-O3" "-O2" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") | |
| 54 | + if(MINGW) | |
| 55 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s") | |
| 56 | + endif() | |
| 57 | +else() | |
| 58 | + # Let Qt track the use of QSharedPointer | |
| 59 | + set(CMAKE_CXX_CFLAGS "${CMAKE_CXX_FLAGS} -DQT_SHAREDPOINTER_TRACK_POINTERS") | |
| 60 | + # If we're debugging, remove -O2 completely | |
| 61 | + string(REGEX REPLACE "-O2" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") | |
| 62 | + string(REGEX REPLACE "-O2" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") | |
| 63 | + string(REGEX REPLACE "-O2" "" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}") | |
| 64 | + string(REGEX REPLACE "-O2" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") | |
| 65 | +endif() | |
| 66 | + | |
| 67 | +# Disable asserts with -DNOASSERTS=1 as a CMake command-line parameter | |
| 68 | +if(NOASSERTS) | |
| 69 | + add_definitions(-DQT_NO_DEBUG) | |
| 70 | + add_definitions(-DNDEBUG) | |
| 71 | + message(STATUS "Asserts have been disabled") | |
| 72 | +endif(NOASSERTS) | |
| 73 | + | |
| 74 | +if(APPLE) | |
| 75 | + # AVX instructions currently cause assembler errors, so disabling them | |
| 76 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -w -mno-avx -mmacosx-version-min=10.7 -stdlib=libc++ ") | |
| 77 | + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -w -mno-avx -mmacosx-version-min=10.7") | |
| 78 | +endif(APPLE) | |
| 79 | + | |
| 80 | +if(UNIX) | |
| 81 | + if(BUILD_WITH_COVERAGE) | |
| 82 | + # Specifically enable coverate info, since ccache can't cache with | |
| 83 | + # profiling enabled, seriously hurting build-times in Debug-mode | |
| 84 | + message(STATUS "Generate coverage info") | |
| 85 | + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fprofile-arcs -ftest-coverage") | |
| 86 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage") | |
| 87 | + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fprofile-arcs -ftest-coverage") | |
| 88 | + if (NOT TARGET RemoveGCDA) | |
| 89 | + add_custom_target(RemoveGCDA ALL | |
| 90 | + COMMAND find . -name "*.gcda" -delete | |
| 91 | + COMMENT "Removing gcda files") | |
| 92 | + endif(NOT TARGET RemoveGCDA) | |
| 93 | + | |
| 94 | + if(NOT NOASSERTS) | |
| 95 | + add_definitions(-DQT_SHAREDPOINTER_TRACK_POINTERS) | |
| 96 | + endif(NOT NOASSERTS) | |
| 97 | + else() | |
| 98 | + message(STATUS "Building without coverage info") | |
| 99 | + endif() | |
| 100 | +endif(UNIX) | |
| 101 | + | |
| 102 | +if(UNIX AND NOT APPLE) | |
| 103 | + # needed for making qwt happy | |
| 104 | + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lrt" ) | |
| 105 | +endif(UNIX AND NOT APPLE) | |
| 106 | + | |
| 107 | +if(MINGW) | |
| 108 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mwindows" ) | |
| 109 | +endif(MINGW) | |
| 110 | + | |
| 111 | +CHECK_CXX_COMPILER_FLAG( -fstack-protector-all result ) | |
| 112 | +if(result) | |
| 113 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fstack-protector-all") | |
| 114 | +endif(result) | |
| 115 | + | |
| 116 | +CHECK_CXX_COMPILER_FLAG( -fthreadsafe-statics THREADSAFE_RESULT) | |
| 117 | +if( NOT THREADSAFE_RESULT) | |
| 118 | + message(FATAL_ERROR, "Compiler does not support threadsafe statics variables in methods") | |
| 119 | +endif() | |
| 120 | +# We use static variables in method scope, they must be threadsafe, this is on by default since gcc 4 but this flag is a check | |
| 121 | +# If the compiler does not support this then build will fail. | |
| 122 | +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fthreadsafe-statics") | |
| 123 | + | |
| 124 | +if(CMAKE_COMPILER_IS_GNUCXX) | |
| 125 | + # Check on which architecture we are. ARM doesn't support mfpmath | |
| 126 | + if(CMAKE_SYSTEM_PROCESSOR MATCHES "^x86_64") | |
| 127 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mfpmath=sse" ) | |
| 128 | + endif() | |
| 129 | + | |
| 130 | + MESSAGE(STATUS "Checking the c++ Standard supported by the compiler" ) | |
| 131 | + # Check which version of c++ we can use. We drill down from c++17 to c96 | |
| 132 | + CHECK_CXX_COMPILER_FLAG( -std=c++17 cxxresult ) | |
| 133 | + if( NOT cxxresult ) | |
| 134 | + CHECK_CXX_COMPILER_FLAG( -std=c++14 cxxresult ) | |
| 135 | + if( NOT cxxresult ) | |
| 136 | + CHECK_CXX_COMPILER_FLAG( -std=c++11 cxxresult ) | |
| 137 | + if( NOT cxxresult ) | |
| 138 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") | |
| 139 | + else() | |
| 140 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") | |
| 141 | + endif() | |
| 142 | + else() | |
| 143 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") | |
| 144 | + endif() | |
| 145 | + else() | |
| 146 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") | |
| 147 | + endif() | |
| 148 | + MESSAGE(STATUS "Compiling for ${CMAKE_CXX_FLAGS}") | |
| 149 | + | |
| 150 | + # -Wzero-as-null-pointer-constant is disabled for now, since the Qt 4.8.4 | |
| 151 | + # macro's produce a bucketload of these warnings. Might be useful later on. | |
| 152 | +# CHECK_CXX_COMPILER_FLAG( -Wzero-as-null-pointer-constant cxxresult ) | |
| 153 | +# if(cxxresult) | |
| 154 | +# set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wzero-as-null-pointer-constant") | |
| 155 | +# endif(cxxresult) | |
| 156 | + # Leave out deprecation warnings, mostly generated by CppUnit | |
| 157 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-deprecated-declarations") | |
| 158 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Weffc++") | |
| 159 | + | |
| 160 | +endif(CMAKE_COMPILER_IS_GNUCXX) | |
| 161 | + | |
| 162 | +if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") | |
| 163 | + MESSAGE(STATUS "Enabling Clang flags") | |
| 164 | + # We enable all warnings and disable what we don't need | |
| 165 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Weverything") | |
| 166 | + # Warns if items need to be re-aligned to 4-byte boundaries. Since we use | |
| 167 | + # booleans in our code, these warnings are all over the place. If | |
| 168 | + # memory-usage becomes an issue, we can pack all booleans together using | |
| 169 | + # this warning. However, it's currently not practical to eliminate them all. | |
| 170 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-padded") | |
| 171 | + # We use a lot of static objects, which get cleaned up at exit by their destructors. | |
| 172 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-exit-time-destructors") | |
| 173 | + # Static objects tend to have global constructors | |
| 174 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-global-constructors") | |
| 175 | + # We mix int / unsigned int a lot, so disabled it for the moment | |
| 176 | + #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-sign-conversion") | |
| 177 | + # Warning caused by the Qt translations | |
| 178 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-missing-prototypes") | |
| 179 | + # We standardize on C++11, so don't bother us with C++98 | |
| 180 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-c++98-compat -Wno-c++98-compat-pedantic") | |
| 181 | + # We explicitly want to use the switch(){default: break;} construction | |
| 182 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-switch-enum") | |
| 183 | + # Q_OBJECT does an "int i = i;"... | |
| 184 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-self-assign") | |
| 185 | + # Compile for C++11 | |
| 186 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") | |
| 187 | + # Don't complain about unused arguments, since this also triggers warnings | |
| 188 | + # about include-directories that are unused... | |
| 189 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Qunused-arguments") | |
| 190 | + # Don't complain about fall-throughs in switch/case statements | |
| 191 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-implicit-fallthrough") | |
| 192 | + # Since "Q_ASSERT(false)" creates a not of noise, disable it when asserts are active | |
| 193 | + if(NOT NOASSERTS) | |
| 194 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unreachable-code") | |
| 195 | + endif(NOT NOASSERTS) | |
| 196 | + # There is no way to avoid this warning right now, so we disable it | |
| 197 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-weak-template-vtables") | |
| 198 | + # Warning caused by Qt resource files, so disabling it | |
| 199 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-missing-variable-declarations") | |
| 200 | + # WORKAROUND: Somehow Qt forgets that Clang is a C++11 compiler | |
| 201 | + ADD_DEFINITIONS("-DQ_COMPILER_INITIALIZER_LISTS") | |
| 202 | + # Clang 3.3 doesn't know Doxygens' "\test" and "\retval" tags, so disabling | |
| 203 | + # check for unknown tags for now | |
| 204 | + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-documentation-unknown-command") | |
| 205 | + | |
| 206 | + if(CMAKE_CXX_COMPILER_VERSION MATCHES "3\\.4\\.2") | |
| 207 | + message(STATUS "compiler is clang version 3.4.2") | |
| 208 | + platformRelease() | |
| 209 | + if("${PLATFORM_RELEASE}" MATCHES "CentOS Linux release 7\\.2\\..+") | |
| 210 | + # Override the gnu minor version only for this specific combination of platform and clang version | |
| 211 | + set(CMAKE_CXX_FLAGS "-U__GNUC_MINOR__ -D__GNUC_MINOR__=3 ${CMAKE_CXX_FLAGS}") | |
| 212 | + message(STATUS "Overriding clang gnu minor version to 3 so that several libstd c++11 features like tuple can be used") | |
| 213 | + endif("${PLATFORM_RELEASE}" MATCHES "CentOS Linux release 7\\.2\\..+") | |
| 214 | + endif(CMAKE_CXX_COMPILER_VERSION MATCHES "3\\.4\\.2") | |
| 215 | +endif(CMAKE_CXX_COMPILER_ID MATCHES "Clang") | |
| 216 | + | |
| 217 | +if(APPLE) | |
| 218 | + set(WHOLE_ARCHIVE_ON "-all_load") | |
| 219 | + set(WHOLE_ARCHIVE_OFF "") | |
| 220 | +else() | |
| 221 | + set(WHOLE_ARCHIVE_ON "-Wl,-whole-archive") | |
| 222 | + set(WHOLE_ARCHIVE_OFF "-Wl,-no-whole-archive") | |
| 223 | +endif() | ... | ... |
cmake/config.cmake.in
0 → 100644
| 1 | +@PACKAGE_INIT@ | |
| 2 | + | |
| 3 | +string( TOUPPER @PROJECT_NAME@ PROJECT_NAME_UPPER ) | |
| 4 | + | |
| 5 | +string( CONCAT MY_PACKAGE_INCLUDE_DIR ${PROJECT_NAME_UPPER} "_INCLUDE_DIR" ) | |
| 6 | +set_and_check(${MY_PACKAGE_INCLUDE_DIR} "@PACKAGE_PROJCOMP_INCLUDE_INSTALL_DIR@") | |
| 7 | +message( STATUS "${MY_PACKAGE_INCLUDE_DIR}: ${${MY_PACKAGE_INCLUDE_DIR}}" ) | |
| 8 | + | |
| 9 | +string( CONCAT MY_PACKAGE_LIB_DIR ${PROJECT_NAME_UPPER} "_LIB_DIR" ) | |
| 10 | +set_and_check(${MY_PACKAGE_LIB_DIR} "@PACKAGE_PROJCOMP_LIB_INSTALL_DIR@") | |
| 11 | +message( STATUS "${MY_PACKAGE_LIB_DIR}: ${${MY_PACKAGE_LIB_DIR}}" ) | |
| 12 | + | |
| 13 | +string( CONCAT MY_PACKAGE_CMAKE_DIR ${PROJECT_NAME_UPPER} "_CMAKE_DIR" ) | |
| 14 | +set_and_check(${MY_PACKAGE_CMAKE_DIR} "@PACKAGE_PROJCOMP_CMAKE_INSTALL_DIR@") | |
| 15 | +message( STATUS "${MY_PACKAGE_CMAKE_DIR}: ${${MY_PACKAGE_CMAKE_DIR}}" ) | |
| 16 | + | |
| 17 | +string( CONCAT MY_PACKAGE_LIB_NAME ${PROJECT_NAME_UPPER} "_LIB_NAME" ) | |
| 18 | +set(${MY_PACKAGE_LIB_NAME} "@PROJECT_NAME@") | |
| 19 | +message( STATUS "${MY_PACKAGE_LIB_NAME}: ${${MY_PACKAGE_LIB_NAME}}" ) | |
| 20 | + | |
| 21 | +check_required_components("@PROJECT_NAME@") | |
| 22 | +#message( STATUS "@PROJECT_NAME@_FOUND: ${${@PROJECT_NAME@}_FOUND}" ) | ... | ... |
cmake/installation.cmake
0 → 100644
| 1 | +set( INSTALLATION_CURRENT_CMAKE_DIR ${CMAKE_CURRENT_LIST_DIR} ) | |
| 2 | + | |
| 3 | +# Layout | |
| 4 | +set(USR_LOCAL_DIR "/usr/local" CACHE STRING "" FORCE) | |
| 5 | +set(LD_SO_CONF_D_DIR "/etc/ld.so.conf.d" CACHE STRING "" FORCE) | |
| 6 | +set(SYSTEMD_CONFIG_DIR "/etc/systemd/system" CACHE STRING "" FORCE) | |
| 7 | +set(VAR_LOG_DIR "/var/log" CACHE STRING "" FORCE) | |
| 8 | +set(VAR_RUN_DIR "/var/run" CACHE STRING "" FORCE) | |
| 9 | +set(PROJCOMP_LOG_INSTALL_DIR "${VAR_LOG_DIR}/${PROJECT_NAME}") | |
| 10 | +set(PROJCOMP_RUN_INSTALL_DIR "${VAR_RUN_DIR}/${PROJECT_NAME}") | |
| 11 | +set(PROJCOMP_BIN_INSTALL_DIR "${PROJECT_NAME}/bin") | |
| 12 | +set(PROJCOMP_LIB_INSTALL_DIR "lib") | |
| 13 | +set(PROJCOMP_INCLUDE_INSTALL_DIR "${PROJECT_NAME}/include") | |
| 14 | +set(PROJCOMP_ETC_INSTALL_DIR "${PROJECT_NAME}/etc") | |
| 15 | +set(PROJCOMP_CMAKE_INSTALL_DIR "${PROJECT_NAME}/cmake") | |
| 16 | +set(PROJCOMP_COMPONENT_NAME "${REPOSITORY_PACKAGE_NAME}-${PROJECT_NAME}") | |
| 17 | +set(PROJCOMP_COMPONENT_NAME_DEVEL "${PROJCOMP_COMPONENT_NAME}-devel") | |
| 18 | + | |
| 19 | +# @brief Installs a library component and performs related actions. | |
| 20 | +function(install_component) | |
| 21 | + | |
| 22 | +set(GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated") | |
| 23 | + | |
| 24 | +# Configuration | |
| 25 | +string(TOLOWER ${PROJECT_NAME} MODULE_NAME_LOWER) | |
| 26 | +set(PROJECT_CONFIG "${GENERATED_DIR}/${MODULE_NAME_LOWER}-config.cmake") | |
| 27 | + | |
| 28 | +# Generate the cmake config file | |
| 29 | +include(CMakePackageConfigHelpers) | |
| 30 | +configure_package_config_file( | |
| 31 | + "${INSTALLATION_CURRENT_CMAKE_DIR}/config.cmake.in" | |
| 32 | + "${PROJECT_CONFIG}" | |
| 33 | + INSTALL_DESTINATION "${PROJCOMP_CMAKE_INSTALL_DIR}" | |
| 34 | + PATH_VARS PROJCOMP_INCLUDE_INSTALL_DIR PROJCOMP_LIB_INSTALL_DIR PROJCOMP_CMAKE_INSTALL_DIR | |
| 35 | +) | |
| 36 | + | |
| 37 | +# Install license file | |
| 38 | +if (EXISTS "${INSTALLATION_CURRENT_CMAKE_DIR}/COPYING.OSDEV") | |
| 39 | + install( | |
| 40 | + FILES "${INSTALLATION_CURRENT_CMAKE_DIR}/COPYING.OSDEV" | |
| 41 | + DESTINATION ${PROJCOMP_LIB_INSTALL_DIR} | |
| 42 | + COMPONENT "${PROJCOMP_COMPONENT_NAME}" | |
| 43 | + ) | |
| 44 | +endif() | |
| 45 | + | |
| 46 | +# Install targets | |
| 47 | +install( | |
| 48 | + TARGETS ${PROJECT_NAME} | |
| 49 | + DESTINATION ${PROJCOMP_LIB_INSTALL_DIR} | |
| 50 | + COMPONENT "${PROJCOMP_COMPONENT_NAME}" | |
| 51 | +) | |
| 52 | + | |
| 53 | +# Configure and install dynamic linker runtime bindings (ld.so.conf.d file) | |
| 54 | +configure_file( | |
| 55 | + "${INSTALLATION_CURRENT_CMAKE_DIR}/ld.so.conf.d.cmake.in" | |
| 56 | + "${GENERATED_DIR}/${PROJECT_NAME}.conf" | |
| 57 | +) | |
| 58 | +install( | |
| 59 | + FILES "${GENERATED_DIR}/${PROJECT_NAME}.conf" | |
| 60 | + DESTINATION ${LD_SO_CONF_D_DIR} | |
| 61 | + COMPONENT "${PROJCOMP_COMPONENT_NAME}" | |
| 62 | +) | |
| 63 | + | |
| 64 | +# Configure and set cpack post install script | |
| 65 | +configure_file( | |
| 66 | + "${INSTALLATION_CURRENT_CMAKE_DIR}/library.post_install.inc.cmake.in" | |
| 67 | + "${GENERATED_DIR}/library.post_install.inc" | |
| 68 | +) | |
| 69 | +# Set the per-component post install script file. | |
| 70 | +set(CPACK_RPM_${PROJCOMP_COMPONENT_NAME}_POST_INSTALL_SCRIPT_FILE "${GENERATED_DIR}/library.post_install.inc" CACHE STRING "${PROJECT_NAME} post_install script" FORCE) | |
| 71 | + | |
| 72 | +# Headers | |
| 73 | +# At the moment, we anticipate the headers to be located according to either 1) or 2). | |
| 74 | + | |
| 75 | +# 1) Apply glob style pattern for those projects that have the header files in the root folder of the repository (such as opcua_model). | |
| 76 | +file (GLOB PACKAGE_HEADERS "${CMAKE_CURRENT_LIST_DIR}/*.h*") | |
| 77 | +install( | |
| 78 | + FILES ${PACKAGE_HEADERS} | |
| 79 | + DESTINATION ${PROJCOMP_INCLUDE_INSTALL_DIR} | |
| 80 | + COMPONENT "${PROJCOMP_COMPONENT_NAME_DEVEL}" | |
| 81 | +) | |
| 82 | +# 2) Copy the include dir for those projects that have the header files in include/mlogic (such as opc_utils). | |
| 83 | +if (EXISTS ${CMAKE_CURRENT_LIST_DIR}/include/mlogic) | |
| 84 | + install( | |
| 85 | + DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/include/mlogic | |
| 86 | + DESTINATION ${PROJCOMP_INCLUDE_INSTALL_DIR} | |
| 87 | + COMPONENT "${PROJCOMP_COMPONENT_NAME_DEVEL}" | |
| 88 | + ) | |
| 89 | +endif() | |
| 90 | + | |
| 91 | +# Install cmake project config | |
| 92 | +install( | |
| 93 | + FILES ${PROJECT_CONFIG} | |
| 94 | + DESTINATION ${PROJCOMP_CMAKE_INSTALL_DIR} | |
| 95 | + COMPONENT "${PROJCOMP_COMPONENT_NAME_DEVEL}" | |
| 96 | +) | |
| 97 | + | |
| 98 | +# The -devel package depends on the runtime package | |
| 99 | +set(CPACK_RPM_${PROJCOMP_COMPONENT_NAME_DEVEL}_PACKAGE_REQUIRES "${PROJCOMP_COMPONENT_NAME} = ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}-${CURRENT_PROJECT_VERSION_RELEASENR}" CACHE STRING "${PROJCOMP_COMPONENT_NAME_DEVEL} dependency" FORCE ) | |
| 100 | +# Clear the dependencies for the runtime package, as cpack erroneously added unexpected dependencies (hints towards the previously built package) | |
| 101 | +set(CPACK_RPM_${PROJCOMP_COMPONENT_NAME}_PACKAGE_REQUIRES "" CACHE STRING "${PROJCOMP_COMPONENT_NAME} dependencies" FORCE ) | |
| 102 | + | |
| 103 | +endfunction() | |
| 104 | + | |
| 105 | +# @brief Installs the executable binary and related items | |
| 106 | +# (such as systemd service files, log folder, post [un]install scripts) | |
| 107 | +# @param INSTALL_SYSTEMD_SERVICE [optional] Boolean to indicate whether the systemd unit files must be installed. Optional. The default is ON. | |
| 108 | +function(install_application) | |
| 109 | + | |
| 110 | +set ( optional_macro_args ${ARGN} ) | |
| 111 | +list ( LENGTH optional_macro_args num_optional_args ) | |
| 112 | +if ( ${num_optional_args} GREATER 0 ) | |
| 113 | + list ( GET optional_macro_args 0 INSTALL_SYSTEMD_SERVICE ) | |
| 114 | +endif() | |
| 115 | + | |
| 116 | +if(NOT DEFINED INSTALL_SYSTEMD_SERVICE) | |
| 117 | + set(INSTALL_SYSTEMD_SERVICE "ON") | |
| 118 | +endif() | |
| 119 | + | |
| 120 | +message(STATUS "INSTALL_SYSTEMD_SERVICE: ${INSTALL_SYSTEMD_SERVICE}") | |
| 121 | + | |
| 122 | +set(GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated") | |
| 123 | + | |
| 124 | +# Install license file | |
| 125 | +if (EXISTS "${INSTALLATION_CURRENT_CMAKE_DIR}/COPYING.OSDEV") | |
| 126 | + install( | |
| 127 | + FILES "${INSTALLATION_CURRENT_CMAKE_DIR}/COPYING.OSDEV" | |
| 128 | + DESTINATION ${PROJCOMP_BIN_INSTALL_DIR} | |
| 129 | + COMPONENT "${PROJCOMP_COMPONENT_NAME}" | |
| 130 | + ) | |
| 131 | +endif() | |
| 132 | + | |
| 133 | +# Install binary file | |
| 134 | +install( | |
| 135 | + TARGETS ${PROJECT_NAME} | |
| 136 | + DESTINATION ${PROJCOMP_BIN_INSTALL_DIR} | |
| 137 | + COMPONENT "${PROJCOMP_COMPONENT_NAME}" | |
| 138 | +) | |
| 139 | + | |
| 140 | +# Install configuration | |
| 141 | +if (EXISTS ${CMAKE_CURRENT_LIST_DIR}/config/) | |
| 142 | + install( | |
| 143 | + DIRECTORY ${CMAKE_CURRENT_LIST_DIR}/config/ | |
| 144 | + DESTINATION ${PROJCOMP_ETC_INSTALL_DIR} | |
| 145 | + COMPONENT "${PROJCOMP_COMPONENT_NAME}" | |
| 146 | + ) | |
| 147 | +endif() | |
| 148 | + | |
| 149 | +if (INSTALL_SYSTEMD_SERVICE STREQUAL "ON") | |
| 150 | + # Configure and install systemd unit file | |
| 151 | + configure_file( | |
| 152 | + "${INSTALLATION_CURRENT_CMAKE_DIR}/service.cmake.in" | |
| 153 | + "${GENERATED_DIR}/${PROJECT_NAME}.service" | |
| 154 | + ) | |
| 155 | + install( | |
| 156 | + FILES "${GENERATED_DIR}/${PROJECT_NAME}.service" | |
| 157 | + DESTINATION ${SYSTEMD_CONFIG_DIR} | |
| 158 | + COMPONENT "${PROJCOMP_COMPONENT_NAME}" | |
| 159 | + ) | |
| 160 | +endif() | |
| 161 | + | |
| 162 | +# Install log folder | |
| 163 | +install( | |
| 164 | + DIRECTORY | |
| 165 | + DESTINATION ${PROJCOMP_LOG_INSTALL_DIR} | |
| 166 | + DIRECTORY_PERMISSIONS | |
| 167 | + OWNER_WRITE OWNER_READ OWNER_EXECUTE | |
| 168 | + GROUP_WRITE GROUP_READ GROUP_EXECUTE SETGID | |
| 169 | + # No permissions for WORLD | |
| 170 | + COMPONENT "${PROJCOMP_COMPONENT_NAME}" | |
| 171 | +) | |
| 172 | + | |
| 173 | +# Install run folder | |
| 174 | +install( | |
| 175 | + DIRECTORY | |
| 176 | + DESTINATION ${PROJCOMP_RUN_INSTALL_DIR} | |
| 177 | + DIRECTORY_PERMISSIONS | |
| 178 | + OWNER_WRITE OWNER_READ OWNER_EXECUTE | |
| 179 | + GROUP_WRITE GROUP_READ GROUP_EXECUTE | |
| 180 | + # No permissions for WORLD | |
| 181 | + COMPONENT "${PROJCOMP_COMPONENT_NAME}" | |
| 182 | +) | |
| 183 | + | |
| 184 | +# Configure and set cpack post install script | |
| 185 | +configure_file( | |
| 186 | + "${INSTALLATION_CURRENT_CMAKE_DIR}/application.post_install.inc.cmake.in" | |
| 187 | + "${GENERATED_DIR}/application.post_install.inc" | |
| 188 | +) | |
| 189 | +# Set the per-component post install script file. | |
| 190 | +set(CPACK_RPM_${PROJCOMP_COMPONENT_NAME}_POST_INSTALL_SCRIPT_FILE "${GENERATED_DIR}/application.post_install.inc" CACHE STRING "${PROJECT_NAME} post_install script" FORCE) | |
| 191 | + | |
| 192 | +endfunction() | ... | ... |
cmake/ld.so.conf.d.cmake.in
0 → 100644
| 1 | +@CMAKE_INSTALL_PREFIX@/@PROJCOMP_LIB_INSTALL_DIR@/ | ... | ... |
cmake/library.cmake
0 → 100644
| 1 | +# @brief Adds a single shared or static library target and performs related actions, | |
| 2 | +# such as target properties and some packaging variables. | |
| 3 | +# @note The default binary directory is CMAKE_BINARY_DIR, but can be overridden by specifying the ${PROJECT_NAME}_CURRENT_BINARY_DIR. | |
| 4 | +function(add_libraries) | |
| 5 | + | |
| 6 | +message( STATUS "${PROJECT_NAME} linking libraries : ${ARGN}") | |
| 7 | + | |
| 8 | +# Use CMAKE_BINARY_DIR by default, but override if necessary. | |
| 9 | +set(CURRENT_PROJECT_BINARY_DIR ${CMAKE_BINARY_DIR}) | |
| 10 | +if (${PROJECT_NAME}_CURRENT_BINARY_DIR) | |
| 11 | + set(CURRENT_PROJECT_BINARY_DIR ${${PROJECT_NAME}_CURRENT_BINARY_DIR}) | |
| 12 | +endif() | |
| 13 | +message(STATUS "CURRENT_PROJECT_BINARY_DIR : ${CURRENT_PROJECT_BINARY_DIR}") | |
| 14 | + | |
| 15 | +if( ${BUILD_STATIC} ) | |
| 16 | + if(${BUILD_STATIC} STREQUAL "ON") | |
| 17 | + set(SHARED_OR_STATIC "STATIC") | |
| 18 | + else() | |
| 19 | + set(SHARED_OR_STATIC "SHARED") | |
| 20 | + endif() | |
| 21 | +else() | |
| 22 | + set(SHARED_OR_STATIC "SHARED") | |
| 23 | +endif() | |
| 24 | + | |
| 25 | +add_library( ${PROJECT_NAME} ${SHARED_OR_STATIC} | |
| 26 | + ${SRC_LIST} | |
| 27 | +) | |
| 28 | + | |
| 29 | +target_link_libraries( ${PROJECT_NAME} | |
| 30 | + ${ARGN} | |
| 31 | +) | |
| 32 | + | |
| 33 | +set_target_properties( ${PROJECT_NAME} | |
| 34 | + PROPERTIES | |
| 35 | + VERSION ${PROJECT_VERSION} | |
| 36 | + SOVERSION ${PROJECT_VERSION_MAJOR} | |
| 37 | + LIBRARY_OUTPUT_DIRECTORY ${CURRENT_PROJECT_BINARY_DIR}/lib | |
| 38 | + ARCHIVE_OUTPUT_DIRECTORY ${CURRENT_PROJECT_BINARY_DIR}/lib | |
| 39 | +) | |
| 40 | + | |
| 41 | +endfunction() | ... | ... |
cmake/library.post_install.inc.cmake.in
0 → 100644
| 1 | +# Update the dynamic linker runtime bindings. | |
| 2 | +VAR1="/sbin/ldconfig" | |
| 3 | +VAR2=`which ldconfig` | |
| 4 | + | |
| 5 | +if [ -e $VAR1 ]; then | |
| 6 | + $VAR1 | |
| 7 | +elif [ ! -z $VAR2 ]; then | |
| 8 | + $VAR2 | |
| 9 | +else | |
| 10 | + VAR3=`find / -name ldconfig -type f` | |
| 11 | + if [ -e $VAR3 ]; then | |
| 12 | + $VAR3 | |
| 13 | + else | |
| 14 | + echo "ldconfig not found!!!" | |
| 15 | + fi | |
| 16 | +fi | ... | ... |
cmake/packaging.cmake
0 → 100644
| 1 | +set( PACKAGING_CURRENT_CMAKE_DIR ${CMAKE_CURRENT_LIST_DIR} ) | |
| 2 | + | |
| 3 | +# @brief Creates component packages. Can be executed by calling "make package". | |
| 4 | +function(package_component) | |
| 5 | + | |
| 6 | +# Determine build architecture | |
| 7 | +execute_process( | |
| 8 | + COMMAND uname -m | |
| 9 | + COMMAND tr -d '\n' | |
| 10 | + OUTPUT_VARIABLE ARCHITECTURE | |
| 11 | +) | |
| 12 | + | |
| 13 | +# Set package name | |
| 14 | +# Known issue: Due to the way cpack works (only evaluated once), the PROJECT_NAME will be the last package to | |
| 15 | +# call this function. We worked around this by including packaging.cmake only from 1 location in the repository. | |
| 16 | +# However, in a superbuild (i.e. from an mlogic parent directory building all repositories at once), | |
| 17 | +# this will yield an erroneous package name (usually datacollector, as that is the last project to be evaluated). | |
| 18 | +# In order to prevent dynamic package names caused by different build directories, | |
| 19 | +# The package name is set to a fixed value. The actual name of the rpm and package will be determined by | |
| 20 | +# other variable values such as the component name and version, leading to uniquely identifiable packages. | |
| 21 | +set(CPACK_PACKAGE_NAME osdev) | |
| 22 | + | |
| 23 | +# Set package version numbers | |
| 24 | +set(CPACK_PACKAGE_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}") | |
| 25 | +set(CPACK_PACKAGE_VERSION_MINOR "${PROJECT_VERSION_MINOR}") | |
| 26 | +set(CPACK_PACKAGE_VERSION_PATCH "${PROJECT_VERSION_PATCH}") | |
| 27 | +# The release number is not part of CPACK_PACKAGE_VERSION and is dealt with seperately (see below) | |
| 28 | +set(CPACK_PACKAGE_VERSION "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}") | |
| 29 | +message( STATUS "Packaging ${CPACK_PACKAGE_NAME} ${CPACK_PACKAGE_VERSION} for ${ARCHITECTURE}.") | |
| 30 | + | |
| 31 | +set(CPACK_PACKAGE_RELEASE "1") | |
| 32 | +if (CURRENT_PROJECT_VERSION_RELEASENR) | |
| 33 | + set(CPACK_PACKAGE_RELEASE ${CURRENT_PROJECT_VERSION_RELEASENR}) | |
| 34 | +endif() | |
| 35 | + | |
| 36 | +# Build CPack driven installer packages | |
| 37 | +include(InstallRequiredSystemLibraries) | |
| 38 | + | |
| 39 | +# This doesn't seem to work, only the specific archive variables (_RPM_, _DEB_) seem to work | |
| 40 | +#set(CPACK_ARCHIVE_COMPONENT_INSTALL ON) | |
| 41 | +set(CPACK_COMPONENTS_IGNORE_GROUPS 1) | |
| 42 | +# Enable the line below if the repository being built has only 1 target that's installed | |
| 43 | +# (No longer necessary, as we now have at least 2 components: runtime and development components.) | |
| 44 | +#set(CPACK_COMPONENTS_ALL ${CPACK_PACKAGE_NAME} ${CPACK_PACKAGE_NAME}-devel) | |
| 45 | + | |
| 46 | +# Enable DESTDIR and copy CMAKE_INSTALL_PREFIX, which requires disabling rpm relocatability | |
| 47 | +set(CPACK_SET_DESTDIR 1) | |
| 48 | +set(CPACK_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX}) | |
| 49 | +set(CPACK_PACKAGE_RELOCATABLE OFF) | |
| 50 | + | |
| 51 | +# Set package metadata | |
| 52 | +if (EXISTS "${PACKAGING_CURRENT_CMAKE_DIR}/../../../COPYING.OSDEV") | |
| 53 | + set(CPACK_RESOURCE_FILE_LICENSE "${PACKAGING_CURRENT_CMAKE_DIR}/../../../COPYING.OSDEV") | |
| 54 | +endif() | |
| 55 | +if (EXISTS "${PACKAGING_CURRENT_CMAKE_DIR}/../../../README.md") | |
| 56 | + set(CPACK_RESOURCE_FILE_README "${PACKAGING_CURRENT_CMAKE_DIR}/../../../README.md") | |
| 57 | +endif() | |
| 58 | +set(CPACK_SYSTEM_NAME "${ARCHITECTURE}") | |
| 59 | +set(CPACK_PACKAGE_FILE_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}.${CURRENT_PROJECT_VERSION_LETTER}-${CPACK_PACKAGE_RELEASE}.${ARCHITECTURE}") | |
| 60 | + | |
| 61 | +# RPM specific fields | |
| 62 | +set(CPACK_RPM_PACKAGE_ARCHITECTURE "${ARCHITECTURE}") | |
| 63 | +set(CPACK_RPM_COMPONENT_INSTALL ON) | |
| 64 | +set(CPACK_RPM_PACKAGE_GROUP "${CPACK_PACKAGE_NAME}-${REPOSITORY_PACKAGE_NAME}") | |
| 65 | +# Unfortunately, CPACK_RPM_PACKAGE_RELEASE isn't inherited from CPACK_PACKAGE_RELEASE automatically. | |
| 66 | +set(CPACK_RPM_PACKAGE_RELEASE ${CPACK_PACKAGE_RELEASE}) | |
| 67 | +set(CPACK_RPM_PACKAGE_VENDOR ${CURRENT_PROJECT_MANUFACTURER_CODE}) | |
| 68 | +set(CPACK_RPM_PACKAGE_SUMMARY "${CPACK_PACKAGE_NAME} package") | |
| 69 | +set(CPACK_RPM_PACKAGE_DESCRIPTION "${CPACK_RPM_PACKAGE_SUMMARY}") | |
| 70 | +set(CPACK_RPM_PACKAGE_LICENSE "${CURRENT_PROJECT_MANUFACTURER_CODE}") | |
| 71 | + | |
| 72 | +# Select CPack generators | |
| 73 | +set(CPACK_GENERATOR "RPM") | |
| 74 | + | |
| 75 | +# Exclude certain system directories from the rpm | |
| 76 | +set(CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION /usr;/etc;/etc/systemd;/var;${USR_LOCAL_DIR};${LD_SO_CONF_D_DIR};${SYSTEMD_CONFIG_DIR};${VAR_LOG_DIR};${VAR_RUN_DIR}) | |
| 77 | + | |
| 78 | +# This line should come last | |
| 79 | +include(CPack) | |
| 80 | + | |
| 81 | +endfunction(package_component) | ... | ... |
cmake/projectheader.cmake
0 → 100644
| 1 | +# @brief Defines the project name, version and binary dir. | |
| 2 | +# @param CURRENT_PROJECT_NAME The name of the project to define. | |
| 3 | +# @param CURRENT_PROJECT_BINARY_DIR [optional] Override for the default project binary dir (PROJECT_BINARY_DIR for executables, CMAKE_BINARY_DIR for libraries). | |
| 4 | +macro ( project_header CURRENT_PROJECT_NAME ) | |
| 5 | + | |
| 6 | +# Determine the version and fill the following variables : | |
| 7 | +# SOVERSION : The tag from the git-repository. Not necessarily a number-only string. | |
| 8 | +find_package(Git QUIET) | |
| 9 | + | |
| 10 | +if(GIT_FOUND) | |
| 11 | + if( EXISTS "${PROJECT_SOURCE_DIR}/.git") | |
| 12 | + execute_process(COMMAND ${GIT_EXECUTABLE} describe --abbrev=0 --tags | |
| 13 | + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} | |
| 14 | + OUTPUT_VARIABLE CURRENT_PROJECT_VERSION | |
| 15 | + OUTPUT_STRIP_TRAILING_WHITESPACE | |
| 16 | + RESULT_VARIABLE GIT_SUBMOD_RESULT) | |
| 17 | + | |
| 18 | + # Exit code will be 128 if no tags are present | |
| 19 | + if( ${GIT_SUBMOD_RESULT} EQUAL 128 ) | |
| 20 | + set(CURRENT_PROJECT_VERSION "0.0.1") | |
| 21 | + endif() | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + message( STATUS "================================================================" ) | |
| 26 | + message( STATUS "Found the following tag : ${CURRENT_PROJECT_VERSION}") | |
| 27 | + message( STATUS "================================================================" ) | |
| 28 | + else() | |
| 29 | + message( STATUS ".git directory does not exists..") | |
| 30 | + message( STATUS "Project directory : ${PROJECT_SOURCE_DIR}") | |
| 31 | + endif() | |
| 32 | +else() | |
| 33 | + message( STATUS "git-command not found....") | |
| 34 | + message( FATAL "Unable to determine the version of the software.") | |
| 35 | +endif() | |
| 36 | + | |
| 37 | + | |
| 38 | +message( STATUS "" ) | |
| 39 | +message( STATUS "================================================================" ) | |
| 40 | +message( STATUS "Creating Makefile of ${CURRENT_PROJECT_NAME}" ) | |
| 41 | +message( STATUS "================================================================" ) | |
| 42 | +message( STATUS "CURRENT_PROJECT_VERSION: ${CURRENT_PROJECT_VERSION}" ) | |
| 43 | + | |
| 44 | +set(SOVERSION "${CURRENT_PROJECT_VERSION}") | |
| 45 | +set(VERSION "${CURRENT_PROJECT_VERSION}") | |
| 46 | + | |
| 47 | +project(${CURRENT_PROJECT_NAME} VERSION ${CURRENT_PROJECT_VERSION}) | |
| 48 | +set_property(GLOBAL PROPERTY GLOBAL_DEPENDS_NO_CYCLES 1) | |
| 49 | + | |
| 50 | +set ( optional_macro_args ${ARGN} ) | |
| 51 | +list ( LENGTH optional_macro_args num_optional_args ) | |
| 52 | +if ( ${num_optional_args} GREATER 0 ) | |
| 53 | + # Set project binary dir override to the specified value | |
| 54 | + list ( GET optional_macro_args 0 CURRENT_PROJECT_BINARY_DIR ) | |
| 55 | + set ( ${PROJECT_NAME}_CURRENT_BINARY_DIR ${CURRENT_PROJECT_BINARY_DIR} CACHE STRING "${PROJECT_NAME} binary dir" FORCE ) | |
| 56 | +endif() | |
| 57 | + | |
| 58 | +endmacro() | ... | ... |
cmake/qtmoc.cmake
0 → 100644
| 1 | +# @brief Creates the qt5 mocs for the specified header files. | |
| 2 | +# @param SRC_LIST The current source list of the project, to which to add the created moc files. | |
| 3 | +# @param MOC_LIST The list of header files for which to create qt5 mocs. | |
| 4 | +macro(create_mocs SRC_LIST MOC_LIST) | |
| 5 | + | |
| 6 | +message( STATUS "${PROJECT_NAME} Creating mocs for: ${ARGN}") | |
| 7 | + | |
| 8 | +set( MOCABLE_LIST | |
| 9 | + ${ARGN} | |
| 10 | +) | |
| 11 | + | |
| 12 | +# Empty the MOC_LIST variable | |
| 13 | +set( ${MOC_LIST} | |
| 14 | +) | |
| 15 | + | |
| 16 | +# Create the MOC_LIST | |
| 17 | +QT6_WRAP_CPP( ${MOC_LIST} ${MOCABLE_LIST} ) | |
| 18 | + | |
| 19 | +# Append SRC_LIST with MOC_LIST | |
| 20 | +list ( APPEND SRC_LIST | |
| 21 | + ${${MOC_LIST}} | |
| 22 | +) | |
| 23 | + | |
| 24 | +message( STATUS "${PROJECT_NAME} MOC_LIST: ${${MOC_LIST}}") | |
| 25 | +message( STATUS "${PROJECT_NAME} SRC_LIST: ${${SRC_LIST}}") | |
| 26 | + | |
| 27 | +set_source_files_properties( | |
| 28 | + ${${MOC_LIST}} | |
| 29 | + PROPERTIES | |
| 30 | + COMPILE_FLAGS -Wno-undefined-reinterpret-cast | |
| 31 | +) | |
| 32 | + | |
| 33 | +endmacro() | ... | ... |
cmake/qtuic.cmake
0 → 100644
| 1 | +# @brief Creates the qt5 ui_ headers for the specified designer files. | |
| 2 | +# @param SRC_LIST The current source list of the project, to which to add the created moc files. | |
| 3 | +# @param UIC_LIST The list of designer files for which to create qt5 headers. | |
| 4 | +macro(create_ui SRC_LIST UIC_LIST) | |
| 5 | + | |
| 6 | +message( STATUS "${PROJECT_NAME} Creating headers for: ${ARGN}") | |
| 7 | + | |
| 8 | +set( UICABLE_LIST | |
| 9 | + ${ARGN} | |
| 10 | +) | |
| 11 | + | |
| 12 | +# Empty the UIC_LIST variable | |
| 13 | +set( ${UIC_LIST} | |
| 14 | +) | |
| 15 | + | |
| 16 | +# Create the UIC_LIST | |
| 17 | +QT5_WRAP_UI( ${UIC_LIST} ${UICABLE_LIST} ) | |
| 18 | + | |
| 19 | +# Append SRC_LIST with UIC_LIST | |
| 20 | +list ( APPEND SRC_LIST | |
| 21 | + ${${UIC_LIST}} | |
| 22 | +) | |
| 23 | + | |
| 24 | +# Avoid warnings by including a generated header file. | |
| 25 | +include_directories( ${SYSTEMORNOT} | |
| 26 | + ${CMAKE_CURRENT_BINARY_DIR} | |
| 27 | + ${CMAKE_SOURCE_DIR} | |
| 28 | +) | |
| 29 | + | |
| 30 | +message( STATUS "${PROJECT_NAME} UIC_LIST: ${${UIC_LIST}}") | |
| 31 | +message( STATUS "${PROJECT_NAME} SRC_LIST: ${${SRC_LIST}}") | |
| 32 | + | |
| 33 | +set_source_files_properties( | |
| 34 | + ${${UIC_LIST}} | |
| 35 | + PROPERTIES | |
| 36 | + COMPILE_FLAGS -Wno-undefined-reinterpret-cast | |
| 37 | +) | |
| 38 | + | |
| 39 | +endmacro() | ... | ... |
cmake/service.cmake.in
0 → 100644
| 1 | +[Unit] | |
| 2 | +Description=Mlogic @PROJECT_NAME@ | |
| 3 | +After=network.target | |
| 4 | + | |
| 5 | +[Service] | |
| 6 | +WorkingDirectory=@CMAKE_INSTALL_PREFIX@/@PROJECT_NAME@/ | |
| 7 | +ExecStart=@CMAKE_INSTALL_PREFIX@/@PROJCOMP_BIN_INSTALL_DIR@/@PROJECT_NAME@ | |
| 8 | +User=@PROJECT_NAME@ | |
| 9 | + | |
| 10 | +[Install] | |
| 11 | +WantedBy=multi-user.target | ... | ... |
cmake/sync.sh
0 → 100755
| 1 | +#!/bin/bash | |
| 2 | + | |
| 3 | +# $1: cmake-file-filename | |
| 4 | +function sync-file() | |
| 5 | +{ | |
| 6 | + echo ---------- Syncing $1 started | |
| 7 | + | |
| 8 | + cp -f ../../mlogic_support/cmake/$1 $1 | |
| 9 | + if [ $? -ne 0 ] ; then | |
| 10 | + echo ---------- Syncing $1 failed | |
| 11 | + return 1 | |
| 12 | + fi | |
| 13 | + | |
| 14 | + echo ---------- Syncing $1 finished | |
| 15 | +} | |
| 16 | + | |
| 17 | +# We don't copy installation.cmake, because the includes files are in the src folder. | |
| 18 | +# datacollector is different in this respect from the other repositories. | |
| 19 | +MLOGIC_CMAKE_FILES="artifacts.cmake | |
| 20 | +compiler.cmake | |
| 21 | +config.cmake.in | |
| 22 | +FindGMock.cmake | |
| 23 | +library.cmake | |
| 24 | +packaging.cmake | |
| 25 | +projectheader.cmake | |
| 26 | +qtmoc.cmake" | |
| 27 | + | |
| 28 | +# Process the cmake files | |
| 29 | +cd $(dirname $(readlink -f $0)) || exit 1 | |
| 30 | +for cmake_file in ${MLOGIC_CMAKE_FILES} | |
| 31 | +do | |
| 32 | + sync-file ${cmake_file} | |
| 33 | +done | ... | ... |
cmake/targetprops.cmake
0 → 100644
include/daemonbase.h
0 → 100644
| 1 | +/* **************************************************************************** | |
| 2 | + * Copyright 2019 Open Systems Development BV * | |
| 3 | + * * | |
| 4 | + * Permission is hereby granted, free of charge, to any person obtaining a * | |
| 5 | + * copy of this software and associated documentation files (the "Software"), * | |
| 6 | + * to deal in the Software without restriction, including without limitation * | |
| 7 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, * | |
| 8 | + * and/or sell copies of the Software, and to permit persons to whom the * | |
| 9 | + * Software is furnished to do so, subject to the following conditions: * | |
| 10 | + * * | |
| 11 | + * The above copyright notice and this permission notice shall be included in * | |
| 12 | + * all copies or substantial portions of the Software. * | |
| 13 | + * * | |
| 14 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * | |
| 15 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * | |
| 16 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * | |
| 17 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * | |
| 18 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * | |
| 19 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * | |
| 20 | + * DEALINGS IN THE SOFTWARE. * | |
| 21 | + * ****************************************************************************/ | |
| 22 | +#pragma once | |
| 23 | + | |
| 24 | +#include <cstdlib> | |
| 25 | +#include <iostream> | |
| 26 | +#include <sys/types.h> | |
| 27 | +#include <unistd.h> | |
| 28 | +#include <cerrno> | |
| 29 | +#include <cstring> | |
| 30 | +#include <string> | |
| 31 | +#include <csignal> | |
| 32 | +#include <sys/stat.h> | |
| 33 | +#include <stdexcept> | |
| 34 | +#include <chrono> | |
| 35 | +#include <thread> | |
| 36 | +#include <atomic> | |
| 37 | +#include <condition_variable> | |
| 38 | + | |
| 39 | +#include "daemonlog.h" | |
| 40 | +#include "daemonconfig.h" | |
| 41 | + | |
| 42 | +namespace osdev::components::daemon | |
| 43 | +{ | |
| 44 | +class DaemonBase | |
| 45 | +{ | |
| 46 | +private: | |
| 47 | + static DaemonBase *instance; | |
| 48 | + | |
| 49 | +public: | |
| 50 | + /** | |
| 51 | + * Construct a new daemon process. | |
| 52 | + * @note: only one daemon per application is possible. | |
| 53 | + * @param name: name of daemon process | |
| 54 | + * @param cwd: daemon current working directory, root "/" directory by default. | |
| 55 | + * @param update_duration: duration to sleep before waking up the on_update() callback every time, deafult 10 seconds. | |
| 56 | + */ | |
| 57 | + DaemonBase(const std::string &name, | |
| 58 | + const std::string &cwd = "/", | |
| 59 | + const std::chrono::high_resolution_clock::duration &update_duration = std::chrono::seconds(10)) | |
| 60 | + : m_name(name) | |
| 61 | + , m_cwd(cwd) | |
| 62 | + , m_update_duration(update_duration) | |
| 63 | + , m_is_running(false) | |
| 64 | + , m_exit_code(EXIT_SUCCESS) | |
| 65 | + { | |
| 66 | + if (instance) | |
| 67 | + { | |
| 68 | + daemonlog::error("Only one daemon instance is possible."); | |
| 69 | + std::exit(EXIT_FAILURE); | |
| 70 | + } | |
| 71 | + instance = this; | |
| 72 | + } | |
| 73 | + | |
| 74 | + DaemonBase() | |
| 75 | + : m_name("<unknown_daemon>") | |
| 76 | + , m_cwd("/") | |
| 77 | + , m_update_duration(std::chrono::seconds(10)) | |
| 78 | + , m_is_running(false) | |
| 79 | + { | |
| 80 | + if(instance) | |
| 81 | + { | |
| 82 | + daemonlog::error("Only one daemon instance is possible."); | |
| 83 | + std::exit(EXIT_FAILURE); | |
| 84 | + } | |
| 85 | + instance = this; | |
| 86 | + } | |
| 87 | + | |
| 88 | + void run(int argc, char *argv[]) | |
| 89 | + { | |
| 90 | + if (m_is_running.load()) | |
| 91 | + { | |
| 92 | + daemonlog::error("Daemon '" + m_name + "' is already running."); | |
| 93 | + return; | |
| 94 | + } | |
| 95 | + | |
| 96 | + // Get config file path from cmd args passed by ExecStart=/usr/bin/my_daemon --config /etc/my_daemon/my_daemon.conf | |
| 97 | + // since we need it for a reload./ | |
| 98 | + for (std::int32_t i = 0; i < argc; i++) | |
| 99 | + { | |
| 100 | + if (!std::strcmp(argv[i], "--config")) | |
| 101 | + { | |
| 102 | + if (i + 1 < argc) | |
| 103 | + { | |
| 104 | + m_config_file = argv[i + 1]; | |
| 105 | + } | |
| 106 | + else | |
| 107 | + { | |
| 108 | + daemonlog::error("Missing config file. Did ytou forget to specify a config file in your .serve file's ExecStart ?"); | |
| 109 | + } | |
| 110 | + break; | |
| 111 | + } | |
| 112 | + } | |
| 113 | + | |
| 114 | + // daemonize this program by forking the parent process. | |
| 115 | + daemonize(); | |
| 116 | + | |
| 117 | + // Mark as running (better to have it before on_start() as a user may call stop() inside on_start()). | |
| 118 | + m_is_running = true; | |
| 119 | + on_start(daemonconfig::from_file(m_config_file)); | |
| 120 | + while (m_is_running.load()) | |
| 121 | + { | |
| 122 | + on_update(); | |
| 123 | + | |
| 124 | + // On long sleeps, if we want to exit we need a condition_variable to wake up the thread from sleep to carry on exiting. | |
| 125 | + std::unique_lock<std::mutex> lock(m_mutex); | |
| 126 | + m_update_cv.wait_for(lock, m_update_duration, [this]() | |
| 127 | + { | |
| 128 | + return !m_is_running.load(); | |
| 129 | + }); | |
| 130 | + } | |
| 131 | + on_stop(); | |
| 132 | + } | |
| 133 | + | |
| 134 | + void stop(std::int32_t code = EXIT_SUCCESS) | |
| 135 | + { | |
| 136 | + m_exit_code = code; | |
| 137 | + m_is_running.store(false); | |
| 138 | + m_update_cv.notify_all(); | |
| 139 | + } | |
| 140 | + | |
| 141 | + virtual ~DaemonBase() | |
| 142 | + { | |
| 143 | + daemonlog::shutdown(); | |
| 144 | + // Terminate the child process when the daemon completes (loop stopped) | |
| 145 | + // @note that calling std::exit() inside the run function will not call DTor, | |
| 146 | + std::exit(m_exit_code); | |
| 147 | + } | |
| 148 | + | |
| 149 | + // Getters & Setters | |
| 150 | + void set_update_duration(const std::chrono::high_resolution_clock::duration &duration) noexcept | |
| 151 | + { m_update_duration = duration; } | |
| 152 | + | |
| 153 | + const std::chrono::high_resolution_clock::duration& get_update_duration() const noexcept | |
| 154 | + { return m_update_duration; } | |
| 155 | + | |
| 156 | + void set_name(const std::string &daemon_name) noexcept | |
| 157 | + { m_name = daemon_name; } | |
| 158 | + | |
| 159 | + const std::string& get_name() const noexcept | |
| 160 | + { return m_name; } | |
| 161 | + | |
| 162 | + void set_cwd(const std::string ¤t_working_dir) noexcept | |
| 163 | + { | |
| 164 | + // Change the current working directory to a directory guaranteed to exist, provided by the user. | |
| 165 | + if (chdir(current_working_dir.c_str()) < 0) | |
| 166 | + { | |
| 167 | + daemonlog::error("Could not change current working directory to'" | |
| 168 | + + current_working_dir + "': " | |
| 169 | + + std::string(std::strerror(errno))); | |
| 170 | + return; | |
| 171 | + } | |
| 172 | + m_cwd = current_working_dir; | |
| 173 | + } | |
| 174 | + | |
| 175 | + const std::string& get_cwd() const noexcept { return m_cwd; } | |
| 176 | + | |
| 177 | + pid_t get_pid() const noexcept { return m_pid; } | |
| 178 | + pid_t get_sid() const noexcept { return m_sid; } | |
| 179 | + | |
| 180 | +protected: // Callbacks | |
| 181 | + /** | |
| 182 | + * @brief Called once on daemon starts | |
| 183 | + * @scenarios: | |
| 184 | + * - when system starts | |
| 185 | + * - when you run `$ systemctl start your_daemon` manually | |
| 186 | + * @param cfg: Installed daemon config file | |
| 187 | + * Initialize your code here... | |
| 188 | + */ | |
| 189 | + virtual void on_start(const daemonconfig &cfg) = 0; | |
| 190 | + | |
| 191 | + /** | |
| 192 | + * @brief Called every DURATION which was set by set_update_duration(DURATION). | |
| 193 | + * Update your code here... | |
| 194 | + */ | |
| 195 | + virtual void on_update() = 0; | |
| 196 | + | |
| 197 | + /** | |
| 198 | + * @brief Called once before daemon is about to exit. | |
| 199 | + * @scenarios: | |
| 200 | + * - when you call stop(ewxit_code) | |
| 201 | + * - when you run `$ systemctl stop your_daemon` manually | |
| 202 | + * - when the system kills your daemon for some reason | |
| 203 | + * Cleanup your code here... | |
| 204 | + */ | |
| 205 | + virtual void on_stop() = 0; | |
| 206 | + | |
| 207 | + /** | |
| 208 | + * @brief Called once when daemon's config or service files are updated. | |
| 209 | + * @scenarios: | |
| 210 | + * - when you run `$systemctl daemon-reload` after you have changed your .conf or .service files | |
| 211 | + * (after reinstalling your daemon with `$ sudo make install` for example) | |
| 212 | + * Reinitialize your code here... | |
| 213 | + */ | |
| 214 | + virtual void on_reload(const daemonconfig &cfg) = 0; | |
| 215 | + | |
| 216 | +private: | |
| 217 | + static void signal_handler(std::int32_t sig) | |
| 218 | + { | |
| 219 | + daemonlog::info("Signal " + std::to_string(sig) + " received."); | |
| 220 | + | |
| 221 | + switch(sig) | |
| 222 | + { | |
| 223 | + // daemon.service handler : ExecStop=/bin/kill -s SIGTERM $MAINPID | |
| 224 | + // When daemon is stopped, system sends SIGTERM first. | |
| 225 | + // If daemon didn't respond during 90 seconds, it will send a SIGKILL signal | |
| 226 | + case SIGTERM: | |
| 227 | + case SIGKILL: | |
| 228 | + { | |
| 229 | + instance->stop(); | |
| 230 | + break; | |
| 231 | + } | |
| 232 | + // daemon.service handler : ExecReload=/bin/kill -S SIGHUB $MAINPID | |
| 233 | + // When a daemon is reloaded due updates in .service or .conf, system sends SIGHUP signal. | |
| 234 | + case SIGHUP: | |
| 235 | + { | |
| 236 | + instance->on_reload(daemonconfig::from_file(instance->m_config_file)); | |
| 237 | + break; | |
| 238 | + } | |
| 239 | + default: | |
| 240 | + { | |
| 241 | + break; | |
| 242 | + } | |
| 243 | + } | |
| 244 | + } | |
| 245 | + | |
| 246 | + /** | |
| 247 | + * @brief Daemonize this program | |
| 248 | + * @note: It is also possible to use glibc function daemon() | |
| 249 | + * at this point, but it is useful to customize your daemon. | |
| 250 | + * Like for example handle signals, set working directory... | |
| 251 | + */ | |
| 252 | + void daemonize() | |
| 253 | + { | |
| 254 | + // Fork off the parent process (https://linux.die.net/man/3/fork) | |
| 255 | + m_pid = fork(); | |
| 256 | + // Success: The parent process continues with a PID > 0 | |
| 257 | + if (m_pid > 0) | |
| 258 | + { | |
| 259 | + std::exit(EXIT_SUCCESS); | |
| 260 | + } | |
| 261 | + else if (m_pid < 0) | |
| 262 | + { | |
| 263 | + // An error occurred. A process ID lower than 0 indicates a failure in either process | |
| 264 | + std::exit(EXIT_FAILURE); | |
| 265 | + } | |
| 266 | + // The parent process has now terminated, and the forked child process will continue | |
| 267 | + // (the pid of the child process was 0) | |
| 268 | + | |
| 269 | + // Since the child process is a daemon, the unask needs to be set so files and logs can be written | |
| 270 | + umask(0); | |
| 271 | + | |
| 272 | + // Initialize syslog for this daemon, here it's a good place to do so. | |
| 273 | + daemonlog::init(m_name); | |
| 274 | + | |
| 275 | + // On success: The child process becomes session leader. Generate a session ID for the child process. | |
| 276 | + m_sid = setsid(); | |
| 277 | + if (m_sid < 0) | |
| 278 | + { | |
| 279 | + daemonlog::error("Could not set SID to child process: " + std::string(std::strerror(errno))); | |
| 280 | + std::exit(EXIT_FAILURE); | |
| 281 | + } | |
| 282 | + | |
| 283 | + // Ignore the Child terminated or stopped signal. | |
| 284 | + std::signal(SIGCHLD, SIG_IGN); | |
| 285 | + | |
| 286 | + // Set signal handlers to detect daemon interrupt, restart.. | |
| 287 | + std::signal(SIGHUP, signal_handler); | |
| 288 | + | |
| 289 | + // When a sudo systemctl stop my_daemon is ran, by default, a SIGTERM is sent, | |
| 290 | + // followed by 90 seconds of waiting followed by a SIGKILL | |
| 291 | + std::signal(SIGTERM, signal_handler); | |
| 292 | + std::signal(SIGKILL, signal_handler); | |
| 293 | + | |
| 294 | + // Change the current working directory to a directory guaranteed to exist, procided by the user | |
| 295 | + if (chdir(m_cwd.c_str()) < 0) | |
| 296 | + { | |
| 297 | + daemonlog::error("Could not change current working directory to `" + m_cwd + "': " + std::string(std::strerror(errno))); | |
| 298 | + std::exit(EXIT_FAILURE); | |
| 299 | + } | |
| 300 | + | |
| 301 | + // A daemon cannot use the terminal, so close standard file descriptors for security reasons | |
| 302 | + close(STDIN_FILENO); | |
| 303 | + close(STDOUT_FILENO); | |
| 304 | + close(STDERR_FILENO); | |
| 305 | + } | |
| 306 | + | |
| 307 | + // Member variables | |
| 308 | + pid_t m_pid; | |
| 309 | + pid_t m_sid; | |
| 310 | + std::string m_config_file; | |
| 311 | + std::string m_name; | |
| 312 | + std::string m_cwd; | |
| 313 | + std::chrono::high_resolution_clock::duration m_update_duration; | |
| 314 | + std::atomic<bool> m_is_running; | |
| 315 | + std::condition_variable m_update_cv; | |
| 316 | + std::mutex m_mutex; | |
| 317 | + std::int32_t m_exit_code; | |
| 318 | + | |
| 319 | +}; | |
| 320 | + | |
| 321 | +DaemonBase* DaemonBase::instance = nullptr; | |
| 322 | + | |
| 323 | +} /* End namespace osdev::components::daemon */ | |
| 0 | 324 | \ No newline at end of file | ... | ... |
include/daemonconfig.h
0 → 100644
| 1 | +/* **************************************************************************** | |
| 2 | + * Copyright 2019 Open Systems Development BV * | |
| 3 | + * * | |
| 4 | + * Permission is hereby granted, free of charge, to any person obtaining a * | |
| 5 | + * copy of this software and associated documentation files (the "Software"), * | |
| 6 | + * to deal in the Software without restriction, including without limitation * | |
| 7 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, * | |
| 8 | + * and/or sell copies of the Software, and to permit persons to whom the * | |
| 9 | + * Software is furnished to do so, subject to the following conditions: * | |
| 10 | + * * | |
| 11 | + * The above copyright notice and this permission notice shall be included in * | |
| 12 | + * all copies or substantial portions of the Software. * | |
| 13 | + * * | |
| 14 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * | |
| 15 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * | |
| 16 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * | |
| 17 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * | |
| 18 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * | |
| 19 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * | |
| 20 | + * DEALINGS IN THE SOFTWARE. * | |
| 21 | + * ****************************************************************************/ | |
| 22 | +#pragma once | |
| 23 | + | |
| 24 | +#include <fstream> | |
| 25 | +#include <cstring> | |
| 26 | +#include <string> | |
| 27 | +#include <vector> | |
| 28 | +#include <sstream> | |
| 29 | +#include <iostream> | |
| 30 | +#include <algorithm> | |
| 31 | +#include <map> | |
| 32 | + | |
| 33 | +#include "daemonlog.h" | |
| 34 | + | |
| 35 | +// TODO: Do a better config parsing. | |
| 36 | +namespace osdev::components::daemon | |
| 37 | +{ | |
| 38 | + struct daemonconfig | |
| 39 | + { | |
| 40 | + std::map<std::string, std::string> values; | |
| 41 | + | |
| 42 | + std::string get(const std::string &key) const | |
| 43 | + { | |
| 44 | + auto it = values.find(key); | |
| 45 | + if (it != values.end()) | |
| 46 | + { | |
| 47 | + return it->second; | |
| 48 | + } | |
| 49 | + return ""; | |
| 50 | + } | |
| 51 | + | |
| 52 | + static daemonconfig from_file(const std::string &filename) | |
| 53 | + { | |
| 54 | + daemonconfig cfg; | |
| 55 | + if (filename.empty()) | |
| 56 | + { | |
| 57 | + return cfg; | |
| 58 | + } | |
| 59 | + | |
| 60 | + auto split = [](const std::string &str, char delim) | |
| 61 | + { | |
| 62 | + std::vector<std::string> parts; | |
| 63 | + std::stringstream oss(str); | |
| 64 | + std::string part; | |
| 65 | + while (std::getline(oss, part, delim)) | |
| 66 | + { | |
| 67 | + parts.push_back(part); | |
| 68 | + } | |
| 69 | + return parts; | |
| 70 | + }; | |
| 71 | + | |
| 72 | + auto trim = [](std::string &s) | |
| 73 | + { | |
| 74 | + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](unsigned char ch){ return !std::isspace(ch);})); | |
| 75 | + s.erase(std::find_if(s.rbegin(), s.rend(), [](unsigned char ch){return !std::isspace(ch);}).base(), s.end()); | |
| 76 | + }; | |
| 77 | + | |
| 78 | + std::ifstream ifs{filename}; | |
| 79 | + std::string line; | |
| 80 | + | |
| 81 | + while(std::getline(ifs, line)) | |
| 82 | + { | |
| 83 | + trim(line); | |
| 84 | + if (line.empty()) // skip empty lines | |
| 85 | + { | |
| 86 | + continue; | |
| 87 | + } | |
| 88 | + | |
| 89 | + if (line[0] == '#') // skip comments | |
| 90 | + { | |
| 91 | + continue; | |
| 92 | + } | |
| 93 | + | |
| 94 | + auto parts = split(line, '='); | |
| 95 | + std::string key = parts[0]; | |
| 96 | + std::string value = parts[1]; | |
| 97 | + trim(key); | |
| 98 | + trim(value); | |
| 99 | + cfg.values[key] = value; | |
| 100 | + } | |
| 101 | + ifs.close(); | |
| 102 | + return cfg; | |
| 103 | + } | |
| 104 | + }; | |
| 105 | +} | |
| 0 | 106 | \ No newline at end of file | ... | ... |
include/daemonlog.h
0 → 100644
| 1 | +/* **************************************************************************** | |
| 2 | + * Copyright 2019 Open Systems Development BV * | |
| 3 | + * * | |
| 4 | + * Permission is hereby granted, free of charge, to any person obtaining a * | |
| 5 | + * copy of this software and associated documentation files (the "Software"), * | |
| 6 | + * to deal in the Software without restriction, including without limitation * | |
| 7 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, * | |
| 8 | + * and/or sell copies of the Software, and to permit persons to whom the * | |
| 9 | + * Software is furnished to do so, subject to the following conditions: * | |
| 10 | + * * | |
| 11 | + * The above copyright notice and this permission notice shall be included in * | |
| 12 | + * all copies or substantial portions of the Software. * | |
| 13 | + * * | |
| 14 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * | |
| 15 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * | |
| 16 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * | |
| 17 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * | |
| 18 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * | |
| 19 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * | |
| 20 | + * DEALINGS IN THE SOFTWARE. * | |
| 21 | + * ****************************************************************************/ | |
| 22 | +#pragma once | |
| 23 | + | |
| 24 | +#include <sys/syslog.h> | |
| 25 | +#include <syslog.h> | |
| 26 | +#include <cstdio> | |
| 27 | +#include <string> | |
| 28 | + | |
| 29 | +namespace osdev::components::daemon { | |
| 30 | + | |
| 31 | +class daemonlog | |
| 32 | +{ | |
| 33 | +public: | |
| 34 | + /** | |
| 35 | + * Initialize the logger | |
| 36 | + * @param daemon_name | |
| 37 | + */ | |
| 38 | + static void init(const std::string &daemon_name) | |
| 39 | + { | |
| 40 | + // m_daemon_name = daemon_name; | |
| 41 | + openlog(daemon_name.c_str(), LOG_PID, LOG_DAEMON); | |
| 42 | + } | |
| 43 | + | |
| 44 | + /** | |
| 45 | + * main logger with priority LOG_X | |
| 46 | + * @param message | |
| 47 | + * @param priority | |
| 48 | + */ | |
| 49 | + static void log(const std::string &message, std::int32_t priority) | |
| 50 | + { | |
| 51 | + syslog(priority, "%s", message.c_str()); | |
| 52 | + } | |
| 53 | + | |
| 54 | + /** | |
| 55 | + * debug-level messages | |
| 56 | + * @param message | |
| 57 | + */ | |
| 58 | + static void debug(const std::string &message) | |
| 59 | + { | |
| 60 | + log(message, LOG_DEBUG); | |
| 61 | + } | |
| 62 | + | |
| 63 | + /** | |
| 64 | + * informational | |
| 65 | + * @param message | |
| 66 | + */ | |
| 67 | + static void info(const std::string &message) | |
| 68 | + { | |
| 69 | + log(message, LOG_INFO); | |
| 70 | + } | |
| 71 | + | |
| 72 | + /** | |
| 73 | + * normal but significant condition | |
| 74 | + * @param message | |
| 75 | + */ | |
| 76 | + static void notice(const std::string &message) | |
| 77 | + { | |
| 78 | + log(message, LOG_NOTICE); | |
| 79 | + } | |
| 80 | + | |
| 81 | + /** | |
| 82 | + * Warning conditions | |
| 83 | + * @param message | |
| 84 | + */ | |
| 85 | + static void warning(const std::string &message) | |
| 86 | + { | |
| 87 | + log(message, LOG_WARNING); | |
| 88 | + } | |
| 89 | + | |
| 90 | + /** | |
| 91 | + * error conditions | |
| 92 | + * @param message | |
| 93 | + */ | |
| 94 | + static void error(const std::string &message) | |
| 95 | + { | |
| 96 | + log(message, LOG_ERR); | |
| 97 | + } | |
| 98 | + | |
| 99 | + /** | |
| 100 | + * critical conditions | |
| 101 | + * @param message | |
| 102 | + */ | |
| 103 | + static void critical(const std::string &message) | |
| 104 | + { | |
| 105 | + log(message, LOG_CRIT); | |
| 106 | + } | |
| 107 | + | |
| 108 | + /** | |
| 109 | + * action must be taken immediately | |
| 110 | + * @param message | |
| 111 | + */ | |
| 112 | + static void alert(const std::string &message) | |
| 113 | + { | |
| 114 | + log(message, LOG_ALERT); | |
| 115 | + } | |
| 116 | + | |
| 117 | + /** | |
| 118 | + * system is unusable | |
| 119 | + * @param message | |
| 120 | + */ | |
| 121 | + static void emergency(const std::string &message) | |
| 122 | + { | |
| 123 | + log(message, LOG_EMERG); | |
| 124 | + } | |
| 125 | + | |
| 126 | + /** | |
| 127 | + * shutdown the logger | |
| 128 | + */ | |
| 129 | + static void shutdown() | |
| 130 | + { | |
| 131 | + closelog(); | |
| 132 | + } | |
| 133 | + | |
| 134 | +private: | |
| 135 | + static std::string priority_str(std::int32_t priority) | |
| 136 | + { | |
| 137 | + switch(priority) | |
| 138 | + { | |
| 139 | + case LOG_EMERG: return "emergency"; | |
| 140 | + case LOG_ALERT: return "alert"; | |
| 141 | + case LOG_CRIT: return "critical"; | |
| 142 | + case LOG_ERR: return "error"; | |
| 143 | + case LOG_WARNING: return "warning"; | |
| 144 | + case LOG_NOTICE: return "notice"; | |
| 145 | + case LOG_INFO: return "info"; | |
| 146 | + case LOG_DEBUG: return "debug"; | |
| 147 | + default: return "unknown_priority"; | |
| 148 | + } | |
| 149 | + } | |
| 150 | + | |
| 151 | + std::string m_daemon_name; | |
| 152 | + | |
| 153 | +}; | |
| 154 | + | |
| 155 | +// std::string osdev::components::daemon::m_daemon_name{}; | |
| 156 | + | |
| 157 | +} | |
| 0 | 158 | \ No newline at end of file | ... | ... |
test/CMakeLists.txt
0 → 100644
| 1 | +# | |
| 2 | +# Don't call this file directly from cmake. | |
| 3 | +# TRhis file is included from the upper directory. | |
| 4 | +# | |
| 5 | +# Build rules for the daemon library | |
| 6 | + | |
| 7 | +add_executable(MyExampleDaemon | |
| 8 | + MyDaemonExample.cpp | |
| 9 | +) | |
| 10 | + | |
| 11 | +target_include_directories(MyExampleDaemon PRIVATE | |
| 12 | + ${CMAKE_CURRENT_SOURCE_DIR} | |
| 13 | + ../include | |
| 14 | +) | |
| 15 | + | |
| 16 | +target_link_libraries(MyExampleDaemon PRIVATE | |
| 17 | + daemonbase | |
| 18 | +) | |
| 0 | 19 | \ No newline at end of file | ... | ... |
test/MyDaemonExample.cpp
0 → 100644
| 1 | +/* **************************************************************************** | |
| 2 | + * Copyright 2019 Open Systems Development BV * | |
| 3 | + * * | |
| 4 | + * Permission is hereby granted, free of charge, to any person obtaining a * | |
| 5 | + * copy of this software and associated documentation files (the "Software"), * | |
| 6 | + * to deal in the Software without restriction, including without limitation * | |
| 7 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, * | |
| 8 | + * and/or sell copies of the Software, and to permit persons to whom the * | |
| 9 | + * Software is furnished to do so, subject to the following conditions: * | |
| 10 | + * * | |
| 11 | + * The above copyright notice and this permission notice shall be included in * | |
| 12 | + * all copies or substantial portions of the Software. * | |
| 13 | + * * | |
| 14 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * | |
| 15 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * | |
| 16 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * | |
| 17 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * | |
| 18 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * | |
| 19 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * | |
| 20 | + * DEALINGS IN THE SOFTWARE. * | |
| 21 | + * ****************************************************************************/ | |
| 22 | +#include "daemonbase.h" | |
| 23 | +#include <cstdlib> | |
| 24 | + | |
| 25 | +using namespace osdev::components::daemon; | |
| 26 | +using namespace std::chrono_literals; | |
| 27 | + | |
| 28 | +class MyExampleDaemon : public DaemonBase | |
| 29 | +{ | |
| 30 | +public: | |
| 31 | + void on_start(const daemonconfig &config) override | |
| 32 | + { | |
| 33 | + /// Called once after daemon starts automatically with system startup | |
| 34 | + /// or when you manually call `$ system,ctl start MyExampleDaemon` | |
| 35 | + | |
| 36 | + /// Initialize your code here... | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + daemonlog::info("MyExampleDaemon::on_start(): MyExampleDaemon version: " + config.get("version") + " started successfully!"); | |
| 41 | + } | |
| 42 | + | |
| 43 | + void on_update() override | |
| 44 | + { | |
| 45 | + /// Called every DURATION set in set_update_duration()... | |
| 46 | + | |
| 47 | + /// Update your code here | |
| 48 | + | |
| 49 | + daemonlog::info("MyExampleDaemon::on_update()"); | |
| 50 | + } | |
| 51 | + | |
| 52 | + void on_stop() override | |
| 53 | + { | |
| 54 | + /// Called once before daemon is about to exit with system shutdown or when you manually call `$ systemctl stop MyExampleDaemon` | |
| 55 | + /// Cleanup your code here... | |
| 56 | + | |
| 57 | + daemonlog::info("MyExampleDaemon::on_stop()"); | |
| 58 | + } | |
| 59 | + | |
| 60 | + void on_reload(const daemonconfig &cfg) override | |
| 61 | + { | |
| 62 | + /// Called once after your daemon's config fil is updated then reloaded with `$ systemctl reload MyExampleDaemon` | |
| 63 | + /// Handle your config updates here... | |
| 64 | + | |
| 65 | + daemonlog::info("MyExampleDaemon::on_reload(): new daemon version from updated config: " + cfg.get("version")); | |
| 66 | + } | |
| 67 | +}; | |
| 68 | + | |
| 69 | + | |
| 70 | +int main(int argc, char *argv[]) | |
| 71 | +{ | |
| 72 | + MyExampleDaemon oDaemon; // Create the daemon instance. | |
| 73 | + | |
| 74 | + oDaemon.set_name("MyAweSomeExampleDaemon"); // Set daemon name to identify logs in syslog | |
| 75 | + oDaemon.set_update_duration(3s); // Set duration to sleep before triggering the on_update callback 3 seconds. | |
| 76 | + oDaemon.set_cwd("/root"); // set daemon's current working directory to roots home-folder | |
| 77 | + oDaemon.run(argc, argv); // run the daemon | |
| 78 | + | |
| 79 | + return(EXIT_SUCCESS); // Close the main process now the child process is running. | |
| 80 | +} | |
| 0 | 81 | \ No newline at end of file | ... | ... |