diff options
author | Milan Crha <mcrha@redhat.com> | 2016-10-10 14:46:59 +0200 |
---|---|---|
committer | Milan Crha <mcrha@redhat.com> | 2016-10-10 14:46:59 +0200 |
commit | 3cba4951951a40e299296b0a401f9406ac3ac9a2 (patch) | |
tree | fddbd053e47e446b2fee9b3ee7bfe0a0e2252b9a /cmake | |
parent | dad728dfd69aaba8edfe84a8f922a012dbad32ac (diff) | |
download | evolution-3cba4951951a40e299296b0a401f9406ac3ac9a2.tar.gz |
Convert from autotools to CMake
Diffstat (limited to 'cmake')
-rw-r--r-- | cmake/cmake_uninstall.cmake.in | 21 | ||||
-rw-r--r-- | cmake/modules/CheckTarget.cmake | 21 | ||||
-rw-r--r-- | cmake/modules/CodeCoverageGCOV.cmake | 45 | ||||
-rw-r--r-- | cmake/modules/DistTargets.cmake | 87 | ||||
-rw-r--r-- | cmake/modules/EvolutionMacros.cmake | 63 | ||||
-rw-r--r-- | cmake/modules/FindIntltool.cmake | 209 | ||||
-rw-r--r-- | cmake/modules/FindLDAP.cmake | 133 | ||||
-rw-r--r-- | cmake/modules/FindSMIME.cmake | 146 | ||||
-rw-r--r-- | cmake/modules/GLibTools.cmake | 277 | ||||
-rw-r--r-- | cmake/modules/GtkDoc.cmake | 150 | ||||
-rw-r--r-- | cmake/modules/IconCache.cmake | 74 | ||||
-rw-r--r-- | cmake/modules/InstalledTests.cmake | 88 | ||||
-rw-r--r-- | cmake/modules/PkgConfigEx.cmake | 90 | ||||
-rw-r--r-- | cmake/modules/PrintableOptions.cmake | 74 | ||||
-rw-r--r-- | cmake/modules/SetupBuildFlags.cmake | 80 | ||||
-rw-r--r-- | cmake/modules/UninstallTarget.cmake | 13 | ||||
-rwxr-xr-x | cmake/verify-news-file.sh | 56 |
17 files changed, 1627 insertions, 0 deletions
diff --git a/cmake/cmake_uninstall.cmake.in b/cmake/cmake_uninstall.cmake.in new file mode 100644 index 0000000000..2037e36539 --- /dev/null +++ b/cmake/cmake_uninstall.cmake.in @@ -0,0 +1,21 @@ +if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") + message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") +endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") + +file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) +string(REGEX REPLACE "\n" ";" files "${files}") +foreach(file ${files}) + message(STATUS "Uninstalling $ENV{DESTDIR}${file}") + if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") + exec_program( + "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" + OUTPUT_VARIABLE rm_out + RETURN_VALUE rm_retval + ) + if(NOT "${rm_retval}" STREQUAL 0) + message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}") + endif(NOT "${rm_retval}" STREQUAL 0) + else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") + message(STATUS "File $ENV{DESTDIR}${file} does not exist.") + endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}") +endforeach(file) diff --git a/cmake/modules/CheckTarget.cmake b/cmake/modules/CheckTarget.cmake new file mode 100644 index 0000000000..71824a990a --- /dev/null +++ b/cmake/modules/CheckTarget.cmake @@ -0,0 +1,21 @@ +# CheckTarget.cmake +# +# Defines a custom target 'check', which gathers test programs like 'make check' +# This is taken from https://cmake.org/Wiki/CMakeEmulateMakeCheck +# +# What you do is to call command: +# add_check_test(_name) +# where _name is the name of the test, as defined by add_executable(). +# Note it is a good idea to use EXCLUDE_FROM_ALL within the add_executable(). + +include(CTest) + +# Disable this to not have verbose tests +set(CMAKE_CTEST_COMMAND ${CMAKE_CTEST_COMMAND} -V) + +add_custom_target(check COMMAND ${CMAKE_CTEST_COMMAND}) + +macro(add_check_test _name) + add_test(NAME ${_name} COMMAND ${_name}) + add_dependencies(check ${_name}) +endmacro(add_check_test) diff --git a/cmake/modules/CodeCoverageGCOV.cmake b/cmake/modules/CodeCoverageGCOV.cmake new file mode 100644 index 0000000000..bf670e0a59 --- /dev/null +++ b/cmake/modules/CodeCoverageGCOV.cmake @@ -0,0 +1,45 @@ +# CodeCoverageGCOV.cmake +# +# Adds options ENABLE_CODE_COVERAGE, which builds the project with +# code coverage support +# +# It sets variables: +# CODE_COVERAGE_DEFINES - to be used with target_compile_definitions() and similar +# CODE_COVERAGE_CFLAGS - to be used with target_compile_options() and similar for C code +# CODE_COVERAGE_CXXFLAGS - to be used with target_compile_options() and similar for C++ code +# CODE_COVERAGE_LDFLAGS - to be used with target_link_libraries() and similar +# +# These variables should be added as the last in the options, because they change compilation + +include(CheckLibraryExists) +include(PrintableOptions) + +add_printable_option(ENABLE_CODE_COVERAGE "Enable build with GCOV code coverage" OFF) + +if(ENABLE_CODE_COVERAGE) + if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") + CHECK_LIBRARY_EXISTS("gcov" "gcov_exit" "" HAVE_GCOV_LIBRARY) + if(HAVE_GCOV_LIBRARY) + set(CODE_COVERAGE_CFLAGS "-O0 -g -fprofile-arcs -ftest-coverage") + set(CODE_COVERAGE_LDFLAGS "-lgcov") + + add_definitions(-DNDEBUG) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CODE_COVERAGE_CFLAGS}") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CODE_COVERAGE_CFLAGS}") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CODE_COVERAGE_LDFLAGS}") + set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${CODE_COVERAGE_LDFLAGS}") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${CODE_COVERAGE_LDFLAGS}") + set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} ${CODE_COVERAGE_LDFLAGS}") + else(HAVE_GCOV_LIBRARY) + message(FATAL_ERROR "Cannot fing gcov library, use -DENABLE_CODE_COVERAGE=OFF disable it") + endif(HAVE_GCOV_LIBRARY) + + else("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") + message(FATAL_ERROR "Code coverage requires gcc compiler, use -DENABLE_CODE_COVERAGE=OFF disable it") + endif("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") +else(ENABLE_CODE_COVERAGE) + set(CODE_COVERAGE_DEFINES "") + set(CODE_COVERAGE_CFLAGS "") + set(CODE_COVERAGE_CXXFLAGS "") + set(CODE_COVERAGE_LDFLAGS "") +endif(ENABLE_CODE_COVERAGE) diff --git a/cmake/modules/DistTargets.cmake b/cmake/modules/DistTargets.cmake new file mode 100644 index 0000000000..2551d3aa25 --- /dev/null +++ b/cmake/modules/DistTargets.cmake @@ -0,0 +1,87 @@ +# DistTarget.cmake +# +# Defines custom targets related to distributing source code. +# It requires to have populated 'PROJECT_NAME' and 'PROJECT_VERSION' variables, +# possibly through the project() command. It also uses 'PROJECT_DISTCONFIGURE_PARAMS' +# variable when configuring the unpacked distribution. +# +# Added targets: +# dist - only creates a tarball +# disttest - creates a tarball and 'make && make install' it to a temporary prefix +# to verify that the code can be built and installed; it also verifies +# that the first line of the NEWS file contains the same version as +# the tarball and that it claims today's date. +# distcheck - similar to 'disttest', only runs also 'make check' before installing + +# Filenames for tarball +set(ARCHIVE_BASE_NAME ${PROJECT_NAME}-${PROJECT_VERSION}) +set(ARCHIVE_FULL_NAME ${ARCHIVE_BASE_NAME}.tar.xz) + +add_custom_target(dist + COMMAND ${CMAKE_COMMAND} -E echo "Creating '${ARCHIVE_FULL_NAME}'..." + COMMAND git archive --prefix=${ARCHIVE_BASE_NAME}/ HEAD | xz -z > ${CMAKE_BINARY_DIR}/${ARCHIVE_FULL_NAME} + COMMAND ${CMAKE_COMMAND} -E echo "Distribution tarball '${ARCHIVE_FULL_NAME}' created at ${CMAKE_BINARY_DIR}" + WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} +) + +set(disttest_extract_dir "${CMAKE_BINARY_DIR}/${ARCHIVE_BASE_NAME}") +set(disttest_build_dir "${disttest_extract_dir}/_build") +set(disttest_install_dir "${disttest_extract_dir}/_install") + +add_custom_command(OUTPUT ${disttest_build_dir}/Makefile + # remove any left-over directory + COMMAND ${CMAKE_COMMAND} -E remove_directory ${disttest_extract_dir} + + # extract the tarball + COMMAND ${CMAKE_COMMAND} -E chdir ${CMAKE_BINARY_DIR} tar -xf ${ARCHIVE_FULL_NAME} + + # verify the NEWS file contains what it should contain + COMMAND ${CMAKE_COMMAND} -E chdir ${CMAKE_BINARY_DIR} + bash ${CMAKE_SOURCE_DIR}/cmake/verify-news-file.sh "${disttest_extract_dir}/NEWS" "${PROJECT_VERSION}" + + # create a _build sub-directory + COMMAND ${CMAKE_COMMAND} -E make_directory "${disttest_build_dir}" + + # configure the project with PROJECT_DISTCHECK_PARAMS + COMMAND ${CMAKE_COMMAND} -E chdir "${disttest_build_dir}" + ${CMAKE_COMMAND} -G "Unix Makefiles" + ${PROJECT_DISTCONFIGURE_PARAMS} + -DCMAKE_BUILD_TYPE=Release + -DCMAKE_INSTALL_PREFIX="${disttest_install_dir}" + .. + + # 'make' the project + COMMAND ${CMAKE_COMMAND} -E chdir ${disttest_build_dir} make -j + + DEPENDS dist + COMMENT "Building from distribution tarball ${ARCHIVE_FULL_NAME}..." +) + +add_custom_target(distcheck + # 'make check' the project + COMMAND ${CMAKE_COMMAND} -E chdir ${disttest_build_dir} make -j check + + # 'make install' the project + COMMAND ${CMAKE_COMMAND} -E chdir ${disttest_build_dir} make -j install + + # if we get this far, then everything worked, thus clean up + COMMAND ${CMAKE_COMMAND} -E remove_directory ${disttest_extract_dir} + + # and show the good news + COMMAND ${CMAKE_COMMAND} -E echo "distcheck of '${ARCHIVE_FULL_NAME}' succeeded" + + DEPENDS ${disttest_build_dir}/Makefile +) + +add_custom_target(disttest + # 'make install' the project + COMMAND ${CMAKE_COMMAND} -E chdir ${disttest_build_dir} make -j install + + # if we get this far, then everything worked, thus clean up + COMMAND ${CMAKE_COMMAND} -E remove_directory ${disttest_extract_dir} + + # and show the good news + COMMAND ${CMAKE_COMMAND} -E echo "disttest of '${ARCHIVE_FULL_NAME}' succeeded" + + DEPENDS ${disttest_build_dir}/Makefile +) diff --git a/cmake/modules/EvolutionMacros.cmake b/cmake/modules/EvolutionMacros.cmake new file mode 100644 index 0000000000..0491e135a0 --- /dev/null +++ b/cmake/modules/EvolutionMacros.cmake @@ -0,0 +1,63 @@ +# EvolutionMacros.cmake +# +# Utility macros for evolution-related files +# +# add_error_files(_part _file0) +# Adds build and install rules to create .error files from .error.xml +# files in the current source directory. The _file0 is expected to be +# without the .xml extension. The macro can receive one or more error +# files. There is created a custom "${_part}-error-files" target. +# +# add_eplug_file(_part _eplug_filename) +# Adds build and install rules to create .eplug files from .eplug.xml +# files in the current source directory. The _eplug_filename is expected +# to be without the .xml extension. The macro can receive exactly one +# eplug file. There is created a custom "${_part}-eplug-file" target. + +include(FindIntltool) + +macro(add_custom_xml_files _part _destination _targetsuffix _ext _mergeparam _file0) + set(filedeps) + + foreach(file ${_file0} ${ARGN}) + intltool_merge(${file}${_ext} ${file} --xml-style --utf8 ${_mergeparam}) + + get_filename_component(_path ${file} DIRECTORY) + if(_path STREQUAL "") + set(builtfile ${CMAKE_CURRENT_BINARY_DIR}/${file}) + else(_path STREQUAL "") + set(builtfile ${file}) + endif(_path STREQUAL "") + + install(FILES ${builtfile} + DESTINATION ${_destination} + ) + + list(APPEND filedeps ${builtfile}) + endforeach(file) + + add_custom_target(${_part}-${_targetsuffix}-files ALL + DEPENDS ${filedeps} + ) +endmacro(add_custom_xml_files) + +macro(add_error_files _part _file0) + add_custom_xml_files(${_part} ${errordir} error .xml --no-translations ${_file0} ${ARGN}) +endmacro(add_error_files) + +macro(add_eplug_file _part _eplug_filename) + set(PLUGINDIR "${plugindir}") + set(SOEXT "${CMAKE_SHARED_MODULE_SUFFIX}") + set(LOCALEDIR "${LOCALE_INSTALL_DIR}") + + configure_file(${_eplug_filename}.xml + ${CMAKE_CURRENT_BINARY_DIR}/${_eplug_filename}.in + @ONLY + ) + + unset(PLUGINDIR) + unset(SOEXT) + unset(LOCALEDIR) + + add_custom_xml_files(${_part} ${plugindir} plugin .in --no-translations ${CMAKE_CURRENT_BINARY_DIR}/${_eplug_filename}) +endmacro(add_eplug_file) diff --git a/cmake/modules/FindIntltool.cmake b/cmake/modules/FindIntltool.cmake new file mode 100644 index 0000000000..f6f27fe504 --- /dev/null +++ b/cmake/modules/FindIntltool.cmake @@ -0,0 +1,209 @@ +# FindIntltool.cmake +# +# Searches for intltool and gettext. It aborts, if anything cannot be found. +# Requires GETTEXT_PO_DIR to be set to full path of the po/ directory. +# +# Output is: +# INTLTOOL_UPDATE - an intltool-update executable path, as found +# INTLTOOL_EXTRACT - an intltool-extract executable path, as found +# INTLTOOL_MERGE - an intltool-merge executable path, as found +# +# and anything from the FindGettext module. +# +# The below provided macros require GETTEXT_PACKAGE to be set. +# +# intltool_add_check_potfiles_target() +# Adds a check-potfiles target, which verifies that all files with translations +# are added in the POTFILES.in file inside GETTEXT_PO_DIR. This macro can be called +# only inside GETTEXT_PO_DIR. +# +# intltool_add_pot_file_target() +# Creates a new target pot-file, which generates ${GETTEXT_PACKAGE}.pot file into +# the CMAKE_CURERNT_BINARY_DIR. This target is not part of ALL. +# This can be called only inside GETTEXT_PO_DIR. +# +# intltool_process_po_files() +# Processes all files in the GETTEXT_PO_DIR and generates .gmo files for them +# in CMAKE_CURRENT_BINARY_DIR. These are added into a new target gmo-files. +# It also installs them into proper location under LOCALE_INSTALL_DIR. +# This can be called only inside GETTEXT_PO_DIR. +# +# intltool_setup_po_dir() +# Shortcut to setup intltool's po/ directory by adding all custom targets +# and such. this can be called only inside GETTEXT_PO_DIR. +# +# intltool_merge(_in_filename _out_filename ...args) +# Adds rule to call intltool-merge. The args are optional arguments. +# This can be called in any folder, only the GETTEXT_PO_DIR should +# be properly set, otherwise the call will fail. +# +# add_appdata_file(_infilename _outfilename) +# A shortcut to call intltool-merge() for an appdata file and install it +# to ${SHARE_INSTALL_DIR}/appdata + +include(FindGettext) + +if(NOT GETTEXT_FOUND) + message(FATAL_ERROR "gettext not found, please install at least 0.18.3 version") +endif(NOT GETTEXT_FOUND) + +if(NOT GETTEXT_FOUND) + message(FATAL_ERROR "gettext not found, please install at least 0.18.3 version") +endif(NOT GETTEXT_FOUND) + +if(GETTEXT_VERSION_STRING VERSION_LESS "0.18.3") + message(FATAL_ERROR "gettext version 0.18.3+ required, but version '${GETTEXT_VERSION_STRING}' found instead. Please update your gettext") +endif(GETTEXT_VERSION_STRING VERSION_LESS "0.18.3") + +find_program(XGETTEXT xgettext) +if(NOT XGETTEXT) + message(FATAL_ERROR "xgettext executable not found. Please install or update your gettext to at least 0.18.3 version") +endif(NOT XGETTEXT) + +find_program(INTLTOOL_UPDATE intltool-update) +if(NOT INTLTOOL_UPDATE) + message(FATAL_ERROR "intltool-update not found. Please install it (usually part of an 'intltool' package)") +endif(NOT INTLTOOL_UPDATE) + +find_program(INTLTOOL_EXTRACT intltool-extract) +if(NOT INTLTOOL_EXTRACT) + message(FATAL_ERROR "intltool-extract not found. Please install it (usually part of an 'intltool' package)") +endif(NOT INTLTOOL_EXTRACT) + +find_program(INTLTOOL_MERGE intltool-merge) +if(NOT INTLTOOL_MERGE) + message(FATAL_ERROR "intltool-merge not found. Please install it (usually part of an 'intltool' package)") +endif(NOT INTLTOOL_MERGE) + +macro(intltool_add_check_potfiles_target) + if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL GETTEXT_PO_DIR) + message(FATAL_ERROR "intltool_add_pot_file_target() can be called only inside GETTEXT_PO_DIR ('${GETTEXT_PO_DIR}'), but it is called inside '${CMAKE_CURRENT_SOURCE_DIR}' instead") + endif(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL GETTEXT_PO_DIR) + + add_custom_target(check-potfiles + COMMAND ${INTLTOOL_UPDATE} -m + WORKING_DIRECTORY ${GETTEXT_PO_DIR} + ) +endmacro(intltool_add_check_potfiles_target) + +macro(intltool_add_pot_file_target) + if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL GETTEXT_PO_DIR) + message(FATAL_ERROR "intltool_add_pot_file_target() can be called only inside GETTEXT_PO_DIR ('${GETTEXT_PO_DIR}'), but it is called inside '${CMAKE_CURRENT_SOURCE_DIR}' instead") + endif(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL GETTEXT_PO_DIR) + + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${GETTEXT_PACKAGE}.pot + COMMAND ${CMAKE_COMMAND} -E env INTLTOOL_EXTRACT="${INTLTOOL_EXTRACT}" XGETTEXT="${XGETTEXT}" srcdir=${CMAKE_CURRENT_SOURCE_DIR} ${INTLTOOL_UPDATE} --gettext-package ${GETTEXT_PACKAGE} --pot + ) + + add_custom_target(pot-file + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${GETTEXT_PACKAGE}.pot + ) +endmacro(intltool_add_pot_file_target) + +macro(intltool_process_po_files) + if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL GETTEXT_PO_DIR) + message(FATAL_ERROR "intltool_process_po_files() can be called only inside GETTEXT_PO_DIR ('${GETTEXT_PO_DIR}'), but it is called inside '${CMAKE_CURRENT_SOURCE_DIR}' instead") + endif(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL GETTEXT_PO_DIR) + + file(GLOB po_files ${GETTEXT_PO_DIR}/*.po) + + set(LINGUAS) + set(LINGUAS_GMO) + + foreach(file IN LISTS po_files) + get_filename_component(lang ${file} NAME_WE) + list(APPEND LINGUAS ${lang}) + list(APPEND LINGUAS_GMO ${lang}.gmo) + + add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${lang}.gmo + COMMAND ${GETTEXT_MSGFMT_EXECUTABLE} -o ${CMAKE_CURRENT_BINARY_DIR}/${lang}.gmo ${CMAKE_CURRENT_SOURCE_DIR}/${lang}.po + DEPENDS ${lang}.po + ) + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${lang}.gmo + DESTINATION ${LOCALE_INSTALL_DIR}/${lang}/LC_MESSAGES/ + RENAME ${GETTEXT_PACKAGE}.mo + ) + if(EXISTS ${CMAKE_CURRENT_BINARY_DIR}/${lang}.gmo.m) + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${lang}.gmo.m + DESTINATION ${LOCALE_INSTALL_DIR}/${lang}/LC_MESSAGES/ + RENAME ${GETTEXT_PACKAGE}.mo.m + ) + endif(EXISTS ${CMAKE_CURRENT_BINARY_DIR}/${lang}.gmo.m) + endforeach(file) + + add_custom_target(gmo-files ALL + DEPENDS ${LINGUAS_GMO} + ) +endmacro(intltool_process_po_files) + +macro(intltool_setup_po_dir) + if(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL GETTEXT_PO_DIR) + message(FATAL_ERROR "intltool_setup_po_dir() can be called only inside GETTEXT_PO_DIR ('${GETTEXT_PO_DIR}'), but it is called inside '${CMAKE_CURRENT_SOURCE_DIR}' instead") + endif(NOT CMAKE_CURRENT_SOURCE_DIR STREQUAL GETTEXT_PO_DIR) + + intltool_add_check_potfiles_target() + intltool_add_pot_file_target() + intltool_process_po_files() +endmacro(intltool_setup_po_dir) + +macro(intltool_merge _in_filename _out_filename) + set(_in ${_in_filename}) + set(_out ${_out_filename}) + + get_filename_component(_path ${_in} DIRECTORY) + if(_path STREQUAL "") + set(_in ${CMAKE_CURRENT_SOURCE_DIR}/${_in}) + endif(_path STREQUAL "") + + get_filename_component(_path ${_out} DIRECTORY) + if(_path STREQUAL "") + set(_out ${CMAKE_CURRENT_BINARY_DIR}/${_out}) + endif(_path STREQUAL "") + + set(_has_no_translations OFF) + set(_args) + foreach(_arg ${ARGN}) + list(APPEND _args "${_arg}") + if(_arg STREQUAL "--no-translations") + set(_has_no_translations ON) + endif(_arg STREQUAL "--no-translations") + endforeach(_arg) + + if(_has_no_translations) + add_custom_command(OUTPUT ${_out} + COMMAND ${INTLTOOL_MERGE} ${_args} --quiet "${_in}" "${_out}" + DEPENDS ${_in} + ) + else(_has_no_translations) + add_custom_command(OUTPUT ${_out} + COMMAND ${INTLTOOL_MERGE} ${_args} --quiet --cache="${CMAKE_BINARY_DIR}/po/.intltool-merge-cache" "${GETTEXT_PO_DIR}" "${_in}" "${_out}" + DEPENDS ${_in} + ) + endif(_has_no_translations) +endmacro(intltool_merge) + +macro(add_appdata_file _infilename _outfilename) + if(NOT TARGET appdata-files) + add_custom_target(appdata-files ALL) + endif(NOT TARGET appdata-files) + + set(_out ${_outfilename}) + get_filename_component(_outtarget ${_out} NAME_WE) + get_filename_component(_path ${_out} DIRECTORY) + if(_path STREQUAL "") + set(_out ${CMAKE_CURRENT_BINARY_DIR}/${_out}) + endif(_path STREQUAL "") + + intltool_merge(${_infilename} ${_out} --xml-style --utf8) + + add_custom_target(appdata-${_outtarget} + DEPENDS ${_out} + ) + + add_dependencies(appdata-files appdata-${_outtarget}) + + install(FILES ${_out} + DESTINATION ${SHARE_INSTALL_DIR}/appdata + ) +endmacro(add_appdata_file) diff --git a/cmake/modules/FindLDAP.cmake b/cmake/modules/FindLDAP.cmake new file mode 100644 index 0000000000..bc3bf86714 --- /dev/null +++ b/cmake/modules/FindLDAP.cmake @@ -0,0 +1,133 @@ +# FindLDAP.cmake +# +# Searches for OpenLDAP/SunLDAP library +# +# Adds these options: +# -DWITH_OPENLDAP=ON/OFF/PATH - enable/disable OpenLDAP, eventually set prefix to find it +# -DWITH_SUNLDAP=OFF/ON/PATH - enable/disable SunLDAP, eventually set prefix to find it +# -DWITH_STATIC_LDAP=OFF/ON - enable/disable static LDAP linking +# +# The OpenLDAP has precedence over SunLDAP, if both are specified. The default is to use OpenLDAP. +# +# The output is: +# HAVE_LDAP - set to ON, if LDAP support is enabled and libraries found +# SUNLDAP - set to ON, when using SunLDAP implementation +# LDAP_CFLAGS - CFLAGS to use with target_compile_options() and similar commands +# LDAP_INCLUDE_DIRS - include directories to use with target_include_directories() and similar commands +# LDAP_LIBS - libraries to use with target_link_libraries() and similar commands + +include(CheckCSourceCompiles) +include(CheckLibraryExists) +include(PrintableOptions) + +add_printable_variable_path(WITH_OPENLDAP "Enable LDAP support using OpenLDAP, default ON" "ON") +add_printable_variable_path(WITH_SUNLDAP "Enable LDAP support using SunLDAP, default OFF" "OFF") +add_printable_option(WITH_STATIC_LDAP "Link LDAP statically, default OFF" OFF) + +if((NOT WITH_OPENLDAP) AND (NOT WITH_SUNLDAP)) + return() +endif((NOT WITH_OPENLDAP) AND (NOT WITH_SUNLDAP)) + +string(LENGTH "${CMAKE_BINARY_DIR}" bindirlen) +string(SUBSTRING "${WITH_OPENLDAP}" 0 ${bindirlen} substr) +string(TOUPPER "${WITH_OPENLDAP}" optupper) + +if(("${optupper}" STREQUAL "ON") OR ("${substr}" STREQUAL "${CMAKE_BINARY_DIR}")) + set(WITH_OPENLDAP "/usr") +endif(("${optupper}" STREQUAL "ON") OR ("${substr}" STREQUAL "${CMAKE_BINARY_DIR}")) + +string(SUBSTRING "${WITH_SUNLDAP}" 0 ${bindirlen} substr) +string(TOUPPER "${WITH_SUNLDAP}" optupper) + +if(("${optupper}" STREQUAL "ON") OR ("${substr}" STREQUAL "${CMAKE_BINARY_DIR}")) + set(WITH_SUNLDAP "/usr") +endif(("${optupper}" STREQUAL "ON") OR ("${substr}" STREQUAL "${CMAKE_BINARY_DIR}")) + +unset(bindirlen) +unset(substr) +unset(optupper) + +set(HAVE_LDAP ON) +set(SUNLDAP OFF) + +macro(add_ldap_lib_if_provides _lib _symbol) + CHECK_LIBRARY_EXISTS(${_lib} ${_symbol} "" lib${_lib}_provides_${_symbol}) + if(lib${_lib}_provides_${_symbol}) + set(LDAP_LIBS "${LDAP_LIBS} -l${_lib}") + endif(lib${_lib}_provides_${_symbol}) +endmacro(add_ldap_lib_if_provides) + +set(LDAP_PREFIX "") +if(WITH_OPENLDAP) + set(LDAP_PREFIX "${WITH_OPENLDAP}") +else(WITH_OPENLDAP) + set(LDAP_PREFIX "${WITH_SUNLDAP}") + set(SUNLDAP ON) +endif(WITH_OPENLDAP) + +set(LDAP_CFLAGS "") +set(LDAP_INCLUDE_DIRS "${LDAP_PREFIX}/include") +set(LDAP_LIBS "-L${LDAP_PREFIX}/lib${LIB_SUFFIX}") + +set(CMAKE_REQUIRED_INCLUDES "${LDAP_INCLUDE_DIRS}") +set(CMAKE_REQUIRED_LIBRARIES "${LDAP_LIBS}") + +if(WITH_OPENLDAP) + CHECK_C_SOURCE_COMPILES("#include \"ldap.h\" + int main(void) { + #if !defined(LDAP_VENDOR_VERSION) || LDAP_VENDOR_VERSION < 20000 + #error OpenLDAP version not at least 2.0 + #endif + return 0; }" openldap_2_x) + if(NOT openldap_2_x) + message(FATAL_ERROR "At least 2.0 OpenLDAP version required") + endif(NOT openldap_2_x) +else(WITH_OPENLDAP) + CHECK_C_SOURCE_COMPILES("#include \"ldap.h\" + int main(void) { + #if !defined(LDAP_VENDOR_VERSION) || LDAP_VENDOR_VERSION < 500 + #error SunLDAP version not at least 2.0 + #endif + return 0; }" sunldap_2_x) + if(NOT sunldap_2_x) + message(FATAL_ERROR "At least 2.0 SunLDAP version required") + endif(NOT sunldap_2_x) +endif(WITH_OPENLDAP) + +add_ldap_lib_if_provides(resolv res_query) +add_ldap_lib_if_provides(resolv __res_query) +add_ldap_lib_if_provides(socket bind) +CHECK_LIBRARY_EXISTS(lber ber_get_tag "" liblber_provides_ber_get_tag) +if(liblber_provides_ber_get_tag) + if(WITH_STATIC_LDAP) + set(LDAP_LIBS "${LDAP_LIBS} ${LDAP_PREFIX}/lib${LIB_SUFFIX}/liblber.a") +# # libldap might depend on OpenSSL... We need to pull +# # in the dependency libs explicitly here since we're +# # not using libtool for the configure test. +# if test -f ${LDAP_PREFIX}/lib${LIB_SUFFIX}/libldap.la; then +# LDAP_LIBS="`. ${LDAP_PREFIX}/libPLIB_SUFFIX}/libldap.la; echo $dependency_libs` $LDAP_LIBS" +# fi + else(WITH_STATIC_LDAP) + set(LDAP_LIBS "${LDAP_LIBS} -llber") + endif(WITH_STATIC_LDAP) +endif(liblber_provides_ber_get_tag) + +CHECK_LIBRARY_EXISTS(ldap ldap_open "" libldap_provides_ldap_open) +if(libldap_provides_ldap_open) + if(WITH_STATIC_LDAP) + set(LDAP_LIBS "${LDAP_LIBS} ${LDAP_PREFIX}/lib${LIB_SUFFIX}/libldap.a") + else(WITH_STATIC_LDAP) + set(LDAP_LIBS "${LDAP_LIBS} -lldap") + endif(WITH_STATIC_LDAP) +else(libldap_provides_ldap_open) + if(WITH_OPENLDAP) + message(FATAL_ERROR "Could not find OpenLDAP libraries") + else(WITH_OPENLDAP) + message(FATAL_ERROR "Could not find SunLDAP libraries") + endif(WITH_OPENLDAP) +endif(libldap_provides_ldap_open) + +unset(CMAKE_REQUIRED_INCLUDES) +unset(CMAKE_REQUIRED_LIBRARIES) + +add_definitions(-DLDAP_DEPRECATED) diff --git a/cmake/modules/FindSMIME.cmake b/cmake/modules/FindSMIME.cmake new file mode 100644 index 0000000000..3f47a65fc1 --- /dev/null +++ b/cmake/modules/FindSMIME.cmake @@ -0,0 +1,146 @@ +# FindSMIME.cmake +# +# Searches for Mozilla's NSS and NSPR libraries, unless -DENABLE_SMIME=OFF is used +# +# The output is: +# mozilla_nspr - if non-empty, then a pkg-config package name for nspr +# mozilla_nss - if non-empty, then a pkg-config package name for nss +# MANUAL_NSPR_INCLUDES - if non-empty, then contains manual nspr include directory, used for target_include_directories() and similar commands +# MANUAL_NSPR_LIBS - if non-empty, then contains manual nspr libraries, used for target_link_libraries() and similar commands +# MANUAL_NSS_INCLUDES - if non-empty, then contains manual nss include directory, used for target_include_directories() and similar commands +# MANUAL_NSS_LIBS - if non-empty, then contains manual nss libraries, used for target_link_libraries() and similar commands +# MOZILLA_NSS_LIB_DIR - a lib directory where Mozilla stores its libraries + +include(CheckIncludeFiles) +include(CheckCSourceCompiles) +include(PrintableOptions) +include(PkgConfigEx) + +add_printable_option(ENABLE_SMIME "Enable SMIME support through Mozilla nss" ON) +add_printable_variable_path(WITH_NSPR_INCLUDES "Prefix of Mozilla nspr4 includes" "") +add_printable_variable_path(WITH_NSPR_LIBS "Prefix of Mozilla nspr4 libs" "") +add_printable_variable_path(WITH_NSS_INCLUDES "Prefix of Mozilla nss3 includes" "") +add_printable_variable_path(WITH_NSS_LIBS "Prefix of Mozilla nss3 libs" "") + +if(NOT ENABLE_SMIME) + return() +endif(NOT ENABLE_SMIME) + +set(mozilla_nspr "") +set(mozilla_nss "") +set(MOZILLA_NSS_LIB_DIR "") + +# Use pkg-config when none is specified +if((WITH_NSPR_INCLUDES STREQUAL "") AND (WITH_NSPR_LIBS STREQUAL "") AND (WITH_NSS_INCLUDES STREQUAL "") AND (WITH_NSS_INCLUDES STREQUAL "")) + foreach(pkg nspr mozilla-nspr firefox-nspr xulrunner-nspr seamonkey-nspr) + pkg_check_exists(_have_pkg ${pkg}) + if(_have_pkg) + set(mozilla_nspr ${pkg}) + break() + endif(_have_pkg) + endforeach(pkg) + + foreach(pkg nss mozilla-nss firefox-nss xulrunner-nss seamonkey-nss) + pkg_check_exists(_have_pkg ${pkg}) + if(_have_pkg) + set(mozilla_nss ${pkg}) + break() + endif(_have_pkg) + endforeach(pkg) + + if((NOT (mozilla_nspr STREQUAL "")) AND (NOT (mozilla_nss STREQUAL ""))) + pkg_check_variable(_nss_libdir ${mozilla_nss} libdir) + + set(MANUAL_NSPR_INCLUDES "") + set(MANUAL_NSPR_LIBS "") + set(MANUAL_NSS_INCLUDES "") + set(MANUAL_NSS_LIBS "") + set(MOZILLA_NSS_LIB_DIR "${_nss_libdir}") + return() + endif((NOT (mozilla_nspr STREQUAL "")) AND (NOT (mozilla_nss STREQUAL ""))) +endif() + +# Manual search, even when pkg-config failed + +# ****************** +# Check for NSPR 4 +# ****************** + +if(NOT (WITH_NSPR_INCLUDES STREQUAL "")) + set(CMAKE_REQUIRED_INCLUDES ${WITH_NSPR_INCLUDES}) +endif(NOT (WITH_NSPR_INCLUDES STREQUAL "")) + +CHECK_INCLUDE_FILES(nspr.h prio.h _have_headers) + +unset(CMAKE_REQUIRED_INCLUDES) + +if(NOT _have_headers) + message(FATAL_ERROR "NSPR headers not found. Use -DWITH_NSPR_INCLUDES=/path/to/nspr to specify the include dir of NSPR.") +endif(NOT _have_headers) + +set(MANUAL_NSPR_INCLUDES "${WITH_NSPR_INCLUDES}") + +set(nsprlibs "-lplc4 -lplds4 -lnspr4") + +set(CMAKE_REQUIRED_INCLUDES ${MANUAL_NSPR_INCLUDES}) +set(CMAKE_REQUIRED_LIBRARIES ${nsprlibs}) +CHECK_C_SOURCE_COMPILES("#include <prinit.h> + int main(void) { PR_Initialized(); return 0; }" _nsprlibs_okay) +unset(CMAKE_REQUIRED_FLAGS) +unset(CMAKE_REQUIRED_LIBRARIES) + +if(NOT _nsprlibs_okay) + message(FATAL_ERROR "NSPR libs not found. Use -DWITH_NSPR_LIBS=/path/to/libs to specify the libdir of NSPR") +endif(NOT _nsprlibs_okay) + +set(MANUAL_NSPR_LIBS "") + +if(NOT (WITH_NSPR_LIBS STREQUAL "")) + set(MANUAL_NSPR_LIBS "-L${WITH_NSPR_LIBS}") +endif(NOT (WITH_NSPR_LIBS STREQUAL "")) + +set(MANUAL_NSPR_LIBS "${MANUAL_NSPR_LIBS} ${nsprlibs}") + +# ***************** +# Check for NSS 3 +# ***************** + +if(NOT (WITH_NSS_INCLUDES STREQUAL "")) + set(CMAKE_REQUIRED_INCLUDES ${WITH_NSS_INCLUDES}) +endif(NOT (WITH_NSS_INCLUDES STREQUAL "")) + +CHECK_INCLUDE_FILES(nss.h ssl.h smime.h _have_headers) + +unset(CMAKE_REQUIRED_INCLUDES) + +if(NOT _have_headers) + message(FATAL_ERROR "NSS headers not found. Use -DWITH_NSS_INCLUDES=/path/to/nss to specify the include dir of NSS.") +endif(NOT _have_headers) + +set(MANUAL_NSS_INCLUDES "${WITH_NSS_INCLUDES} ${MANUAL_NSPR_INCLUDES}") + +set(nsslibs "-lssl3 -lsmime3 -lnss3") + +set(CMAKE_REQUIRED_INCLUDES ${MANUAL_NSS_INCLUDES}) +set(CMAKE_REQUIRED_LIBRARIES ${nsslibs} ${nsprlibs}) +CHECK_C_SOURCE_COMPILES("#include <nss.h> + int main(void) { NSS_Init(\"\"); return 0; }" _nsslibs_okay) +unset(CMAKE_REQUIRED_FLAGS) +unset(CMAKE_REQUIRED_LIBRARIES) + +if(NOT _nsslibs_okay) + message(FATAL_ERROR "NSS libs not found. Use -DWITH_NSS_LIBS=/path/to/libs to specify the libdir of NSS") +endif(NOT _nsslibs_okay) + +set(MANUAL_NSS_LIBS "") + +if(NOT (WITH_NSS_LIBS STREQUAL "")) + set(MANUAL_NSS_LIBS "-L${WITH_NSS_LIBS}") + set(MOZILLA_NSS_LIB_DIR "${WITH_NSS_LIBS}") +endif(NOT (WITH_NSS_LIBS STREQUAL "")) + +set(MANUAL_NSS_LIBS "${MANUAL_NSS_LIBS} ${nsslibs} ${MANUAL_NSPR_LIBS}") + +if(MOZILLA_NSS_LIB_DIR STREQUAL "") + set(MOZILLA_NSS_LIB_DIR "${LIB_INSTALL_DIR}") +endif(MOZILLA_NSS_LIB_DIR STREQUAL "") diff --git a/cmake/modules/GLibTools.cmake b/cmake/modules/GLibTools.cmake new file mode 100644 index 0000000000..ba05824228 --- /dev/null +++ b/cmake/modules/GLibTools.cmake @@ -0,0 +1,277 @@ +# GLibTools.cmake +# +# Provides functions to run glib tools. +# +# Functions: +# +# glib_mkenums(_output_filename_noext _enums_header _define_name) +# runs glib-mkenums to generate enumtypes .h and .c files from _enums_header. +# It searches for files in the current source directory and exports to the current +# binary directory. +# +# An example call is: +# glib_mkenums(camel-enumtypes camel-enums.h CAMEL_ENUMTYPES_H) +# which uses camel-enums.h as the source of known enums and generates +# camel-enumtypes.h which will use the CAMEL_ENUMTYPES_H define +# and also generates camel-enumtypes.c with the needed code. +# +# glib_genmarshal(_output_filename_noext _prefix _marshallist_filename) +# runs glib-genmarshal to process ${_marshallist_filename} to ${_output_filename_noext}.c +# and ${_output_filename_noext}.h files in the current binary directory, using +# the ${_prefix} as the function prefix. +# +# gdbus_codegen(_xml _interface_prefix _c_namespace _files_prefix _list_gens) +# runs gdbus-codegen to generate GDBus code from _xml file description, +# using _interface_prefix, _c_namespace and _files_prefix as arguments. +# The _list_gens is a list variable are stored expected generated files. +# +# An example call is: +# set(GENERATED_DBUS_LOCALE +# e-dbus-localed.c +# e-dbus-localed.h +# ) +# gdbus_codegen(org.freedesktop.locale1.xml org.freedesktop. E_DBus e-dbus-localed GENERATED_DBUS_LOCALE) +# +# gdbus_codegen_custom(_xml _interface_prefix _c_namespace _files_prefix _list_gens _args) +# The same as gdbus_codegen() except allows to pass other arguments to the call, +# like for example --c-generate-object-manager +# +# add_gsettings_schemas(_target _schema0 ...) +# Adds one or more GSettings schemas. The extension is supposed to be .gschema.xml. The schema file generation +# is added as a dependency of _target. +# +# glib_compile_resources _sourcedir _outputprefix _cname _inxml ...deps) +# Calls glib-compile-resources as defined in _inxml and using _outputprefix and_cname as other arguments +# beside _sourcedir. The optional arguments are other dependencies. + +include(PkgConfigEx) +include(UninstallTarget) + +find_program(GLIB_MKENUMS glib-mkenums) +if(NOT GLIB_MKENUMS) + message(FATAL_ERROR "Cannot find glib-mkenums, which is required to build ${PROJECT_NAME}") +endif(NOT GLIB_MKENUMS) + +function(glib_mkenums _output_filename_noext _enums_header _define_name) + set(HEADER_TMPL " +/*** BEGIN file-header ***/ +#ifndef ${_define_name} +#define ${_define_name} +/*** END file-header ***/ + +/*** BEGIN file-production ***/ + +#include <glib-object.h> + +G_BEGIN_DECLS + +/* Enumerations from \"@filename@\" */ + +/*** END file-production ***/ + +/*** BEGIN enumeration-production ***/ +#define @ENUMPREFIX@_TYPE_@ENUMSHORT@ (@enum_name@_get_type()) +GType @enum_name@_get_type (void) G_GNUC_CONST; + +/*** END enumeration-production ***/ + +/*** BEGIN file-tail ***/ +G_END_DECLS + +#endif /* ${_define_name} */ +/*** END file-tail ***/") + + file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/enumtypes-${_output_filename_noext}.h.tmpl" "${HEADER_TMPL}\n") + + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_output_filename_noext}.h + COMMAND ${GLIB_MKENUMS} --template "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/enumtypes-${_output_filename_noext}.h.tmpl" "${CMAKE_CURRENT_SOURCE_DIR}/${_enums_header}" >${CMAKE_CURRENT_BINARY_DIR}/${_output_filename_noext}.h + ) + +set(SOURCE_TMPL " +/*** BEGIN file-header ***/ +#include \"${_output_filename_noext}.h\" +/*** END file-header ***/ + +/*** BEGIN file-production ***/ +/* enumerations from \"@filename@\" */ +#include \"@filename@\" + +/*** END file-production ***/ + +/*** BEGIN value-header ***/ +GType +@enum_name@_get_type (void) +{ + static volatile gsize the_type__volatile = 0; + + if (g_once_init_enter (&the_type__volatile)) { + static const G\@Type\@Value values[] = { +/*** END value-header ***/ + +/*** BEGIN value-production ***/ + { \@VALUENAME\@, + \"@VALUENAME@\", + \"@valuenick@\" }, +/*** END value-production ***/ + +/*** BEGIN value-tail ***/ + { 0, NULL, NULL } + }; + GType the_type = g_\@type\@_register_static ( + g_intern_static_string (\"@EnumName@\"), + values); + g_once_init_leave (&the_type__volatile, the_type); + } + return the_type__volatile; +} + +/*** END value-tail ***/") + + file(WRITE "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/enumtypes-${_output_filename_noext}.c.tmpl" "${SOURCE_TMPL}\n") + + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_output_filename_noext}.c + COMMAND ${GLIB_MKENUMS} --template "${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/enumtypes-${_output_filename_noext}.c.tmpl" "${CMAKE_CURRENT_SOURCE_DIR}/${_enums_header}" >${CMAKE_CURRENT_BINARY_DIR}/${_output_filename_noext}.c + ) +endfunction(glib_mkenums) + +find_program(GLIB_GENMARSHAL glib-genmarshal) +if(NOT GLIB_GENMARSHAL) + message(FATAL_ERROR "Cannot find glib-genmarshal, which is required to build ${PROJECT_NAME}") +endif(NOT GLIB_GENMARSHAL) + +function(glib_genmarshal _output_filename_noext _prefix _marshallist_filename) + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_output_filename_noext}.h + COMMAND ${GLIB_GENMARSHAL} --header --prefix=${_prefix} "${CMAKE_CURRENT_SOURCE_DIR}/${_marshallist_filename}" >${CMAKE_CURRENT_BINARY_DIR}/${_output_filename_noext}.h.tmp + COMMAND ${CMAKE_COMMAND} -E rename ${CMAKE_CURRENT_BINARY_DIR}/${_output_filename_noext}.h.tmp ${CMAKE_CURRENT_BINARY_DIR}/${_output_filename_noext}.h + DEPENDS ${_marshallist_filename} + ) + + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${_output_filename_noext}.c + COMMAND ${CMAKE_COMMAND} -E echo " #include \\\"${_output_filename_noext}.h\\\"" >${CMAKE_CURRENT_BINARY_DIR}/${_output_filename_noext}.c.tmp + COMMAND ${GLIB_GENMARSHAL} --body --prefix=${_prefix} "${CMAKE_CURRENT_SOURCE_DIR}/${_marshallist_filename}" >>${CMAKE_CURRENT_BINARY_DIR}/${_output_filename_noext}.c.tmp + COMMAND ${CMAKE_COMMAND} -E rename ${CMAKE_CURRENT_BINARY_DIR}/${_output_filename_noext}.c.tmp ${CMAKE_CURRENT_BINARY_DIR}/${_output_filename_noext}.c + DEPENDS ${_marshallist_filename} + ) +endfunction(glib_genmarshal) + +find_program(GDBUS_CODEGEN gdbus-codegen) +if(NOT GDBUS_CODEGEN) + message(FATAL_ERROR "Cannot find gdbus-codegen, which is required to build ${PROJECT_NAME}") +endif(NOT GDBUS_CODEGEN) + +function(gdbus_codegen_custom _xml _interface_prefix _c_namespace _files_prefix _list_gens _args) + add_custom_command( + OUTPUT ${${_list_gens}} + COMMAND ${GDBUS_CODEGEN} + ARGS --interface-prefix ${_interface_prefix} + --c-namespace ${_c_namespace} + --generate-c-code ${_files_prefix} + --generate-docbook ${_files_prefix} + ${_args} + ${CMAKE_CURRENT_SOURCE_DIR}/${_xml} + VERBATIM + ) +endfunction(gdbus_codegen_custom) + +function(gdbus_codegen _xml _interface_prefix _c_namespace _files_prefix _list_gens) + gdbus_codegen_custom(${_xml} ${_interface_prefix} ${_c_namespace} ${_files_prefix} ${_list_gens} "") +endfunction(gdbus_codegen) + +add_printable_option(ENABLE_SCHEMAS_COMPILE "Enable GSettings regeneration of gschemas.compile on install" ON) + +if(CMAKE_CROSSCOMPILING) + find_program(GLIB_COMPILE_SCHEMAS glib-compile-schemas) +else(CMAKE_CROSSCOMPILING) + pkg_check_variable(GLIB_COMPILE_SCHEMAS gio-2.0 glib_compile_schemas) +endif(CMAKE_CROSSCOMPILING) + +if(NOT GLIB_COMPILE_SCHEMAS) + message(FATAL_ERROR "Cannot find glib-compile-schemas, which is required to build ${PROJECT_NAME}") +endif(NOT GLIB_COMPILE_SCHEMAS) + +set(GSETTINGS_SCHEMAS_DIR "${SHARE_INSTALL_DIR}/glib-2.0/schemas/") + +macro(add_gsettings_schemas _target _schema0) + set(_install_code) + + foreach(_schema ${_schema0} ${ARGN}) + string(REPLACE ".xml" ".valid" _outputfile "${_schema}") + get_filename_component(_outputfile "${_outputfile}" NAME) + + get_filename_component(_schema_fullname "${_schema}" DIRECTORY) + get_filename_component(_schema_filename "${_schema}" NAME) + if(_schema_fullname STREQUAL "") + set(_schema_fullname ${CMAKE_CURRENT_SOURCE_DIR}/${_schema}) + else(_schema_fullname STREQUAL "") + set(_schema_fullname ${_schema}) + endif(_schema_fullname STREQUAL "") + + add_custom_command( + OUTPUT ${_outputfile} + COMMAND ${GLIB_COMPILE_SCHEMAS} --strict --dry-run --schema-file=${_schema_fullname} + COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_schema_fullname}" "${CMAKE_CURRENT_BINARY_DIR}/${_outputfile}" + DEPENDS ${_schema_fullname} + VERBATIM + ) + add_custom_target(gsettings-schemas-${_schema_filename} ALL DEPENDS ${_outputfile}) + add_dependencies(${_target} gsettings-schemas-${_schema_filename}) + if(ENABLE_SCHEMAS_COMPILE) + # this is required to compile gsettings schemas like after 'make install, + # because there is no better way in CMake to run a code/script after + # the whole `make install` + set(_install_code "${_install_code} + COMMAND ${CMAKE_COMMAND} -E copy_if_different \"${_schema_fullname}\" \"${GSETTINGS_SCHEMAS_DIR}\"" + ) + endif(ENABLE_SCHEMAS_COMPILE) + + # Do both, to have 'uninstall' working properly + install(FILES ${_schema_fullname} + DESTINATION ${GSETTINGS_SCHEMAS_DIR}) + endforeach(_schema) + + if(_install_code) + # Compile gsettings schemas and ensure that all of them are in the place. + install(CODE + "execute_process(${_install_code} + COMMAND ${CMAKE_COMMAND} -E chdir . \"${GLIB_COMPILE_SCHEMAS}\" \"${GSETTINGS_SCHEMAS_DIR}\" + )") + endif(_install_code) +endmacro(add_gsettings_schemas) + +# This is called too early, when the schemas are not installed yet during `make install` +# +# compile_gsettings_schemas() +# Optionally (based on ENABLE_SCHEMAS_COMPILE) recompiles schemas at the destination folder +# after install. It's necessary to call it as the last command in the toplevel CMakeLists.txt, +# thus the compile runs when all the schemas are installed. +# +if(ENABLE_SCHEMAS_COMPILE) + add_custom_command(TARGET uninstall POST_BUILD + COMMAND ${CMAKE_COMMAND} -E chdir . "${GLIB_COMPILE_SCHEMAS}" "${GSETTINGS_SCHEMAS_DIR}" + COMMENT "Recompile GSettings schemas in '${GSETTINGS_SCHEMAS_DIR}'" + ) +endif(ENABLE_SCHEMAS_COMPILE) + +find_program(GLIB_COMPILE_RESOURCES glib-compile-resources) +if(NOT GLIB_COMPILE_RESOURCES) + message(FATAL_ERROR "Cannot find glib-compile-resources, which is required to build ${PROJECT_NAME}") +endif(NOT GLIB_COMPILE_RESOURCES) + +macro(glib_compile_resources _sourcedir _outputprefix _cname _inxml) + add_custom_command( + OUTPUT ${_outputprefix}.h + COMMAND ${GLIB_COMPILE_RESOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/${_inxml} --target=${_outputprefix}.h --sourcedir=${_sourcedir} --c-name ${_cname} --generate-header + DEPENDS ${_inxml} ${ARGN} + VERBATIM + ) + add_custom_command( + OUTPUT ${_outputprefix}.c + COMMAND ${GLIB_COMPILE_RESOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/${_inxml} --target=${_outputprefix}.c --sourcedir=${_sourcedir} --c-name ${_cname} --generate-source + DEPENDS ${_inxml} ${ARGN} + VERBATIM + ) +endmacro(glib_compile_resources) diff --git a/cmake/modules/GtkDoc.cmake b/cmake/modules/GtkDoc.cmake new file mode 100644 index 0000000000..4aa286ae26 --- /dev/null +++ b/cmake/modules/GtkDoc.cmake @@ -0,0 +1,150 @@ +# GtkDoc.cmake +# +# Macros to support develper documentation build from sources with gtk-doc. +# +# add_gtkdoc(_module _namespace _deprecated_guards _srcdirsvar _depsvar _ignoreheadersvar) +# Adds rules to build developer documentation using gtk-doc for some part. +# Arguments: +# _module - the module name, like 'camel'; it expects ${_part}-docs.sgml.in in the CMAKE_CURRENT_SOURCE_DIR +# _namespace - namespace for symbols +# _deprecated_guards - define name, which guards deprecated symbols +# _srcdirsvar - variable with dirs where the source files are located +# _depsvar - a variable with dependencies (targets) +# _ignoreheadersvar - a variable with a set of header files to ignore +# +# It also adds custom target gtkdoc-rebuild-${_module}-sgml to rebuild the sgml.in +# file based on the current sources. + +include(PrintableOptions) + +add_printable_option(ENABLE_GTK_DOC "Use gtk-doc to build documentation" OFF) + +if(NOT ENABLE_GTK_DOC) + return() +endif(NOT ENABLE_GTK_DOC) + +find_program(GTKDOC_SCAN gtkdoc-scan) +find_program(GTKDOC_MKDB gtkdoc-mkdb) +find_program(GTKDOC_MKHTML gtkdoc-mkhtml) +find_program(GTKDOC_FIXXREF gtkdoc-fixxref) + +if(NOT (GTKDOC_SCAN AND GTKDOC_MKDB AND GTKDOC_MKHTML AND GTKDOC_FIXXREF)) + message(FATAL_ERROR "Cannot find all gtk-doc binaries, install them or use -DENABLE_GTK_DOC=OFF instead") + return() +endif() + +if(NOT TARGET gtkdocs) + add_custom_target(gtkdocs ALL) +endif(NOT TARGET gtkdocs) + +if(NOT TARGET gtkdoc-rebuild-sgmls) + add_custom_target(gtkdoc-rebuild-sgmls) +endif(NOT TARGET gtkdoc-rebuild-sgmls) + +macro(add_gtkdoc _module _namespace _deprecated_guards _srcdirsvar _depsvar _ignoreheadersvar) + configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/${_module}-docs.sgml.in + ${CMAKE_CURRENT_BINARY_DIR}/${_module}-docs.sgml + @ONLY + ) + + set(OUTPUT_DOCDIR ${SHARE_INSTALL_DIR}/gtk-doc/html/${_module}) + + set(_ignore_headers) + foreach(_header ${${_ignoreheadersvar}}) + set(_ignore_headers "${_ignore_headers} ${_header}") + endforeach(_header) + + set(_filedeps) + set(_srcdirs) + foreach(_srcdir ${${_srcdirsvar}}) + set(_srcdirs ${_srcdirs} --source-dir="${_srcdir}") + file(GLOB _files ${_srcdir}/*.h* ${_srcdir}/*.c*) + list(APPEND _filedeps ${_files}) + endforeach(_srcdir) + + set(_mkhtml_prefix "") + if(APPLE) + set(_mkhtml_prefix "${CMAKE_COMMAND} -E env XML_CATALOG_FILES=\"/usr/local/etc/xml/catalog\"") + endif(APPLE) + + add_custom_command(OUTPUT html/index.html + COMMAND ${GTKDOC_SCAN} + --module=${_module} + --deprecated-guards="${_deprecated_guards}" + --ignore-headers="${_ignore_headers}" + --rebuild-sections + --rebuild-types + ${_srcdirs} + + COMMAND ${GTKDOC_MKDB} + --module=${_module} + --name-space=${_namespace} + --main-sgml-file="${CMAKE_CURRENT_BINARY_DIR}/${_module}-docs.sgml" + --sgml-mode + --output-format=xml + ${_srcdirs} + + COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/html" + + COMMAND ${CMAKE_COMMAND} -E chdir "${CMAKE_CURRENT_BINARY_DIR}/html" ${_mkhtml_prefix} ${GTKDOC_MKHTML} --path=.. ${_module} ../${_module}-docs.sgml + + COMMAND ${GTKDOC_FIXXREF} + --module=${_module} + --module-dir=. + --extra-dir=.. + --html-dir="${OUTPUT_DOCDIR}" + + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/${_module}-docs.sgml" + ${_filedeps} + COMMENT "Generating ${_module} documentation" + ) + + add_custom_target(gtkdoc-${_module} + DEPENDS html/index.html + ) + + if(${_depsvar}) + add_dependencies(gtkdoc-${_module} ${${_depsvar}}) + endif(${_depsvar}) + + add_dependencies(gtkdocs gtkdoc-${_module}) + + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html/ + DESTINATION ${OUTPUT_DOCDIR} + ) + + # *************************************** + # sgml.in file rebuild, unconditional + # *************************************** + add_custom_target(gtkdoc-rebuild-${_module}-sgml + COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_CURRENT_BINARY_DIR}/tmp" + COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_CURRENT_BINARY_DIR}/tmp" + + COMMAND ${CMAKE_COMMAND} -E chdir "${CMAKE_CURRENT_BINARY_DIR}/tmp" + ${GTKDOC_SCAN} + --module=${_module} + --deprecated-guards="${_deprecated_guards}" + --ignore-headers="${_ignore_headers}" + --rebuild-sections + --rebuild-types + ${_srcdirs} + + COMMAND ${CMAKE_COMMAND} -E chdir "${CMAKE_CURRENT_BINARY_DIR}/tmp" + ${GTKDOC_MKDB} + --module=${_module} + --name-space=${_namespace} + --main-sgml-file="${CMAKE_CURRENT_BINARY_DIR}/tmp/${_module}-docs.sgml" + --sgml-mode + --output-format=xml + ${_srcdirs} + + COMMAND ${CMAKE_COMMAND} -E rename ${CMAKE_CURRENT_BINARY_DIR}/tmp/${_module}-docs.sgml ${CMAKE_CURRENT_SOURCE_DIR}/${_module}-docs.sgml.in + + COMMAND ${CMAKE_COMMAND} -E echo "File '${CMAKE_CURRENT_SOURCE_DIR}/${_module}-docs.sgml.in' overwritten, make sure you replace generated strings with proper content before committing." + ) + + add_dependencies(gtkdoc-rebuild-sgmls gtkdoc-rebuild-${_module}-sgml) + +endmacro(add_gtkdoc) diff --git a/cmake/modules/IconCache.cmake b/cmake/modules/IconCache.cmake new file mode 100644 index 0000000000..065a44bcdd --- /dev/null +++ b/cmake/modules/IconCache.cmake @@ -0,0 +1,74 @@ +# IconCache.cmake +# +# This is required here only to have defined target 'uninstall' +# in the same directory. +# +# Macros: +# add_icon_cache_files(_destdir _fileslistvar ...) +# adds rules to install icons to icon cache directory with prefix _destdir; +# the other arguments are one or more list variables with file names. + +include(UninstallTarget) + +macro(get_one_icon_component _instring _outvalue _outrest) + string(FIND "${_instring}" "_" _pos) + if(_pos EQUAL -1) + message(FATAL_ERROR "get_one_icon_component() failed to get one component from '${_instring}'") + endif(_pos EQUAL -1) + + math(EXPR _posinc "${_pos}+1") + + string(SUBSTRING "${_instring}" 0 ${_pos} ${_outvalue}) + string(SUBSTRING "${_instring}" ${_posinc} -1 ${_outrest}) +endmacro(get_one_icon_component) + +macro(split_icon_components _infilename _outtheme _outcontext _outsize _outiconfile) + set(_rest "${_infilename}") + + get_one_icon_component("${_rest}" ${_outtheme} _rest) + get_one_icon_component("${_rest}" ${_outcontext} _rest) + get_one_icon_component("${_rest}" ${_outsize} _rest) + set(${_outiconfile} "${_rest}") +endmacro(split_icon_components) + +find_program(GTK_UPDATE_ICON_CACHE gtk-update-icon-cache) +if(NOT GTK_UPDATE_ICON_CACHE) + message(WARNING "gtk-update-icon-cache not found. Make sure to call ${GTK_UPDATE_ICON_CACHE} -f -t \"${SHARE_INSTALL_DIR}/icons/hicolor\" after install and uninstall") +endif(NOT GTK_UPDATE_ICON_CACHE) + +set(_update_icon_cache_cmd ${GTK_UPDATE_ICON_CACHE} -f -t "${SHARE_INSTALL_DIR}/icons/hicolor") + +macro(process_icons _destdir _fileslistvar _install_codevar) + foreach(srcfile IN LISTS ${_fileslistvar}) + split_icon_components(${srcfile} theme context size iconfile) + install(FILES ${srcfile} + DESTINATION ${_destdir}/icons/${theme}/${size}/${context} + RENAME ${iconfile} + ) + set(${_install_codevar} "${${_install_codevar}} + COMMAND ${CMAKE_COMMAND} -E copy_if_different \"${CMAKE_CURRENT_SOURCE_DIR}/${srcfile}\" \"${_destdir}/icons/${theme}/${size}/${context}/${iconfile}\"" + ) + endforeach(srcfile) +endmacro(process_icons) + +macro(add_icon_cache_files _destdir _fileslistvar) + set(_install_code) + + foreach(_filesvar ${_fileslistvar} ${ARGN}) + process_icons("${_destdir}" ${_filesvar} _install_code) + endforeach(_filesvar) + + if(GTK_UPDATE_ICON_CACHE) + install(CODE + "execute_process(${_install_code} + COMMAND ${CMAKE_COMMAND} -E chdir . ${_update_icon_cache_cmd} + )") + endif(GTK_UPDATE_ICON_CACHE) +endmacro(add_icon_cache_files) + +if(GTK_UPDATE_ICON_CACHE) + add_custom_command(TARGET uninstall POST_BUILD + COMMAND ${CMAKE_COMMAND} -E chdir . ${_update_icon_cache_cmd} + COMMENT "Updating icon cache in '${SHARE_INSTALL_DIR}/icons/hicolor'" + ) +endif(GTK_UPDATE_ICON_CACHE) diff --git a/cmake/modules/InstalledTests.cmake b/cmake/modules/InstalledTests.cmake new file mode 100644 index 0000000000..ec445539c0 --- /dev/null +++ b/cmake/modules/InstalledTests.cmake @@ -0,0 +1,88 @@ +# InstalledTests.cmake +# +# Adds option ENABLE_INSTALLED_TESTS and helper macros to manage +# installed test. There are also set variables: +# INSTALLED_TESTS_EXEC_DIR - where to store installed tests and eventually its data +# INSTALLED_TESTS_META_DIR - where to store .test meta files for installed tests +# +# install_test_if_enabled(_test_target _type _environ) +# Adds rules to install a test whose target is _test_target (the one +# used for add_executable()), while the target name should match +# the executable name. The _type and _environ are used for populating +# the .test meta file. +# +# install_behave_tests_if_enabled(_testsvar _type _environ) +# Adds rules to install the 'behave' tests as stored in _testsvar +# in the current source directory. + +include(PrintableOptions) + +add_printable_option(ENABLE_INSTALLED_TESTS "Enable installed tests" OFF) + +set(INSTALLED_TESTS_EXEC_DIR ${privlibexecdir}/installed-tests) +set(INSTALLED_TESTS_META_DIR ${SHARE_INSTALL_DIR}/installed-tests/${PROJECT_NAME}) + +macro(install_test_if_enabled _test_target _type _environ) + if(ENABLE_INSTALLED_TESTS) + set(TEST_TYPE ${_type}) + set(TEST_ENVIRONMENT) + if(NOT ${_environ} STREQUAL "") + set(TEST_ENVIRONMENT "env ${_environ} ") + endif(NOT ${_environ} STREQUAL "") + + set(teststring "[Test] +Type=${TEST_TYPE} +Exec=${TEST_ENVIRONMENT}${INSTALLED_TESTS_EXEC_DIR}/${_test_target} +" +) + + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/${_test_target}.test "${teststring}") + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${_test_target}.test + DESTINATION ${INSTALLED_TESTS_META_DIR} + ) + + install(TARGETS ${_test_target} + DESTINATION ${INSTALLED_TESTS_EXEC_DIR} + ) + endif(ENABLE_INSTALLED_TESTS) +endmacro(install_test_if_enabled) + +macro(install_behave_tests_if_enabled _testsvar _type _environ) + if(ENABLE_INSTALLED_TESTS) + set(TEST_TYPE ${_type}) + set(TEST_ENVIRONMENT) + if(NOT ${_environ} STREQUAL "") + set(TEST_ENVIRONMENT "env ${_environ} ") + endif(NOT ${_environ} STREQUAL "") + + file(GLOB BEHAVE_FEATURES ${CMAKE_CURRENT_SOURCE_DIR}/*.feature) + file(GLOB BEHAVE_STEP_DEFINITIONS ${CMAKE_CURRENT_SOURCE_DIR}/steps/*.py) + set(BEHAVE_COMMON_FILES + ${CMAKE_CURRENT_SOURCE_DIR}/environment.py + ${CMAKE_CURRENT_SOURCE_DIR}/common_steps.py + ) + + install(FILES ${BEHAVE_FEATURES} ${BEHAVE_COMMON_FILES} + DESTINATION ${INSTALLED_TESTS_EXEC_DIR} + ) + + install(FILES ${BEHAVE_STEP_DEFINITIONS} + DESTINATION ${INSTALLED_TESTS_EXEC_DIR}/steps/ + ) + + foreach(_test ${${_testsvar}}) + set(teststring "[Test] +Type=${TEST_TYPE} +Exec=${TEST_ENVIRONMENT}behave ${INSTALLED_TESTS_EXEC_DIR} -t ${_test} -k -f html -o ${_test}.html -f plain +" +) + + file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/${_test}.test "${teststring}") + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${_test}.test + DESTINATION ${INSTALLED_TESTS_META_DIR} + ) + endforeach(_test) + endif(ENABLE_INSTALLED_TESTS) +endmacro(install_behave_tests_if_enabled) diff --git a/cmake/modules/PkgConfigEx.cmake b/cmake/modules/PkgConfigEx.cmake new file mode 100644 index 0000000000..866fe7c074 --- /dev/null +++ b/cmake/modules/PkgConfigEx.cmake @@ -0,0 +1,90 @@ +# PkgConfigEx.cmake +# +# Extends CMake's PkgConfig module with commands: +# +# pkg_check_modules_for_option(_option_name _option_description _prefix _module0) +# +# which calls `pkg_check_modules(_prefix _module0)` and if <_prefix>_FOUND is False, +# then prints an error with a hint to disaable the _option_name if needed. +# +# pkg_check_exists(_output_name _pkg) +# +# calls pkg-config --exists for _pkg and stores the result to _output_name. +# +# pkg_check_at_least_version(_output_name _pkg _version) +# +# calls pkg-config --at-least-version=_version for _pkg and stores the result to _output_name. +# +# pkg_check_exact_version(_output_name _pkg _version) +# +# calls pkg-config --exact-version=_version for _pkg and stores the result to _output_name. +# +# pkg_check_variable(_output_name _pkg _name) +# +# gets a variable named _name from package _pkg and stores the result into _output_name + +find_package(PkgConfig REQUIRED) + +macro(pkg_check_modules_for_option _option_name _option_description _prefix _module0) + pkg_check_modules(${_prefix} ${_module0} ${ARGN}) + + if(NOT ${_prefix}_FOUND) + message(FATAL_ERROR "Necessary libraries not found or not enough version. If you want to disable ${_option_description}, please use -D${_option_name}=OFF argument to cmake command.") + endif(NOT ${_prefix}_FOUND) +endmacro() + +macro(pkg_check_exists _output_name _pkg) + execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --exists ${_pkg} + RESULT_VARIABLE ${_output_name}) + + # Negate the result, because 0 means 'found' + if(${_output_name}) + set(${_output_name} OFF) + else(${_output_name}) + set(${_output_name} ON) + endif(${_output_name}) +endmacro() + +macro(pkg_check_at_least_version _output_name _pkg _version) + execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --atleast-version=${_version} ${_pkg} + RESULT_VARIABLE ${_output_name}) + + # Negate the result, because 0 means 'found' + if(${_output_name}) + set(${_output_name} OFF) + else(${_output_name}) + set(${_output_name} ON) + endif(${_output_name}) +endmacro() + +macro(pkg_check_exact_version _output_name _pkg _version) + execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --exact-version=${_version} ${_pkg} + RESULT_VARIABLE ${_output_name}) + + # Negate the result, because 0 means 'found' + if(${_output_name}) + set(${_output_name} OFF) + else(${_output_name}) + set(${_output_name} ON) + endif(${_output_name}) +endmacro() + +function(pkg_check_variable _output_name _pkg _name) + execute_process(COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=${_name} ${_pkg} + OUTPUT_VARIABLE _pkg_result + OUTPUT_STRIP_TRAILING_WHITESPACE) + + set("${_output_name}" "${_pkg_result}" CACHE STRING "pkg-config variable ${_name} of ${_pkg}") +endfunction() + +macro(add_pkgconfig_file _input _output) + configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/${_input} + ${CMAKE_CURRENT_BINARY_DIR}/${_output} + @ONLY + ) + + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${_output} + DESTINATION ${LIB_INSTALL_DIR}/pkgconfig + ) +endmacro() diff --git a/cmake/modules/PrintableOptions.cmake b/cmake/modules/PrintableOptions.cmake new file mode 100644 index 0000000000..23ce356991 --- /dev/null +++ b/cmake/modules/PrintableOptions.cmake @@ -0,0 +1,74 @@ +# PrintableOptions.cmake +# +# Provides functions to manage printable otpions, +# which can be printed at the end of the configuration +# +# add_printable_variable_bare(_name) +# adds variable named _name to the list of prinable options +# +# add_printable_option(_name _description _default_value) +# the same as option() commnd, only also notes this option for later printing +# +# add_printable_variable(_name _description _default_value) +# sets a new cached STRING variable and adds it to the list of printable options +# +# add_printable_variable_path(_name _description _default_value) +# sets a new cached PATH variable and adds it to the list of printable options +# +# print_build_options() +# prints all the build options previously added with the above functions + +macro(add_printable_variable_bare _name) + if(_name STREQUAL "") + message(FATAL_ERROR "variable name cannot be empty") + endif(_name STREQUAL "") + list(APPEND _printable_options ${_name}) +endmacro() + +macro(add_printable_option _name _description _default_value) + if(_name STREQUAL "") + message(FATAL_ERROR "option name cannot be empty") + endif(_name STREQUAL "") + option(${_name} ${_description} ${_default_value}) + add_printable_variable_bare(${_name}) +endmacro() + +macro(add_printable_variable _name _description _default_value) + if(_name STREQUAL "") + message(FATAL_ERROR "variable name cannot be empty") + endif(_name STREQUAL "") + set(${_name} ${_default_value} CACHE STRING ${_description}) + add_printable_variable_bare(${_name}) +endmacro() + +macro(add_printable_variable_path _name _description _default_value) + if(_name STREQUAL "") + message(FATAL_ERROR "path variable name cannot be empty") + endif(_name STREQUAL "") + set(${_name} ${_default_value} CACHE PATH ${_description}) + add_printable_variable_bare(${_name}) +endmacro() + +function(print_build_options) + message(STATUS "Configure options:") + + set(max_len 0) + foreach(opt IN LISTS _printable_options) + string(LENGTH "${opt}" len) + if(max_len LESS len) + set(max_len ${len}) + endif(max_len LESS len) + endforeach() + math(EXPR max_len "${max_len} + 2") + + foreach(opt IN LISTS _printable_options) + string(LENGTH "${opt}" len) + set(str " ${opt} ") + foreach (IGNORE RANGE ${len} ${max_len}) + set(str "${str}.") + endforeach () + set(str "${str} ${${opt}}") + + message(STATUS ${str}) + endforeach() +endfunction() diff --git a/cmake/modules/SetupBuildFlags.cmake b/cmake/modules/SetupBuildFlags.cmake new file mode 100644 index 0000000000..a7d2aa4172 --- /dev/null +++ b/cmake/modules/SetupBuildFlags.cmake @@ -0,0 +1,80 @@ +# SetupBuildFlags.cmake +# +# Setups compiler/linker flags, skipping those which are not supported. + +include(CheckCCompilerFlag) +include(CheckCXXCompilerFlag) + +macro(setup_build_flags _maintainer_mode) + list(APPEND proposed_flags + -Werror-implicit-function-declaration + -Wformat + -Wformat-security + -Winit-self + -Wmissing-declarations + -Wmissing-noreturn + -Wpointer-arith + -Wredundant-decls + -Wundef + -Wwrite-strings + -no-undefined + -fno-strict-aliasing + ) + + if(_maintainer_mode) + list(APPEND proposed_flags + -Wall + -Wextra + -Wdeprecated-declarations + -Wmissing-include-dirs + ) + else(_maintainer_mode) + list(APPEND proposed_flags + -Wno-deprecated-declarations + -Wno-missing-include-dir) + endif(_maintainer_mode) + + list(APPEND proposed_c_flags + ${proposed_flags} + -Wdeclaration-after-statement + -Wno-missing-field-initializers + -Wno-sign-compare + -Wno-unused-parameter + -Wnested-externs + ) + + if("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") + list(APPEND proposed_c_flags + -Wno-parentheses-equality + -Wno-format-nonliteral + ) + endif("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") + + list(APPEND proposed_cxx_flags + ${proposed_flags} + -Wabi + -Wnoexcept + ) + + foreach(flag IN LISTS proposed_c_flags) + check_c_compiler_flag(${flag} c_flag_${flag}_supported) + if(c_flag_${flag}_supported) + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${flag}") + endif(c_flag_${flag}_supported) + unset(c_flag_${flag}_supported) + endforeach() + + foreach(flag IN LISTS proposed_cxx_flags) + check_cxx_compiler_flag(${flag} cxx_flag_${flag}_supported) + if(cxx_flag_${flag}_supported) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag}") + endif(cxx_flag_${flag}_supported) + unset(cxx_flag_${flag}_supported) + endforeach() + + if(("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") OR ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--no-undefined") + set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--no-undefined") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--no-undefined") + endif(("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") OR ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")) +endmacro() diff --git a/cmake/modules/UninstallTarget.cmake b/cmake/modules/UninstallTarget.cmake new file mode 100644 index 0000000000..7ccfcf3947 --- /dev/null +++ b/cmake/modules/UninstallTarget.cmake @@ -0,0 +1,13 @@ +# UninstallTarget.cmake +# +# Defines a custom target named 'uninstall' + +if(NOT TARGET uninstall) + configure_file( + "${CMAKE_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in" + "${CMAKE_BINARY_DIR}/cmake_uninstall.cmake" + IMMEDIATE @ONLY) + + add_custom_target(uninstall + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_BINARY_DIR}/cmake_uninstall.cmake) +endif(NOT TARGET uninstall) diff --git a/cmake/verify-news-file.sh b/cmake/verify-news-file.sh new file mode 100755 index 0000000000..98d819102b --- /dev/null +++ b/cmake/verify-news-file.sh @@ -0,0 +1,56 @@ +#!/bin/bash + +# Verifies that the NEWS file's first line contains correct version and date. +# Requires arguments: +# $1 ... the NEWS file name, preferably with full path +# $2 ... expected version string, like "1.2.3" +# +# The date is expected in a form of YYYY-MM-DD of the current local time. +# The NEWS line is in form of "PROJECTNAME VERSION DATE". +# +# The test can be skipped entirely when SKIP_NEWS_FILE_TEST=1 is set. + +FILENAME=$1 +EXPVERSION=$2 + +if [ ! -f "$FILENAME" ]; then + echo "File '$FILENAME' does not exist" 1>&2 + exit 1 +fi + +if [ -z "$EXPVERSION" ]; then + echo "Expected version argument not given or empty, use format '1.2.3'" 1>&2 + exit 1 +fi + +NEWSLINE=`head --lines=1 "$FILENAME"` +EXPDATE=`date +%Y-%m-%d` + +NEWSVERSION="${NEWSLINE#* }" +NEWSDATE="${NEWSVERSION#* }" +NEWSVERSION="${NEWSVERSION% *}" +SUCCESS=1 + +if [ "$NEWSVERSION" != "$EXPVERSION" ]; then + echo "Read NEWS version '$NEWSVERSION' doesn't match expected version '$EXPVERSION'" 1>&2 + SUCCESS=0 +fi + +if [ "$NEWSDATE" != "$EXPDATE" ]; then + echo "Read NEWS date '$NEWSDATE' doesn't match expected date '$EXPDATE'" 1>&2 + SUCCESS=0 +fi + +if [ "$SUCCESS" != "1" ]; then + if [ "$SKIP_NEWS_FILE_TEST" = "1" ]; then + echo "" 1>&2 + echo "****************************************************************" 1>&2 + echo "* Failed NEWS file test ignored due to SKIP_NEWS_FILE_TEST=1 *" 1>&2 + echo "****************************************************************" 1>&2 + echo "" 1>&2 + exit 0 + else + echo "(This test can be skipped when SKIP_NEWS_FILE_TEST=1 is set.)" 1>&2 + fi + exit 1 +fi |