X-Git-Url: https://git.quassel-irc.org/?p=quassel.git;a=blobdiff_plain;f=cmake%2FQuasselMacros.cmake;h=1c0c687ca8137ddae4bd85812bf9a094842cd657;hp=652c0042d515ce5c23f1a23b065fd92df68fa63c;hb=a078e08390e41385a3145f22e83afbf622621c2f;hpb=3d3a6b8d34b9d0ab3a2502936c49c0d0d5e91617 diff --git a/cmake/QuasselMacros.cmake b/cmake/QuasselMacros.cmake index 652c0042..1c0c687c 100644 --- a/cmake/QuasselMacros.cmake +++ b/cmake/QuasselMacros.cmake @@ -1,125 +1,160 @@ -# This file contains various macros useful for building Quassel. +# This file contains various functions and macros useful for building Quassel. # -# (C) 2014 by the Quassel Project -# -# The qt4_use_modules function was taken from CMake's Qt4Macros.cmake: -# (C) 2005-2009 Kitware, Inc. +# (C) 2014-2018 by the Quassel Project # # Redistribution and use is allowed according to the terms of the BSD license. # For details see the accompanying COPYING-CMAKE-SCRIPTS file. +################################################################################################### -############################ -# Macros for dealing with Qt -############################ +include(CMakeParseArguments) -# CMake gained this function in 2.8.10. To be able to use older versions, we've copied -# this here. If present, the function from CMake will take precedence and our copy will be ignored. -function(qt4_use_modules _target _link_type) - if ("${_link_type}" STREQUAL "LINK_PUBLIC" OR "${_link_type}" STREQUAL "LINK_PRIVATE") - set(modules ${ARGN}) - set(link_type ${_link_type}) - else() - set(modules ${_link_type} ${ARGN}) - endif() - foreach(_module ${modules}) - string(TOUPPER ${_module} _ucmodule) - set(_targetPrefix QT_QT${_ucmodule}) - if (_ucmodule STREQUAL QAXCONTAINER OR _ucmodule STREQUAL QAXSERVER) - if (NOT QT_Q${_ucmodule}_FOUND) - message(FATAL_ERROR "Can not use \"${_module}\" module which has not yet been found.") - endif() - set(_targetPrefix QT_Q${_ucmodule}) - else() - if (NOT QT_QT${_ucmodule}_FOUND) - message(FATAL_ERROR "Can not use \"${_module}\" module which has not yet been found.") - endif() - if ("${_ucmodule}" STREQUAL "MAIN") - message(FATAL_ERROR "Can not use \"${_module}\" module with qt4_use_modules.") - endif() - endif() - target_link_libraries(${_target} ${link_type} ${${_targetPrefix}_LIBRARIES}) - set_property(TARGET ${_target} APPEND PROPERTY INCLUDE_DIRECTORIES ${${_targetPrefix}_INCLUDE_DIR} ${QT_HEADERS_DIR} ${QT_MKSPECS_DIR}/default) - set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS ${${_targetPrefix}_COMPILE_DEFINITIONS}) - endforeach() -endfunction() +################################################################################################### +# Adds a library target for a Quassel module. +# +# It expects the (CamelCased) module name as a parameter, and derives various +# strings from it. For example, quassel_add_module(Client) produces +# - a library target named quassel_client with output name (lib)quassel-client(.so) +# - an alias target named Quassel::Client in global scope +# +# The function exports the TARGET variable which can be used in the current scope +# for setting source files, properties, link dependencies and so on. +# To refer to the target outside of the current scope, e.g. for linking, use +# the alias name. +# +function(quassel_add_module _module) + # Derive target, alias target, output name from the given module name + set(alias "Quassel::${_module}") + set(target ${alias}) + string(TOLOWER ${target} target) + string(REPLACE "::" "_" target ${target}) + string(REPLACE "_" "-" output_name ${target}) -# Some wrappers for simplifying dual-Qt support + add_library(${target} STATIC "") + add_library(${alias} ALIAS ${target}) -function(qt_use_modules) - if (USE_QT5) - qt5_use_modules(${ARGN}) - else() - qt4_use_modules(${ARGN}) - endif() + set_target_properties(${target} PROPERTIES + OUTPUT_NAME ${output_name} + ) + + target_include_directories(${target} + PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR} # for generated files + ) + + # Export the target name for further use + set(TARGET ${target} PARENT_SCOPE) endfunction() -function(qt_wrap_ui _var) - if (USE_QT5) - qt5_wrap_ui(var ${ARGN}) - else() - qt4_wrap_ui(var ${ARGN}) +################################################################################################### +# Provides a library that contains data files as a Qt resource (.qrc). +# +# quassel_add_resource(QrcName +# [BASEDIR basedir] +# [PREFIX prefix] +# PATTERNS pattern1 pattern2... +# [DEPENDS dep1 dep2...] +# ) +# +# The first parameter is the CamelCased name of the resource; the library target will be called +# "Quassel::Resource::QrcName". The library provides a Qt resource named "qrcname" (lowercased QrcName) +# containing the files matching PATTERNS relative to BASEDIR (by default, the current source dir). +# The resource prefix can be set by giving the PREFIX argument. +# Additional target dependencies can be specified with DEPENDS. +# +function(quassel_add_resource _name) + set(options ) + set(oneValueArgs BASEDIR PREFIX) + set(multiValueArgs DEPENDS PATTERNS) + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if (NOT ARG_BASEDIR) + set(ARG_BASEDIR ${CMAKE_CURRENT_SOURCE_DIR}) endif() - set(${_var} ${${_var}} ${var} PARENT_SCOPE) -endfunction() + get_filename_component(basedir ${ARG_BASEDIR} REALPATH) + + string(TOLOWER ${_name} lower_name) + + set(qrc_target quassel-qrc-${lower_name}) + set(qrc_file ${lower_name}.qrc) + set(qrc_src qrc_${lower_name}.cpp) + set(qrc_filepath ${CMAKE_CURRENT_BINARY_DIR}/${qrc_file}) + set(qrc_srcpath ${CMAKE_CURRENT_BINARY_DIR}/${qrc_src}) + + # This target will always be built, so the qrc file will always be freshly generated. + # That way, changes to the glob result are always taken into account. + add_custom_target(${qrc_target} VERBATIM + COMMENT "Generating ${qrc_file}" + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_SOURCE_DIR}/cmake/GenerateQrc.cmake "${qrc_filepath}" "${ARG_PREFIX}" "${ARG_PATTERNS}" + DEPENDS ${ARG_DEPENDS} + BYPRODUCTS ${qrc_filepath} + WORKING_DIRECTORY ${basedir} + ) + set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${qrc_filepath}) -function(qt_add_resources _var) - if (USE_QT5) - qt5_add_resources(var ${ARGN}) + # RCC sucks and expects the data files relative to the qrc file, with no way to configure it differently. + # Only when reading from stdin ("-") it takes the working directory as a base, so we have to use this if + # we want to use generated qrc files (which obviously cannot be placed in the source directory). + # Since neither autorcc nor qt5_add_resources() support this, we have to invoke rcc manually :( + # + # On Windows, input redirection apparently doesn't work, however piping does. Use this for all platforms for + # consistency, accommodating for the fact that the 'cat' equivalent on Windows is 'type'. + if (WIN32) + set(cat_cmd type) else() - qt4_add_resources(var ${ARGN}) + set(cat_cmd cat) endif() - set(${_var} ${${_var}} ${var} PARENT_SCOPE) + add_custom_command(VERBATIM + COMMENT "Generating ${qrc_src}" + COMMAND ${cat_cmd} "$" + | "$>" --name "${lower_name}" --output "$" - + DEPENDS ${qrc_target} + MAIN_DEPENDENCY ${qrc_filepath} + OUTPUT ${qrc_srcpath} + WORKING_DIRECTORY ${basedir} + ) + + # Generate library target that can be referenced elsewhere + quassel_add_module(Resource::${_name}) + target_sources(${TARGET} PRIVATE ${qrc_srcpath}) + set_target_properties(${TARGET} PROPERTIES AUTOMOC OFF AUTOUIC OFF AUTORCC OFF) + + # Set variable for referencing the target from outside + set(RESOURCE_TARGET ${TARGET} PARENT_SCOPE) endfunction() -function(qt_add_dbus_interface _var) - if (USE_QT5) - qt5_add_dbus_interface(var ${ARGN}) - else() - qt4_add_dbus_interface(var ${ARGN}) +################################################################################################### +# target_link_if_exists(Target +# [PUBLIC dep1 dep2...] +# [PRIVATE dep3 dep4...] +# ) +# +# Convenience function to add dependencies to a target only if they exist. This is useful when +# handling targets that are conditionally created, e.g. resource libraries depending on -DEMBED_DATA. +# +# NOTE: In order to link a given target, it must already have been created, i.e its subdirectory +# must already have been added. This is also true for globally visible ALIAS targets that +# can otherwise be linked to regardless of creation order; "if (TARGET...)" does not +# support handling this case correctly. +# +function(target_link_if_exists _target) + set(options ) + set(oneValueArgs ) + set(multiValueArgs PUBLIC PRIVATE) + cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) + + if (ARG_PUBLIC) + foreach(dep ${ARG_PUBLIC}) + if (TARGET ${dep}) + target_link_libraries(${_target} PUBLIC ${dep}) + endif() + endforeach() endif() - set(${_var} ${${_var}} ${var} PARENT_SCOPE) -endfunction() -function(qt_add_dbus_adaptor _var) - if (USE_QT5) - qt5_add_dbus_adaptor(var ${ARGN}) - else() - qt4_add_dbus_adaptor(var ${ARGN}) + if (ARG_PRIVATE) + foreach(dep ${ARG_PRIVATE}) + if (TARGET ${dep}) + target_link_libraries(${_target} PRIVATE ${dep}) + endif() + endforeach() endif() - set(${_var} ${${_var}} ${var} PARENT_SCOPE) endfunction() - -###################################### -# Macros for dealing with translations -###################################### - -# This generates a .ts from a .po file -macro(generate_ts outvar basename) - set(input ${basename}.po) - set(output ${CMAKE_BINARY_DIR}/po/${basename}.ts) - add_custom_command(OUTPUT ${output} - COMMAND ${QT_LCONVERT_EXECUTABLE} - ARGS -i ${input} - -of ts - -o ${output} - WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/po -# This is a workaround to add (duplicate) strings that lconvert missed to the .ts - COMMAND ${QT_LUPDATE_EXECUTABLE} - ARGS -silent - ${CMAKE_SOURCE_DIR}/src/ - -ts ${output} - DEPENDS ${basename}.po) - set(${outvar} ${output}) -endmacro(generate_ts outvar basename) - -# This generates a .qm from a .ts file -macro(generate_qm outvar basename) - set(input ${CMAKE_BINARY_DIR}/po/${basename}.ts) - set(output ${CMAKE_BINARY_DIR}/po/${basename}.qm) - add_custom_command(OUTPUT ${output} - COMMAND ${QT_LRELEASE_EXECUTABLE} - ARGS -silent - ${input} - DEPENDS ${basename}.ts) - set(${outvar} ${output}) -endmacro(generate_qm outvar basename)