Completely rework the dependency handling in the build system
[quassel.git] / CMakeLists.txt
1 # Main CMake file for building Quassel IRC
2 #
3 # See INSTALL for possible CMake options (or read the code, Luke)
4 #####################################################################
5
6 # General setup
7 #####################################################################
8
9 cmake_minimum_required(VERSION 2.8.9)
10 project(QuasselIRC)
11
12 # Versions
13 set(QUASSEL_MAJOR  0)
14 set(QUASSEL_MINOR 11)
15 set(QUASSEL_PATCH  0)
16 set(QUASSEL_VERSION_STRING "0.11-pre")
17
18 # Tell CMake about or own modules
19 set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake)
20
21 # General conveniences
22 set(CMAKE_AUTOMOC ON)
23 set(CMAKE_INCLUDE_CURRENT_DIR ON)
24
25 # Moar stuff
26 include(CheckFunctionExists)
27 include(CheckIncludeFile)
28
29 include(QuasselCompileSettings)
30 include(QuasselMacros)
31
32 include(CMakeDependentOption)
33 include(FeatureSummary)
34
35
36 # Options and variables that can be set on the command line
37 #####################################################################
38
39 # First, choose a Qt version. We support USE_QT4 and USE_QT5; if neither is set, prefer Qt4 for now
40 option(USE_QT5 "Enable support for Qt5 (disables KDE integration)" OFF)
41 if (USE_QT4) # takes precedence
42     set(USE_QT5 OFF)
43 else()
44     if (NOT USE_QT5)
45         set(USE_QT4 ON)
46     endif()
47 endif()
48
49 # Select the binaries to build
50 option(WANT_CORE     "Build the core (server) binary"           ON)
51 option(WANT_QTCLIENT "Build the Qt GUI client binary"           ON)
52 option(WANT_MONO     "Build the monolithic (all-in-one) binary" ON)
53
54 add_feature_info(WANT_CORE WANT_CORE "Build the core (server) binary")
55 add_feature_info(WANT_QTCLIENT WANT_QTCLIENT "Build the Qt GUI client binary")
56 add_feature_info(WANT_MONO WANT_MONO "Build the monolithic (all-in-one) binary")
57
58
59 # Whether to enable KDE integration (pulls in kdelibs and friends as a dependency); requires Qt4 for now
60 cmake_dependent_option(WITH_KDE      "KDE4 integration" OFF "USE_QT4" OFF)
61 add_feature_info(WITH_KDE WITH_KDE "Enable KDE4 integration")
62
63 # Some options don't make sense with KDE
64 cmake_dependent_option(WITH_PHONON   "Phonon support (for audio notifications)"           ON "NOT WITH_KDE" OFF)
65 cmake_dependent_option(WITH_SNORE    "Snore notification support"                        OFF "NOT WITH_KDE" OFF)
66 cmake_dependent_option(WITH_OXYGEN   "Install Oxygen icon set (usually shipped with KDE)" ON "NOT WITH_KDE" OFF)
67
68 # Misc features
69 option(WITH_OPENSSL     "OpenSSL support (secure networking)"             ON)
70 option(WITH_DBUS        "Use D-Bus for the tray icon (StatusNotifier)"    ON)
71 option(WITH_WEBKIT      "WebKit support (for link previews)"              ON)
72 option(WITH_CRYPT       "Encryption support (QCA)"                        ON)
73 option(WITH_LIBINDICATE "Ayatana (libindicate) notification support"      ON)
74 cmake_dependent_option(WITH_SYSLOG   "Support logging to syslog"          ON "NOT WIN32" OFF)
75
76 if (APPLE)
77     # Notification Center is only available in > 10.8, which is Darwin v12
78     if (CMAKE_SYSTEM_VERSION VERSION_GREATER "11.9.9")
79         option(WITH_NOTIFICATION_CENTER "OS X Notification Center support" ON)
80         add_feature_info(WITH_NOTIFICATION_CENTER WITH_NOTIFICATION_CENTER "Use the OS X Notification Center")
81     endif()
82 endif()
83
84 # Always embed on Windows or for a static build; never embed when enabling KDE integration
85 set(EMBED_DEFAULT OFF)
86 if (STATIC OR WIN32)
87     set(EMBED_DEFAULT ON)
88 endif()
89 cmake_dependent_option(EMBED_DATA "Embed icons and translations in the binaries instead of installing them" ${EMBED_DEFAULT}
90                                    "NOT STATIC;NOT WIN32;NOT WITH_KDE" ${EMBED_DEFAULT})
91
92 cmake_dependent_option(DEPLOY      "Add required libs to bundle resources and create a dmg. Note: requires Qt to be built with 10.4u SDK" OFF "APPLE" OFF)
93
94 # Handle with care
95 set(QT_PATH "" CACHE PATH "Path to a Qt4 installation to use instead of the system Qt (e.g. for static builds)")
96
97
98 # Static builds are not supported and require some manual setup! Don't enable unless you know what you're doing (we don't know either)
99 cmake_dependent_option(STATIC      "Enable static building (not supported)" OFF "NOT WITH_KDE" OFF)
100
101 # For static builds, arbitrary extra libs might need to be linked
102 # Define a comma-separated list here
103 # e.g. for pgsql, we need -DLINK_EXTRA=pq;crypt
104 set(LINK_EXTRA "" CACHE STRING "Semicolon-separated list of libraries to be linked")
105 if (LINK_EXTRA)
106     string(REPLACE "," ";" LINK_EXTRA ${LINK_EXTRA})
107     link_libraries(${LINK_EXTRA})
108 endif()
109
110
111 # Simplify later checks
112 #####################################################################
113
114 if (WANT_MONO OR WANT_QTCLIENT)
115     set(BUILD_GUI true)
116 endif()
117 if (WANT_MONO OR WANT_CORE)
118     set(BUILD_CORE true)
119 endif()
120
121
122 # Set up Qt
123 #####################################################################
124
125 if (USE_QT5)
126     message(STATUS "Building with the Qt5 libraries...")
127     set(QT_MIN_VERSION "5.2.0")
128     add_definitions(-DHAVE_QT5)
129 else()
130     message(STATUS "Building with the Qt4 libraries...")
131     if (BUILD_GUI)
132         set(QT_MIN_VERSION "4.6.0")
133     else()
134         set(QT_MIN_VERSION "4.4.0")
135     endif()
136 endif()
137
138 if (USE_QT5)
139     find_package(Qt5Core ${QT_MIN_VERSION} QUIET REQUIRED)
140
141     # Contains lconvert and friends
142     find_package(Qt5LinguistTools QUIET)
143     set_package_properties(Qt5LinguistTools PROPERTIES TYPE RECOMMENDED
144                            PURPOSE "Required for localization support"
145     )
146 else()
147     # Select a Qt installation here, if you don't want to use system Qt
148     if(QT_PATH)
149         # FindQt4 will look for the qmake binary in $PATH, so we just prepend QT_PATH
150         set(ENV{PATH} ${QT_PATH}/bin:$ENV{PATH})
151     endif()
152
153     # Now that we have the correct $PATH, lets find Qt!
154     find_package(Qt4 ${QT_MIN_VERSION} QUIET REQUIRED)
155 endif()
156
157 # Neither Qt4 nor Qt5 consider lconvert relevant, so they don't support finding it...
158 # Rather than shipping hacked buildsys files, let's just infer the path from lrelease
159 if (QT_LRELEASE_EXECUTABLE)
160     get_filename_component(_lrelease_path ${QT_LRELEASE_EXECUTABLE} PATH)
161     if (USE_QT5)
162         find_program(QT_LCONVERT_EXECUTABLE NAMES lconvert-qt5 lconvert PATHS ${_lrelease_path} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
163     else()
164         find_program(QT_LCONVERT_EXECUTABLE NAMES lconvert-qt4 lconvert PATHS ${_lrelease_path} NO_DEFAULT_PATH NO_CMAKE_FIND_ROOT_PATH)
165     endif()
166 endif()
167
168 add_feature_info("Qt Linguist Tools" QT_LRELEASE_EXECUTABLE "Translation support for Quassel")
169
170 # Optional Dependencies
171 #
172 # Note that you can forcefully disable optional packages
173 # using -DCMAKE_DISABLE_FIND_PACKAGE_<PkgName>=TRUE
174 #####################################################################
175
176 if(USE_QT5)
177     if (BUILD_GUI)
178         find_package(Qt5DBus QUIET)
179         set_package_properties(Qt5DBus PROPERTIES TYPE RECOMMENDED
180             URL "http://qt.digia.com"
181             DESCRIPTION "D-Bus support for Qt5"
182             PURPOSE     "Needed for supporting D-Bus-based notifications and tray icon, used by most modern desktop environments"
183         )
184         if (Qt5DBus_FOUND)
185             find_package(dbusmenu-qt5 QUIET)
186             set_package_properties(dbusmenu-qt5 PROPERTIES TYPE RECOMMENDED
187                 URL "https://launchpad.net/libdbusmenu-qt"
188                 DESCRIPTION "a library implementing the DBusMenu specification"
189                 PURPOSE     "Required for having a context menu for the D-Bus-based tray icon"
190             )
191         endif()
192
193         find_package(Phonon4Qt5 QUIET)
194         set_package_properties(Phonon4Qt5 PROPERTIES TYPE RECOMMENDED
195             URL "https://projects.kde.org/projects/kdesupport/phonon"
196             DESCRIPTION "a multimedia abstraction library"
197             PURPOSE     "Required for audio notifications"
198         )
199
200         if (WITH_WEBKIT)
201             find_package(Qt5Webkit QUIET)
202             set_package_properties(Qt5Webkit PROPERTIES TYPE RECOMMENDED
203                 URL "http://qt.digia.com"
204                 DESCRIPTION "a Webkit implementation for Qt"
205                 PURPOSE     "Needed for displaying previews for URLs in chat"
206             )
207         endif()
208         add_feature_info("WITH_WEBKIT and QtWebkit module" Qt5Webkit_FOUND "Support showing previews for URLs in chat")
209
210     endif(BUILD_GUI)
211     if (BUILD_CORE)
212         # While QCA2 seems to support Qt5, it is not actually co-installable or distinguishable from the Qt4 version...
213         # In order to avoid linking against the Qt4 version (which is probably the one installed), disable this for now
214         #find_package(QCA2 QUIET)
215         #set_package_properties(QCA2 PROPERTIES TYPE RECOMMENDED
216         #    URL "https://projects.kde.org/projects/kdesupport/qca"
217         #    DESCRIPTION "Qt Cryptographic Architecture"
218         #    PURPOSE "Required for encryption support"
219         #)
220
221     endif(BUILD_CORE)
222
223 else(USE_QT5)
224     if (BUILD_GUI)
225         add_feature_info("QtDBus module" QT_QTDBUS_FOUND "Needed for supporting D-Bus-based notifications and tray icon, used by most modern desktop environments")
226         if (QT_QTDBUS_FOUND)
227             find_package(libdbusmenu-qt QUIET)
228             set_package_properties(dbusmenu-qt PROPERTIES TYPE RECOMMENDED
229                 URL "https://launchpad.net/libdbusmenu-qt"
230                 DESCRIPTION "a library implementing the DBusMenu specification"
231                 PURPOSE     "Required for having a context menu for the D-Bus-based tray icon"
232             )
233         endif()
234
235         if (WITH_WEBKIT AND QT_QTWEBKIT_FOUND)
236             set(HAVE_WEBKIT true)
237         endif()
238         add_feature_info("WITH_WEBKIT and QtWebkit module" HAVE_WEBKIT "Support showing previews for URLs in chat")
239
240         if (WITH_KDE)
241             # KDE has overzealous CFLAGS making miniz not compile, so save our old flags
242             set(_cflags ${CMAKE_C_FLAGS})
243             find_package(KDE4 4.4 QUIET)
244             set_package_properties(KDE4 PROPERTIES TYPE REQUIRED
245                 URL "http://www.kde.org"
246                 DESCRIPTION "a world-class desktop environment"
247                 PURPOSE "Enables various bits for improving integration with KDE"
248             )
249             set(CMAKE_C_FLAGS ${_cflags})
250
251         else(WITH_KDE)
252             find_package(Phonon QUIET)
253             set_package_properties(Phonon PROPERTIES TYPE RECOMMENDED
254                 URL "https://projects.kde.org/projects/kdesupport/phonon"
255                 DESCRIPTION "a multimedia abstraction library"
256                 PURPOSE     "Required for audio notifications"
257             )
258
259             find_package(Libsnore QUIET)
260             set_package_properties(Libsnore PROPERTIES TYPE OPTIONAL
261                 URL "https://github.com/TheOneRing/Snorenotify"
262                 DESCRIPTION "a cross-platform notification framework"
263                 PURPOSE     "Enable support for the snorenotify framework"
264             )
265         endif(WITH_KDE)
266
267         find_package(IndicateQt QUIET)
268         set_package_properties(IndicateQt PROPERTIES TYPE OPTIONAL
269             URL "https://launchpad.net/libindicate-qt/"
270             DESCRIPTION "a library to raise flags on DBus for other components of the desktop to pick up and visualize"
271             PURPOSE     "Provides integration into the Ayatana notification system used by e.g. Ubuntu"
272         )
273
274     endif(BUILD_GUI)
275     if (BUILD_CORE)
276
277         find_package(QCA2 QUIET)
278         set_package_properties(QCA2 PROPERTIES TYPE RECOMMENDED
279             URL "https://projects.kde.org/projects/kdesupport/qca"
280             DESCRIPTION "Qt Cryptographic Architecture"
281             PURPOSE     "Required for encryption support"
282         )
283
284
285     endif()
286 endif()
287
288 # Non-Qt-based packages
289
290 # zlib for compression, however we can always fall back to miniz
291 find_package(ZLIB QUIET)
292 set_package_properties(ZLIB PROPERTIES TYPE RECOMMENDED
293     URL "http://www.zlib.net"
294     DESCRIPTION "a popular compression library"
295     PURPOSE     "Use the most common library for protocol compression, instead of the bundled miniz implementation"
296 )
297
298
299 if (NOT WIN32)
300     # Execinfo is needed for generating backtraces
301     find_package(ExecInfo QUIET)
302     set_package_properties(ExecInfo PROPERTIES TYPE OPTIONAL
303         DESCRIPTION "a library for inspecting backtraces"
304         PURPOSE "Used for generating backtraces in case of a crash"
305     )
306 endif()
307
308 # Setup OpenSSL
309 # We don't link to or include OpenSSL ourselves, but use exclusively the Qt API.
310 # Thus, we simply check if OpenSSL support is present in Qt's config and enable our
311 # own SSL stuff in this case. Qt should care for adding what it needs itself.
312 if(WITH_OPENSSL)
313   if(QT_QCONFIG MATCHES "openssl")
314     message(STATUS "Found OpenSSL support in Qt, enabling SSL")
315     add_definitions(-DHAVE_SSL)
316     set(HAVE_SSL true)
317   else(QT_QCONFIG MATCHES "openssl")
318     message(STATUS "No OpenSSL support found in Qt, disabling SSL")
319     add_definitions(-DQT_NO_OPENSSL)
320   endif(QT_QCONFIG MATCHES "openssl")
321 else(WITH_OPENSSL)
322   message(STATUS "Not enabling OpenSSL support")
323 endif(WITH_OPENSSL)
324
325 # Core-only deps
326 if(BUILD_CORE)
327
328   # Setup syslog support
329   if(WITH_SYSLOG)
330     check_include_file(syslog.h HAVE_SYSLOG_H)
331     if(HAVE_SYSLOG_H)
332       message(STATUS "Enabling syslog support")
333       set(HAVE_SYSLOG true)
334       add_definitions(-DHAVE_SYSLOG)
335     else(HAVE_SYSLOG_H)
336       message(STATUS "Disabling syslog support")
337     endif(HAVE_SYSLOG_H)
338   else(WITH_SYSLOG)
339     message(STATUS "Not enabling syslog support")
340   endif(WITH_SYSLOG)
341
342 endif(BUILD_CORE)
343
344
345 #
346 #####################################################################
347
348 if (NOT ZLIB_FOUND)
349     message(STATUS "zlib NOT found, using bundled miniz for compression")
350     if (${CMAKE_SIZEOF_VOID_P} EQUAL 4)
351         message(STATUS "WARNING: This may be slow on 32 bit systems!")
352     endif()
353 endif()
354
355 if (KDE4_FOUND)
356     # We always use external icons for KDE4 support, since we use its iconloader rather than our own
357     set(EMBED_DATA OFF)
358
359     # Better have the compile flags global, even for the core, to avoid problems with linking the mono client
360     add_definitions(-DHAVE_KDE ${KDE4_DEFINITIONS})
361 endif()
362
363
364 # Various settings
365 ##################
366
367 # needed to compile with mingw without kde
368 if (MINGW AND NOT KDE4_FOUND)
369     add_definitions(-D_WIN32_WINNT=0x0500)
370     message(STATUS "Added _WIN32_WINNT=0x0500 definition for MinGW")
371 # workaround for bug in mingw gcc 4.0
372     add_definitions(-U__STRICT_ANSI__)
373 endif()
374
375 # Now set up install locations; those are set by KDE if integration is enabled
376 if(NOT KDE4_FOUND)
377   if(WIN32)
378     set(BIN_INSTALL_DIR ${CMAKE_INSTALL_PREFIX} CACHE FILEPATH "Install path for binaries")
379     set(DATA_INSTALL_DIR $ENV{APPDATA}/quassel-irc.org/share/apps CACHE FILEPATH "Install path for data files")
380     set(ICON_INSTALL_DIR $ENV{APPDATA}/quassel-irc.org/share/icons CACHE FILEPATH "Global icon install path")
381     set(XDG_APPS_INSTALL_DIR $ENV{APPDATA}/quassel-irc.org/share/applications CACHE FILEPATH "Install path for .desktop files")
382   else(WIN32)
383     set(BIN_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/bin CACHE FILEPATH "Install path for binaries")
384     set(DATA_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/share/apps CACHE FILEPATH "Install path for data files")
385     set(ICON_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/share/icons CACHE FILEPATH "Global icon install path")
386     set(XDG_APPS_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/share/applications CACHE FILEPATH "Install path for .desktop files")
387   endif(WIN32)
388 endif()
389
390 if(EMBED_DATA)
391   message(STATUS "Embedding data files into the binary")
392 else(EMBED_DATA)
393   message(STATUS "Installing data files separately")
394 endif(EMBED_DATA)
395
396 # RPATH needs to be set correctly
397 # Do this down here, since otherwise KDE wants to handle it itself, and fails
398 set(CMAKE_INSTALL_RPATH_USE_LINK_PATH 1)
399 set(CMAKE_BUILD_WITH_INSTALL_RPATH 1)
400
401 # Set global buildflags
402 # This is very much non-portable, so don't use -DSTATIC until you know what
403 # you do.
404 if(STATIC AND CMAKE_COMPILER_IS_GNUCXX)
405   set(CMAKE_CXX_FLAGS "-static-libgcc ${CMAKE_CXX_FLAGS}")
406   link_directories(${CMAKE_BINARY_DIR}/staticlibs) # override dynamic libs
407   if(HAVE_SSL)
408     set(QUASSEL_SSL_LIBRARIES ssl crypto)  # these miss in static builds
409   endif(HAVE_SSL)
410 endif(STATIC AND CMAKE_COMPILER_IS_GNUCXX)
411
412 if(WIN32)
413   link_libraries(imm32 winmm dbghelp Secur32)  # missing by default :/
414   if(MSVC)
415     set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBUGINFO "/debug /INCREMENTAL:YES /NODEFAULTLIB:libcmt /DEFAULTLIB:msvcrt")
416     set(CMAKE_EXE_LINKER_FLAGS_DEBUG "/debug /INCREMENTAL:YES /NODEFAULTLIB:libcmt")
417     set(CMAKE_EXE_LINKER_FLAGS_DEBUGFULL "${CMAKE_EXE_LINKER_FLAGS_DEBUG}")
418     link_libraries(Version dwmapi shlwapi)
419   endif(MSVC)
420   if(HAVE_SSL AND STATIC)
421      find_package(OpenSSL REQUIRED)
422      link_libraries(${OPENSSL_LIBRARIES} ${OPENSSL_EAY_LIBRARIES})
423   endif(HAVE_SSL AND STATIC)
424 endif(WIN32)
425
426 if(INDICATEQT_FOUND)
427   add_definitions(-DXDG_APPS_INSTALL_DIR=${XDG_APPS_INSTALL_DIR})
428 endif()
429
430 if(NOT WIN32)
431   check_function_exists(umask HAVE_UMASK)
432   if(HAVE_UMASK)
433     add_definitions(-DHAVE_UMASK)
434   endif(HAVE_UMASK)
435 endif(NOT WIN32)
436
437 # Generate version information from Git
438 include(GetGitRevisionDescription)
439 get_git_head_revision(GIT_REFSPEC GIT_HEAD)
440 git_describe(GIT_DESCRIBE --long)
441
442 # Sanitize things if we're not in a Git repo
443 if(NOT GIT_HEAD OR NOT GIT_DESCRIBE)
444     set(GIT_HEAD "")
445     set(GIT_DESCRIBE "")
446 endif()
447
448 configure_file(version.h.in ${CMAKE_BINARY_DIR}/version.h @ONLY)
449
450 # These variables will be added to the main targets (CORE, QTCLIENT, MONO)
451 set(COMMON_DEPS ${RC_WIN32})
452 set(CORE_DEPS )
453 set(CLIENT_DEPS )
454
455 # Add needed subdirs - the order is important, since src needs some vars set by other dirs
456 add_subdirectory(data)
457 add_subdirectory(icons)
458 add_subdirectory(pics)
459 add_subdirectory(po)
460 add_subdirectory(src)
461
462 # Set up and display feature summary
463 #####################################################################
464
465 feature_summary(WHAT ALL
466                 INCLUDE_QUIET_PACKAGES
467                 FATAL_ON_MISSING_REQUIRED_PACKAGES
468 )