Simplify handling of (dual-)Qt in the build system
authorManuel Nickschas <sputnick@quassel-irc.org>
Wed, 19 Mar 2014 20:00:07 +0000 (21:00 +0100)
committerManuel Nickschas <sputnick@quassel-irc.org>
Wed, 19 Mar 2014 20:00:07 +0000 (21:00 +0100)
We've used a somewhat complex way to link the various targets to the
required Qt libraries (and use the correct defines and CFLAGS...), because
when that stuff was written, there were no target properties in CMake, and
thus it was not easily possible to build targets within the same scope with
different settings. Therefore, we couldn't use the QT_USE_FILE and had to
write our own library handling.

These days, target properties exist, and Qt5 came up with a nice way to attach
the needed properties based on the Qt modules in use: qt5_use_modules()
This was later backported to Qt4, too, replacing the old way of having to
include QT_USE_FILE which would then set global variables.

We now make use of this; because qt4_use_modules() only showed up in
CMake 2.8.10, we've copied that function. It will be used only if it's
not present in CMake proper.

As a bonus, I've also wrapped all the qt-related macros into functions
that do the check for the Qt version we want to build against, and select
the proper macro to call, thus removing lots of WITH_QT5 conditionals
from the rest of the build system. Note that Qt5 support is still incomplete,
anyway.

CMakeLists.txt
cmake/QuasselMacros.cmake
src/CMakeLists.txt
src/client/CMakeLists.txt
src/common/CMakeLists.txt
src/core/CMakeLists.txt
src/qtui/CMakeLists.txt
src/uisupport/CMakeLists.txt

index fcc9530..686c96f 100644 (file)
@@ -34,11 +34,14 @@ set(QUASSEL_MINOR 11)
 set(QUASSEL_PATCH  0)
 set(QUASSEL_VERSION_STRING "0.11-pre")
 
-# Tell CMake about or own stuff
+# Tell CMake about or own modules
 set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
 
+# General conveniences
 set(CMAKE_AUTOMOC ON)
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
 
+# Moar stuff
 include(CheckFunctionExists)
 include(CheckIncludeFile)
 
index f0791ec..eb9dca6 100644 (file)
@@ -1,41 +1,98 @@
-# This macro sets variables for the Qt modules we need.
+# This file contains various macros useful for building Quassel.
+#
+# (C) 2014 by the Quassel Project <devel@quassel-irc.org>
+#
+# The qt4_use_modules function was taken from CMake's Qt4Macros.cmake:
+# (C) 2005-2009 Kitware, Inc.
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
 
-macro(setup_qt_variables)
-  set(QUASSEL_QT_LIBRARIES )
-  set(QUASSEL_QT_INCLUDES ${QT_INCLUDE_DIR})    # Qt4
-  set(QUASSEL_QT_DEFINITIONS ${QT_DEFINITIONS}) # Qt4
+############################
+# Macros for dealing with Qt
+############################
 
-  IF(WIN32)
-    set(MAIN Main)
-  ENDIF(WIN32)
-  foreach(qtmod Core ${ARGV} ${MAIN})
-    if(WITH_QT5)
-      find_package(Qt5${qtmod} ${QT_MIN_VERSION} REQUIRED)
-      list(APPEND QUASSEL_QT_LIBRARIES ${Qt5${qtmod}_LIBRARIES})
-      list(APPEND QUASSEL_QT_INCLUDES ${Qt5${qtmod}_INCLUDE_DIRS})
-      list(APPEND QUASSEL_QT_DEFINITIONS ${Qt5${qtmod}_DEFINITIONS} ${Qt5${qtmod}_EXECUTABLE_COMPILE_FLAGS})
-    else(WITH_QT5)
-      string(TOUPPER ${qtmod} QTMOD)
-      list(APPEND QUASSEL_QT_LIBRARIES ${QT_QT${QTMOD}_LIBRARY})
-      if(STATIC)
-        list(APPEND QUASSEL_QT_LIBRARIES ${QT_QT${QTMOD}_LIB_DEPENDENCIES})
-      endif(STATIC)
-      list(APPEND QUASSEL_QT_INCLUDES ${QT_QT${QTMOD}_INCLUDE_DIR})
-      list(APPEND QUASSEL_QT_DEFINITIONS -DQT_QT${QTMOD}_LIB)
-    endif(WITH_QT5)
-  endforeach(qtmod)
+# 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(quassel_qt4_use_modules _target _link_type)
+    message("SPUT calling")
+    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()
 
-  list(REMOVE_DUPLICATES QUASSEL_QT_LIBRARIES)
-  list(REMOVE_DUPLICATES QUASSEL_QT_INCLUDES)
-  list(REMOVE_DUPLICATES QUASSEL_QT_DEFINITIONS)
+# Some wrappers for simplifying dual-Qt support
 
-  # The COMPILE_FLAGS property expects a string, not a list...
-  set(QUASSEL_QT_COMPILEFLAGS )
-  foreach(flag ${QUASSEL_QT_DEFINITIONS})
-    set(QUASSEL_QT_COMPILEFLAGS "${QUASSEL_QT_COMPILEFLAGS} ${flag}")
-  endforeach(flag)
+function(qt_use_modules)
+    if (WITH_QT5)
+        qt5_use_modules(${ARGN})
+    else()
+        qt4_use_modules(${ARGN})
+    endif()
+endfunction()
 
-endmacro(setup_qt_variables)
+function(qt_wrap_ui _var)
+    if (WITH_QT5)
+        qt5_wrap_ui(var ${ARGN})
+    else()
+        qt4_wrap_ui(var ${ARGN})
+    endif()
+    set(${_var} ${${_var}} ${var} PARENT_SCOPE)
+endfunction()
+
+function(qt_add_resources _var)
+    if (WITH_QT5)
+        qt5_add_resources(var ${ARGN})
+    else()
+        qt4_add_resources(var ${ARGN})
+    endif()
+    set(${_var} ${${_var}} ${var} PARENT_SCOPE)
+endfunction()
+
+function(qt_add_dbus_interface _var)
+    if (WITH_QT5)
+        qt5_add_dbus_interface(var ${ARGN})
+    else()
+        qt4_add_dbus_interface(var ${ARGN})
+    endif()
+    set(${_var} ${${_var}} ${var} PARENT_SCOPE)
+endfunction()
+
+function(qt_add_dbus_adaptor _var)
+    if (WITH_QT5)
+        qt5_add_dbus_adaptor(var ${ARGN})
+    else()
+        qt4_add_dbus_adaptor(var ${ARGN})
+    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)
@@ -50,7 +107,7 @@ macro(generate_ts outvar basename)
 # This is a workaround to add (duplicate) strings that lconvert missed to the .ts
           COMMAND ${QT_LUPDATE_EXECUTABLE}
           ARGS -silent
-              ${CMAKE_SOURCE_DIR}/src/
+               ${CMAKE_SOURCE_DIR}/src/
                -ts ${output}
           DEPENDS ${basename}.po)
   set(${outvar} ${output})
index 244d394..ad96497 100644 (file)
@@ -24,52 +24,45 @@ include_directories(BEFORE ${CMAKE_CURRENT_BINARY_DIR}) # for version.gen
 
 # Add resources. Can't be done in other subdirs apparently.
 # Note that these variables need to contain paths relative to src/ (this dir)
-if(WITH_QT5)
-  qt5_add_resources(CLIENT_DEPS ${CLIENT_RCS})
-  qt5_add_resources(CORE_DEPS ${CORE_RCS})
-  qt5_add_resources(COMMON_DEPS ${COMMON_RCS})
-else(WITH_QT5)
-  qt4_add_resources(CLIENT_DEPS ${CLIENT_RCS})
-  qt4_add_resources(CORE_DEPS ${CORE_RCS})
-  qt4_add_resources(COMMON_DEPS ${COMMON_RCS})
-endif(WITH_QT5)
+qt_add_resources(CLIENT_DEPS ${CLIENT_RCS})
+qt_add_resources(CORE_DEPS ${CORE_RCS})
+qt_add_resources(COMMON_DEPS ${COMMON_RCS})
+
+# For Windows, Qt4 needs the QtMain module
+if (WIN32 AND NOT WITH_QT5)
+    set(MAIN Main)
+endif()
 
 if(WANT_CORE)
-  setup_qt_variables(Network Script Sql ${CORE_QT_MODULES})
-  include_directories(${QUASSEL_QT_INCLUDES})
   add_executable(quasselcore common/main.cpp ${COMMON_DEPS} ${CORE_DEPS})
+  qt_use_modules(quasselcore Core Network ${CORE_QT_MODULES} ${MAIN})
   add_dependencies(quasselcore po)
   set_target_properties(quasselcore PROPERTIES
-                                    COMPILE_FLAGS "-DBUILD_CORE ${QUASSEL_QT_COMPILEFLAGS}"
+                                    COMPILE_FLAGS "-DBUILD_CORE"
                                     OUTPUT_NAME ../quasselcore)
-  target_link_libraries(quasselcore mod_core mod_common ${COMMON_LIBRARIES}
-                                    ${QUASSEL_QT_LIBRARIES} ${QUASSEL_SSL_LIBRARIES})
+  target_link_libraries(quasselcore mod_core mod_common ${COMMON_LIBRARIES} ${QUASSEL_SSL_LIBRARIES})
   install(TARGETS quasselcore RUNTIME DESTINATION ${BIN_INSTALL_DIR})
 endif(WANT_CORE)
 
 if(WANT_QTCLIENT)
-  setup_qt_variables(Gui Network ${CLIENT_QT_MODULES})
-  include_directories(${QUASSEL_QT_INCLUDES})
   add_executable(quasselclient WIN32 common/main.cpp ${COMMON_DEPS} ${CLIENT_DEPS})
+  qt_use_modules(quasselclient Core Gui Network ${CLIENT_QT_MODULES} ${MAIN})
   add_dependencies(quasselclient po)
   set_target_properties(quasselclient PROPERTIES
-                                      COMPILE_FLAGS "-DBUILD_QTUI ${QUASSEL_QT_COMPILEFLAGS} ${CLIENT_COMPILE_FLAGS}"
+                                      COMPILE_FLAGS "-DBUILD_QTUI ${CLIENT_COMPILE_FLAGS}"
                                       OUTPUT_NAME ../quasselclient)
-  target_link_libraries(quasselclient ${LINK_KDE} mod_qtui mod_uisupport mod_client mod_common ${COMMON_LIBRARIES}
-                                      ${QUASSEL_QT_LIBRARIES} ${QUASSEL_SSL_LIBRARIES} ${CLIENT_LIBRARIES})
+  target_link_libraries(quasselclient ${LINK_KDE} mod_qtui mod_uisupport mod_client mod_common ${COMMON_LIBRARIES} ${CLIENT_LIBRARIES} ${QUASSEL_SSL_LIBRARIES})
   install(TARGETS quasselclient RUNTIME DESTINATION ${BIN_INSTALL_DIR})
 endif(WANT_QTCLIENT)
 
 if(WANT_MONO)
-  setup_qt_variables(Gui Network Script Sql ${CLIENT_QT_MODULES} ${CORE_QT_MODULES})
-  include_directories(${QUASSEL_QT_INCLUDES})
   add_executable(quassel WIN32 common/main.cpp qtui/monoapplication.cpp ${COMMON_DEPS} ${CLIENT_DEPS} ${CORE_DEPS})
+  qt_use_modules(quassel Core Gui Network ${CLIENT_QT_MODULES} ${CORE_QT_MODULES} ${MAIN})
   add_dependencies(quassel po)
   set_target_properties(quassel PROPERTIES
-                                COMPILE_FLAGS "-DBUILD_MONO ${QUASSEL_QT_COMPILEFLAGS} ${CLIENT_COMPILE_FLAGS}"
+                                COMPILE_FLAGS "-DBUILD_MONO ${CLIENT_COMPILE_FLAGS}"
                                 OUTPUT_NAME ../quassel)
-  target_link_libraries(quassel mod_qtui mod_uisupport mod_client mod_core mod_common ${COMMON_LIBRARIES}
-                                ${QUASSEL_QT_LIBRARIES} ${QUASSEL_SSL_LIBRARIES} ${CLIENT_LIBRARIES})
+  target_link_libraries(quassel mod_qtui mod_uisupport mod_client mod_core mod_common ${COMMON_LIBRARIES} ${CLIENT_LIBRARIES} ${QUASSEL_SSL_LIBRARIES})
   install(TARGETS quassel RUNTIME DESTINATION ${BIN_INSTALL_DIR})
 endif(WANT_MONO)
 
index c149f25..31f0a4b 100644 (file)
@@ -1,20 +1,8 @@
 # Builds the client module
 
-# In Qt4, we still have some minor deps to QtUi: QItemSelectionModel, QSortFilterProxyModel
+# In Qt4, we still have some minor deps to QtGui: QItemSelectionModel, QSortFilterProxyModel
 # Still in Qt5: QAbstractItemView in BufferModel
 
-set(_modules )
-
-if(WITH_QT5)
-  list(APPEND _modules Widgets)
-endif(WITH_QT5)
-
-if(HAVE_DBUS)
-  list(APPEND _modules DBus)
-endif(HAVE_DBUS)
-
-setup_qt_variables(Gui Network ${_modules})
-
 set(SOURCES
     abstractmessageprocessor.cpp
     backlogrequester.cpp
@@ -50,9 +38,14 @@ set(SOURCES
     clientcoreinfo.h
 )
 
-include_directories(${CMAKE_SOURCE_DIR}/src/common ${QUASSEL_QT_INCLUDES})
+if (WITH_QT5)
+    list(APPEND qt_modules Widgets)
+endif()
+
+if (HAVE_DBUS)
+    list(APPEND qt_modules DBus)
+endif()
 
 add_library(mod_client STATIC ${SOURCES})
+qt_use_modules(mod_client Network Core Gui ${qt_modules})
 add_dependencies(mod_client mod_common)
-
-set_target_properties(mod_client PROPERTIES COMPILE_FLAGS "${QUASSEL_QT_COMPILEFLAGS}")
index 8690625..46835e5 100644 (file)
@@ -1,7 +1,5 @@
 # Builds the common module
 
-setup_qt_variables(Core Network)
-
 set(SOURCES
     aliasmanager.cpp
     authhandler.cpp
@@ -67,10 +65,8 @@ if(CMAKE_HOST_UNIX)
     set(SOURCES ${SOURCES} logbacktrace_unix.cpp)
 endif(CMAKE_HOST_UNIX)
 
-include_directories(${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR} ${QUASSEL_QT_INCLUDES})  # for version.inc and version.gen
-
 add_library(mod_common STATIC ${SOURCES})
-set_target_properties(mod_common PROPERTIES COMPILE_FLAGS "${QUASSEL_QT_COMPILEFLAGS}")
+qt_use_modules(mod_common Core Network)
 
 if(APPLE)
   target_link_libraries(mod_common "-framework CoreServices" "-framework CoreFoundation")
index a167d8f..25e1488 100644 (file)
@@ -1,7 +1,5 @@
 # Builds the core module
 
-setup_qt_variables(Network Sql Script)
-
 set(SOURCES
     abstractsqlstorage.cpp
     core.cpp
@@ -52,13 +50,14 @@ if(HAVE_QCA2)
   include_directories(${QCA2_INCLUDE_DIR})
 endif(HAVE_QCA2)
 
-include_directories(${CMAKE_SOURCE_DIR}/src/common ${QUASSEL_QT_INCLUDES})
+include_directories(${CMAKE_SOURCE_DIR}/src/common)
 
 set(CORE_RCS ${CORE_RCS} core/sql.qrc PARENT_SCOPE)
 
 add_library(mod_core STATIC ${SOURCES})
+qt_use_modules(mod_core Core Network Script Sql)
+
 add_dependencies(mod_core mod_common)
-set_target_properties(mod_core PROPERTIES COMPILE_FLAGS "${QUASSEL_QT_COMPILEFLAGS}")
 
 if(HAVE_QCA2)
   target_link_libraries(mod_core ${QCA2_LIBRARIES})
index 311931e..e2f7eb0 100644 (file)
@@ -1,21 +1,5 @@
 # Builds the qtui module
 
-set(_modules )
-
-if(WITH_QT5)
-  list(APPEND _modules Widgets)
-endif(WITH_QT5)
-
-if(HAVE_DBUS)
-  list(APPEND _modules DBus)
-endif(HAVE_DBUS)
-
-if(HAVE_WEBKIT)
-  list(APPEND _modules Webkit XmlPatterns)
-endif(HAVE_WEBKIT)
-
-setup_qt_variables(Gui Network ${_modules})
-
 set(SOURCES
     aboutdlg.cpp
     awaylogfilter.cpp
@@ -107,18 +91,11 @@ else(HAVE_KDE)
   endif(HAVE_PHONON)
 endif(HAVE_KDE)
 
-if(HAVE_DBUS)
-  set(SOURCES ${SOURCES} statusnotifieritem.cpp statusnotifieritemdbus.cpp dockmanagernotificationbackend.cpp)
-  set(FORMS ${FORMS})
-  if(WITH_QT5)
-    qt5_add_dbus_interface(DBUS ../../interfaces/org.kde.StatusNotifierWatcher.xml statusnotifierwatcher)
-    qt5_add_dbus_interface(DBUS ../../interfaces/org.freedesktop.Notifications.xml notificationsclient)
-    qt5_add_dbus_adaptor(DBUS ../../interfaces/org.kde.StatusNotifierItem.xml statusnotifieritemdbus.h StatusNotifierItemDBus)
-  else(WITH_QT5)
-    qt4_add_dbus_interface(DBUS ../../interfaces/org.kde.StatusNotifierWatcher.xml statusnotifierwatcher)
-    qt4_add_dbus_interface(DBUS ../../interfaces/org.freedesktop.Notifications.xml notificationsclient)
-    qt4_add_dbus_adaptor(DBUS ../../interfaces/org.kde.StatusNotifierItem.xml statusnotifieritemdbus.h StatusNotifierItemDBus)
-  endif(WITH_QT5)
+if (HAVE_DBUS)
+    set(SOURCES ${SOURCES} statusnotifieritem.cpp statusnotifieritemdbus.cpp dockmanagernotificationbackend.cpp)
+    qt_add_dbus_interface(DBUS ../../interfaces/org.kde.StatusNotifierWatcher.xml statusnotifierwatcher)
+    qt_add_dbus_interface(DBUS ../../interfaces/org.freedesktop.Notifications.xml notificationsclient)
+    qt_add_dbus_adaptor(DBUS ../../interfaces/org.kde.StatusNotifierItem.xml statusnotifieritemdbus.h StatusNotifierItemDBus)
 endif(HAVE_DBUS)
 
 if(HAVE_SSL)
@@ -158,15 +135,24 @@ include_directories(${CMAKE_SOURCE_DIR}/src/common
                     ${CMAKE_SOURCE_DIR}/src/qtui
                     ${CMAKE_SOURCE_DIR}/src/qtui/settingspages
                     ${CMAKE_SOURCE_DIR}/src/uisupport
-                    ${CMAKE_CURRENT_BINARY_DIR}
-                    ${QUASSEL_QT_INCLUDES})
 
-if(WITH_QT5)
-  qt5_wrap_ui(UI ${FORMPATH} ${SPFRM})
-else(WITH_QT5)
-  qt4_wrap_ui(UI ${FORMPATH} ${SPFRM})
-endif(WITH_QT5)
+)
+
+qt_wrap_ui(UI ${FORMPATH} ${SPFRM})
+
+if (WITH_QT5)
+    list(APPEND qt_modules Widgets)
+endif()
+
+if (HAVE_DBUS)
+    list(APPEND qt_modules DBus)
+endif()
+
+if (HAVE_WEBKIT)
+    list(APPEND qt_modules Webkit XmlPatterns)
+endif()
 
 add_library(mod_qtui STATIC ${SOURCES} ${SPSRC} ${DBUS} ${UI})
+qt_use_modules(mod_qtui Core Gui Network ${qt_modules})
+
 add_dependencies(mod_qtui mod_common mod_client mod_uisupport)
-set_target_properties(mod_qtui PROPERTIES COMPILE_FLAGS "${QUASSEL_QT_COMPILEFLAGS}")
index 1b4f176..0505d92 100644 (file)
@@ -1,11 +1,5 @@
 # Builds the uisupport module
 
-if(WITH_QT5)
-  setup_qt_variables(Widgets Network)
-else(WITH_QT5)
-  setup_qt_variables(Gui Network)
-endif(WITH_QT5)
-
 set(SOURCES
     abstractbuffercontainer.cpp
     abstractitemview.cpp
@@ -48,12 +42,17 @@ endif(HAVE_KDE)
 
 include_directories(${CMAKE_SOURCE_DIR}/src/common
                     ${CMAKE_SOURCE_DIR}/src/client
-                    ${QUASSEL_QT_INCLUDES})
+)
 
 if(HAVE_QCA2)
   include_directories(${QCA2_INCLUDE_DIR})
 endif(HAVE_QCA2)
 
+if (WITH_QT5)
+    list(APPEND qt_modules Widgets)
+endif()
+
 add_library(mod_uisupport STATIC ${SOURCES})
+qt_use_modules(mod_uisupport Core Gui Network ${qt_modules})
+
 add_dependencies(mod_uisupport mod_common mod_client)
-set_target_properties(mod_uisupport PROPERTIES COMPILE_FLAGS "${QUASSEL_QT_COMPILEFLAGS}")