1# Additional CMake macros 2# 3# Copyright (C) 2015-2018 Jarosław Staniek <staniek@kde.org> 4# 5# Redistribution and use is allowed according to the terms of the BSD license. 6# For details see the accompanying COPYING-CMAKE-SCRIPTS file. 7 8if(__kexi_macros) 9 return() 10endif() 11set(__kexi_macros YES) 12 13#unused: include(KDbCreateSharedDataClasses) # from KDb 14include(CheckFunctionExists) 15include(GenerateExportHeader) 16include(GetGitRevisionDescription) 17include(MacroBoolTo01) 18include(KexiAddSimpleOption) 19 20string(TOUPPER ${PROJECT_NAME} PROJECT_NAME_UPPER) 21string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWER) 22string(COMPARE EQUAL "${CMAKE_CXX_COMPILER_ID}" "Clang" CMAKE_COMPILER_IS_CLANG) 23 24# Keep apps in the same bin dir so resources that are kept relative to this dir can be found 25# without installing. 26set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") 27 28macro(ensure_out_of_source_build _extra_message) 29 string(COMPARE EQUAL "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" _isBuildInSource) 30 if(isBuildInSource) 31 message(FATAL_ERROR "Compiling ${PROJECT_NAME} inside the source directory is not possible. " 32 "${_extra_message}") 33 endif() 34 unset(_isBuildInSource) 35endmacro() 36 37# Sets RELEASE_BUILD to TRUE for release builds 38macro(detect_release_build) 39 if(NOT DEFINED RELEASE_BUILD) 40 # estimate mode by CMAKE_BUILD_TYPE content if not set on cmdline 41 string(TOLOWER "${CMAKE_BUILD_TYPE}" _CMAKE_BUILD_TYPE_TOLOWER) 42 set(_RELEASE_BUILD_TYPES "release" "relwithdebinfo" "minsizerel") 43 list(FIND _RELEASE_BUILD_TYPES "${CMAKE_BUILD_TYPE_TOLOWER}" INDEX) 44 if (INDEX EQUAL -1) 45 set(RELEASE_BUILD FALSE) 46 else() 47 set(RELEASE_BUILD TRUE) 48 endif() 49 unset(_RELEASE_BUILD_TYPES) 50 unset(_CMAKE_BUILD_TYPE_TOLOWER) 51 endif() 52endmacro() 53 54if(WIN32) 55 set(LIB_INSTALL_DIR ${LIB_INSTALL_DIR} 56 RUNTIME DESTINATION ${BIN_INSTALL_DIR} 57 LIBRARY ${INSTALL_TARGETS_DEFAULT_ARGS} 58 ARCHIVE ${INSTALL_TARGETS_DEFAULT_ARGS} ) 59endif() 60 61set(ICONS_INSTALL_DIR "${DATA_INSTALL_DIR}/${KEXI_BASE_PATH}/icons") 62 63# Fetches git revision and branch from the source dir of the current build if possible. 64# Sets ${PROJECT_NAME_UPPER}_GIT_SHA1_STRING and ${PROJECT_NAME_UPPER}_GIT_BRANCH_STRING variables. 65# If git information is not available but ${CMAKE_SOURCE_DIR}/GIT_VERSION file exists, 66# it is parsed. This file can be created by scripts while preparing tarballs and is 67# supposed to contain two lines: hash and branch. 68macro(get_git_revision_and_branch) 69 set(${PROJECT_NAME_UPPER}_GIT_SHA1_STRING "") 70 set(${PROJECT_NAME_UPPER}_GIT_BRANCH_STRING "") 71 get_git_head_revision(GIT_REFSPEC ${PROJECT_NAME_UPPER}_GIT_SHA1_STRING) 72 get_git_branch(${PROJECT_NAME_UPPER}_GIT_BRANCH_STRING) 73 if(NOT ${PROJECT_NAME_UPPER}_GIT_SHA1_STRING OR NOT ${PROJECT_NAME_UPPER}_GIT_BRANCH_STRING) 74 if(EXISTS "${CMAKE_SOURCE_DIR}/GIT_VERSION") 75 file(READ "${CMAKE_SOURCE_DIR}/GIT_VERSION" _ver) 76 string(REGEX REPLACE "\n" ";" _ver "${_ver}") 77 list(GET _ver 0 ${PROJECT_NAME_UPPER}_GIT_SHA1_STRING) 78 list(GET _ver 1 ${PROJECT_NAME_UPPER}_GIT_BRANCH_STRING) 79 endif() 80 endif() 81 if(${PROJECT_NAME_UPPER}_GIT_SHA1_STRING OR ${PROJECT_NAME_UPPER}_GIT_BRANCH_STRING) 82 string(SUBSTRING ${${PROJECT_NAME_UPPER}_GIT_SHA1_STRING} 0 7 ${PROJECT_NAME_UPPER}_GIT_SHA1_STRING) 83 else() 84 set(${PROJECT_NAME_UPPER}_GIT_SHA1_STRING "") 85 set(${PROJECT_NAME_UPPER}_GIT_BRANCH_STRING "") 86 endif() 87endmacro() 88 89# Adds ${PROJECT_NAME_UPPER}_UNFINISHED option. If it is ON, unfinished features 90# (useful for testing but may confuse end-user) are compiled-in. 91# This option is OFF by default. 92macro(add_unfinished_features_option) 93 simple_option(${PROJECT_NAME_UPPER}_UNFINISHED 94 "Include unfinished features (useful for testing but may confuse end-user)" OFF) 95endmacro() 96 97# Adds commands that generate ${_filename}${KEXI_DISTRIBUTION_VERSION}.pc file 98# out of ${_filename}.pc.cmake file and installs the .pc file to ${LIB_INSTALL_DIR}/pkgconfig. 99# These commands are not executed for WIN32. 100# ${CMAKE_SOURCE_DIR}/${_filename}.pc.cmake should exist. 101macro(add_pc_file _filename) 102 if (NOT WIN32) 103 set(_name ${_filename}${KEXI_DISTRIBUTION_VERSION}) 104 configure_file(${CMAKE_SOURCE_DIR}/${_filename}.pc.cmake ${CMAKE_BINARY_DIR}/${_name}.pc @ONLY) 105 install(FILES ${CMAKE_BINARY_DIR}/${_name}.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) 106 endif() 107endmacro() 108 109# Sets detailed version information for library co-installability. 110# - adds PROJECT_STABLE_VERSION_MAJOR to the lib name 111# - sets VERSION to PROJECT_STABLE_VERSION_MAJOR.PROJECT_STABLE_VERSION_MINOR.PROJECT_STABLE_VERSION_RELEASE 112# - sets SOVERSION to KEXI_DISTRIBUTION_VERSION 113# - sets OUTPUT_NAME to ${_target}${KEXI_DISTRIBUTION_VERSION} 114# - sets ${_target_upper}_BASE_NAME variable to the final lib name 115# - sets ${_target_upper}_BASE_NAME_LOWER variable to the final lib name, lowercase 116# - sets ${_target_upper}_INCLUDE_INSTALL_DIR to include dir for library headers 117# - (where _target_upper is uppercase ${_target} 118macro(set_coinstallable_lib_version _target) 119 set(_name ${_target}${KEXI_DISTRIBUTION_VERSION}) 120 set(_version "${PROJECT_STABLE_VERSION_MAJOR}.${PROJECT_STABLE_VERSION_MINOR}.${PROJECT_STABLE_VERSION_RELEASE}") 121 set(_soversion ${KEXI_DISTRIBUTION_VERSION}) 122 set_target_properties(${_target} 123 PROPERTIES VERSION ${_version} 124 SOVERSION ${_soversion} 125 EXPORT_NAME ${_target} 126 OUTPUT_NAME ${_name} 127 ) 128 string(TOUPPER ${_target} _target_upper) 129 string(TOUPPER ${_target_upper}_BASE_NAME _var) 130 set(${_var} ${_name}) 131 string(TOLOWER ${_name} ${_var}_LOWER) 132 set(${_target_upper}_INCLUDE_INSTALL_DIR ${INCLUDE_INSTALL_DIR}/${_name}) 133 unset(_soversion) 134 unset(_version) 135 unset(_target_upper) 136 unset(_var) 137endmacro() 138 139# Combines add_library() with set_coinstallable_lib_version() 140macro(kexi_add_library) 141 set(args ${ARGV}) 142 list(GET args 0 _target) 143 add_library(${args}) 144 set_coinstallable_lib_version(${_target}) 145 unset(_target) 146endmacro() 147 148# Sets detailed version information for executable co-installability. 149# - sets OUTPUT_NAME to ${_target}-${KEXI_DISTRIBUTION_VERSION} 150macro(set_coinstallable_executable_version _target) 151 set_target_properties(${_target} 152 PROPERTIES OUTPUT_NAME ${_target}-${KEXI_DISTRIBUTION_VERSION} 153 ) 154endmacro() 155 156# Combines add_executable() with set_coinstallable_executable_version() 157macro(kexi_add_executable) 158 set(args ${ARGV}) 159 list(GET args 0 _target) 160 add_executable(${args}) 161 set_coinstallable_executable_version(${_target}) 162 unset(_target) 163endmacro() 164 165# Adds custom target that updates given file in the current working dir using specified 166# command and adds its source files to the project files. 167# The target is not executed by default, if dependencies to/from other targets are needed 168# they can be set separately using add_dependencies(). 169# Execution of the command shows status "Updating <filename>". 170# Options: 171# TARGET - name of the new custom target 172# FILE - <filename> - name of the file that is updated using the command 173# COMMAND <cmd> [args...] - command to be executed 174# SOURCES [files...] - source files that are used by the command 175function(add_update_file_target) 176 set(options) 177 set(oneValueArgs TARGET FILE) 178 set(multiValueArgs COMMAND SOURCES) 179 cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) 180 add_custom_target(${ARG_TARGET} 181 COMMAND ${ARG_COMMAND} 182 SOURCES ${ARG_SOURCES} 183 DEPENDS ${ARG_SOURCES} 184 WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" 185 COMMENT "Updating ${ARG_FILE}" 186 VERBATIM 187 ) 188endfunction() 189 190if(WIN32) 191 set(_chmod_name attrib) 192else() 193 set(_chmod_name chmod) 194endif() 195find_program(kexi_chmod_program ${_chmod_name} DOC "chmod program") 196if(kexi_chmod_program) 197 message(STATUS "Found program for changing file permissions: ${kexi_chmod_program}") 198else() 199 message(WARNING "Could not find \"${_chmod_name}\" program for changing file permissions") 200endif() 201 202# Sets file or directory read-only for all (non-root) users. 203# The _path should exist. If it is not absolute, ${CMAKE_CURRENT_SOURCE_DIR} path is prepended. 204function(kexi_set_file_read_only _path) 205 if(NOT kexi_chmod_program) 206 return() 207 endif() 208 if(IS_ABSOLUTE ${_path}) 209 set(_fullpath ${_path}) 210 else() 211 set(_fullpath ${CMAKE_CURRENT_SOURCE_DIR}/${_path}) 212 endif() 213 if(NOT EXISTS ${_fullpath}) 214 message(FATAL_ERROR "File or directory \"${_fullpath}\" does not exist") 215 return() 216 endif() 217 if(WIN32) 218 set(_command "${kexi_chmod_program}" +R "${_fullpath}") 219 else() 220 set(_command "${kexi_chmod_program}" a-w "${_fullpath}") 221 endif() 222 execute_process( 223 COMMAND ${_command} 224 RESULT_VARIABLE _result 225 OUTPUT_VARIABLE _output 226 ERROR_VARIABLE _output 227 ) 228 if(NOT _result EQUAL 0) 229 message(FATAL_ERROR "Command failed (${_result}): ${_command}\n\nOutput:\n${_output}") 230 endif() 231endfunction() 232 233# Adds example KEXI project (.kexi file) 234# - sets it read-only in the source directory 235# - installs to ${KEXI_EXAMPLES_INSTALL_DIR} as read-only for everyone 236macro(kexi_add_example_project _path) 237 kexi_set_file_read_only(${_path}) 238 install(FILES ${_path} DESTINATION ${KEXI_EXAMPLES_INSTALL_DIR} 239 PERMISSIONS OWNER_READ GROUP_READ WORLD_READ) 240endmacro() 241