cmake_minimum_required(VERSION 3.19.0 FATAL_ERROR) set(SUPPORTED_LANGUAGES CXX C) if (APPLE) list (APPEND SUPPORTED_LANGUAGES OBJC OBJCXX) endif() project(krita LANGUAGES ${SUPPORTED_LANGUAGES}) message(STATUS "Using CMake version: ${CMAKE_VERSION}") # Select the Qt version we want to use # Qt5 is the default, set QT_MAJOR_VERSION to 6 to look for Qt6 option(BUILD_WITH_QT6 "Build against Qt 6" OFF) if (BUILD_WITH_QT6) set(MIN_QT_VERSION 6.0.0) set(MIN_FRAMEWORKS_VERSION 6.0.0) else() set(MIN_QT_VERSION 5.15.0) set(MIN_FRAMEWORKS_VERSION 5.44.0) endif() set( CMAKE_CXX_STANDARD 17 ) set( CMAKE_CXX_STANDARD_REQUIRED ON ) set( CMAKE_EXPORT_COMPILE_COMMANDS ON) if (POLICY CMP0002) cmake_policy(SET CMP0002 NEW) endif() if (POLICY CMP0017) cmake_policy(SET CMP0017 NEW) endif () if (POLICY CMP0020) cmake_policy(SET CMP0020 NEW) endif () if (POLICY CMP0022) cmake_policy(SET CMP0022 NEW) endif () if (POLICY CMP0026) cmake_policy(SET CMP0026 NEW) endif() if (POLICY CMP0042) cmake_policy(SET CMP0042 NEW) endif() if (POLICY CMP0046) cmake_policy(SET CMP0046 NEW) endif () if (POLICY CMP0059) cmake_policy(SET CMP0059 NEW) endif() if (POLICY CMP0063) cmake_policy(SET CMP0063 NEW) endif() if (POLICY CMP0054) cmake_policy(SET CMP0054 NEW) endif() if (POLICY CMP0064) cmake_policy(SET CMP0064 NEW) endif() if (POLICY CMP0071) cmake_policy(SET CMP0071 NEW) endif() if (POLICY CMP0135) cmake_policy(SET CMP0135 NEW) endif() # in CMake >=3.30; BoostConfig.cmake is shipped only by Boost >=1.82 if (POLICY CMP0167) cmake_policy(SET CMP0167 OLD) endif() set(CMAKE_POSITION_INDEPENDENT_CODE ON) if (APPLE) add_subdirectory(packaging/macos) if(NOT CMAKE_GENERATOR MATCHES "Xcode") execute_process(COMMAND xcodebuild -version -sdk macosx ProductVersion OUTPUT_VARIABLE XCODE_VERSION) endif() message(STATUS "XCode version: ${XCODE_VERSION}") set(MACOSX_RPATH TRUE) set(APPLE_SUPPRESS_X11_WARNING TRUE) set(KDE_SKIP_RPATH_SETTINGS TRUE) set(CMAKE_FIND_FRAMEWORK LAST) set(CMAKE_MACOSX_RPATH 1) set(BUILD_WITH_INSTALL_RPATH 1) set(MACOS_GUI_TEST "GUI") if (BUILD_WITH_QT6) set(MACOS_MINIMUM_VERSION 12) else() set(MACOS_MINIMUM_VERSION 10.15) endif() add_definitions(-mmacosx-version-min=${MACOS_MINIMUM_VERSION} -Wno-macro-redefined -Wno-deprecated-register) if (CMAKE_OSX_ARCHITECTURES) message(STATUS "CMake OSX architectures: ${CMAKE_OSX_ARCHITECTURES}") endif() endif() function(macos_test_fixrpath) if (APPLE AND BUILD_TESTING) foreach(TEST IN LISTS ARGN) set_property(TARGET ${TEST} PROPERTY BUILD_RPATH "@loader_path/../../../../lib;@loader_path/../lib;@loader_path/../Frameworks;${CMAKE_INSTALL_PREFIX}/${KDE_INSTALL_LIBDIR}") endforeach() endif() endfunction() if (CMAKE_COMPILER_IS_GNUCXX AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9 AND NOT WIN32) add_compile_options($<$:-Wno-suggest-override> -Wextra -Wno-class-memaccess) endif() ###################### ####################### ## Constants defines ## ####################### ###################### if (BUILD_WITH_QT6) set(KRITA_VERSION_STRING "6.0.4") set(KRITA_STABLE_VERSION_MAJOR 6) set(KRITA_STABLE_VERSION_MINOR 0) else() # define common versions of Krita applications, used to generate kritaversion.h # update these version for every release: set(KRITA_VERSION_STRING "5.3.4") # Major version: 3 for 3.x, 4 for 4.x, etc. set(KRITA_STABLE_VERSION_MAJOR 5) # Minor version: 0 for 4.0, 1 for 4.1, etc. set(KRITA_STABLE_VERSION_MINOR 3) endif() # Bugfix release version, or 0 for before the first stable release set(KRITA_VERSION_RELEASE 4) # the 4th digit, really only used for the Windows installer: # - [Pre-]Alpha: Starts from 0, increment 1 per release # - Beta: Starts from 50, increment 1 per release # - Stable: Set to 100, bump to 101 if emergency update is needed set(KRITA_VERSION_REVISION 0) # In MSI packages we cannot use the fourth digit for release numbering, # since this digit is used by Microsoft Store internally. Hence we cannot # release hotfix releases (like 6.0.1.1, 6.0.1.2) on Windows. Therefore we # use the same approach as on Android, we just number all the official # releases in the same X.Y.* branch sequentially. We use a simple formula # for that, e.g. 5.4.2.3 will be released as 5.4.10203.0. math(EXPR KRITA_MSI_VERSION_RELEASE_TRANSITIONAL "10000 + 100 * ${KRITA_VERSION_RELEASE} + ${KRITA_VERSION_REVISION}") # Uncomment the following if this is currently in the "stable" branch. # Do not uncomment for master branch. #set(KRITA_STABLE_BRANCH 1) #set(KRITA_ALPHA 1) # uncomment only for Alpha #set(KRITA_BETA 1) # uncomment only for Beta #set(KRITA_RC 1) # uncomment only for RC if(NOT DEFINED KRITA_ALPHA AND NOT DEFINED KRITA_BETA AND NOT DEFINED KRITA_RC) set(KRITA_STABLE 1) # do not edit endif() message(STATUS "Krita version: ${KRITA_VERSION_STRING}") # Define the generic version of the Krita libraries here # This makes it easy to advance it when the next Krita release comes. # # In general Krita does **not** guarantee any binary compatibility over C++ # libraries between the releases, so there is not reason to update SOVERSION # too often. # # The only reason why we use SOVERSION is to allow multiple **major** versions # of Krita to coexist in the same installation, e.g. Krita 5 and Krita 6. # # We don't support simultaneous installations of, say, Krita 5.1 and Krita 5.2 # (one should use AppImage for things like that) # # Historical note: # # We had a mess with versions previously, we used to increase the versions with # every minor release only. It caused multiple problems: 1) the soversions of # different major releases did overlap; 2) the soversions of different bugfix # releases were the same, even tough they were not binary compatible. # # In Krita 6 we just stop updating SOVERSION on minor releases and declare that # we have no binary compatibility between releases. # # Krita 5.0: SOVERSION -> 17 # Krita 5.1: SOVERSION -> 18 # Krita 5.2: SOVERSION -> 19 # Krita 5.3: SOVERSION -> 20 # # Krita 6.x: SOVERSION -> 21 # Krita 7.x: SOVERSION -> 22 # if(KRITA_STABLE_VERSION_MAJOR EQUAL 5) # In Krita 5 days we increased the SOVERSION with every minor release if(KRITA_STABLE_VERSION_MINOR LESS_EQUAL 3) math(EXPR GENERIC_KRITA_LIB_VERSION_MAJOR "${KRITA_STABLE_VERSION_MINOR} + 17") else() set(GENERIC_KRITA_LIB_VERSION_MAJOR 20) endif() elseif(KRITA_STABLE_VERSION_MAJOR GREATER_EQUAL 6) # In Krita 6 days we increased the SOVERSION only with every **major** release. # We don't guarantee any ABI compatibility between the releases, so there is no # use increasing SOVERSION too often math(EXPR GENERIC_KRITA_LIB_VERSION_MAJOR "${KRITA_STABLE_VERSION_MAJOR} - 6 + 21") endif() set(GENERIC_KRITA_LIB_VERSION "${GENERIC_KRITA_LIB_VERSION_MAJOR}.0.0") set(GENERIC_KRITA_LIB_SOVERSION "${GENERIC_KRITA_LIB_VERSION_MAJOR}") LIST (APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/modules") LIST (APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake/kde_macro") # fetch git revision for the current build set(KRITA_GIT_SHA1_STRING "") set(KRITA_GIT_BRANCH_STRING "") include(GetGitRevisionDescription) get_git_head_hash(GIT_SHA1) get_git_branch(GIT_BRANCH) if(GIT_SHA1) string(SUBSTRING ${GIT_SHA1} 0 7 GIT_SHA1) set(KRITA_GIT_SHA1_STRING ${GIT_SHA1} CACHE STRING "Git commit of the current build" FORCE) if(NOT GIT_BRANCH) set(GIT_BRANCH "(detached HEAD)") endif() set(KRITA_GIT_BRANCH_STRING ${GIT_BRANCH} CACHE STRING "Git branch of the current build" FORCE) endif() # create test make targets enable_testing() # collect list of broken tests, empty here to start fresh with each cmake run set(KRITA_BROKEN_TESTS "" CACHE INTERNAL "KRITA_BROKEN_TESTS") # Keep track of all test target (need special attention on macos) set(KRITA_TESTS_TARGET "" CACHE INTERNAL "KRITA_TESTS_TARGET") ############ ############# ## Options ## ############# ############ include(FeatureSummary) if (WIN32) option(USE_DRMINGW "Support the Dr. Mingw crash handler (only on windows)" ON) add_feature_info("Dr. Mingw" USE_DRMINGW "Enable the Dr. Mingw crash handler") if (MINGW) option(USE_MINGW_HARDENING_LINKER "Enable DEP (NX), ASLR and high-entropy ASLR linker flags (mingw-w64)" ON) add_feature_info("Linker Security Flags" USE_MINGW_HARDENING_LINKER "Enable DEP (NX), ASLR and high-entropy ASLR linker flags") if (USE_MINGW_HARDENING_LINKER) set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--dynamicbase -Wl,--nxcompat -Wl,--disable-auto-image-base") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--dynamicbase -Wl,--nxcompat -Wl,--disable-auto-image-base") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--dynamicbase -Wl,--nxcompat -Wl,--disable-auto-image-base") # Enable high-entropy ASLR for 64-bit # The image base has to be >4GB for HEASLR to be enabled. # The values used here are kind of arbitrary. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--high-entropy-va -Wl,--image-base,0x140000000") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--high-entropy-va -Wl,--image-base,0x180000000") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,--high-entropy-va -Wl,--image-base,0x180000000") else (USE_MINGW_HARDENING_LINKER) message(WARNING "Linker Security Flags not enabled!") endif (USE_MINGW_HARDENING_LINKER) # Clang does not generate DWARF arranges data by default, which makes # DrMingw not able to parse the DWARF debug symbols. Add -gdwarf-aranges # explicitly. # See: https://github.com/jrfonseca/drmingw/issues/42#issuecomment-516614561 if (CMAKE_C_COMPILER_ID STREQUAL "Clang") set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} -gdwarf-aranges") endif () if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -gdwarf-aranges") endif () elseif (MSVC) # Increase the stack size to match MinGW's. Prevents crashes with GMic. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:4194304") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /STACK:4194304") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /STACK:4194304") option(USE_CONTROL_FLOW_GUARD "Enable Control Flow Guard hardening (MSVC)" ON) add_feature_info("Linker Security Flags" USE_CONTROL_FLOW_GUARD "Enable Control Flow Guard") if (USE_CONTROL_FLOW_GUARD) add_compile_options(/guard:cf) add_link_options(/GUARD:CF) endif (USE_CONTROL_FLOW_GUARD) endif (MINGW) elseif(ANDROID) # Increase the stack size to match MinGW's. Prevents crashes with GMic. set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-z,stack-size=4194304") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,stack-size=4194304") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-z,stack-size=4194304") if (${CMAKE_ANDROID_NDK_VERSION} VERSION_GREATER_EQUAL "27.0.0" AND (CMAKE_ANDROID_ARCH_ABI STREQUAL "arm64-v8a" OR CMAKE_ANDROID_ARCH_ABI STREQUAL "x86_64")) message(STATUS "Enable 16K page alignment for Android NDK 27") set(PAGE_ALIGN_16K_LINKER_FLAGS -Wl,-z,max-page-size=16384 -Wl,-z,common-page-size=16384) add_link_options(${PAGE_ALIGN_16K_LINKER_FLAGS}) endif() endif () option(HIDE_SAFE_ASSERTS "Don't show message box for \"safe\" asserts, just ignore them automatically and dump a message to the terminal." ON) add_feature_info("Hide safe asserts" HIDE_SAFE_ASSERTS "Don't show message box for \"safe\" asserts, just ignore them automatically and dump a message to the terminal.") option(INSTALL_BENCHMARKS "Install benchmarks into the installation root to make them packagable" OFF) add_feature_info("Install benchmarks" INSTALL_BENCHMARKS "Install benchmarks into the installation root to make them packagable") option(CRASH_ON_SAFE_ASSERTS "Crash unconditionally whenever a \"safe\" assert happens. Useful for running unittests" OFF) add_feature_info("Crash on safe asserts" CRASH_ON_SAFE_ASSERTS "Crash unconditionally whenever a \"safe\" assert happens. Useful for running unittests") configure_file(config-safe-asserts.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-safe-asserts.h) option(USE_LOCK_FREE_HASH_TABLE "Use lock free hash table instead of blocking." ON) configure_file(config-hash-table-implementation.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-hash-table-implementation.h) add_feature_info("Lock free hash table" USE_LOCK_FREE_HASH_TABLE "Use lock free hash table instead of blocking.") option(FOUNDATION_BUILD "A Foundation build is a binary release build that can package some extra things like color themes. Linux distributions that build and install Krita into a default system location should not define this option to true." OFF) add_feature_info("Foundation Build" FOUNDATION_BUILD "A Foundation build is a binary release build that can package some extra things like color themes. Linux distributions that build and install Krita into a default system location should not define this option to true.") option(KRITA_ENABLE_BROKEN_TESTS "Enable tests that are marked as broken" OFF) add_feature_info("Enable Broken Tests" KRITA_ENABLE_BROKEN_TESTS "Runs broken test when \"make test\" is invoked (use -DKRITA_ENABLE_BROKEN_TESTS=ON to enable).") option(LIMIT_LONG_TESTS "Run long running unittests in a limited quick mode" ON) configure_file(config-limit-long-tests.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-limit-long-tests.h) add_feature_info("Limit long tests" LIMIT_LONG_TESTS "Run long running unittests in a limited quick mode") option(BUILD_KRITA_QT_DESIGNER_PLUGINS "Build Qt Designer plugins for Krita widgets" OFF) add_feature_info("Build Qt Designer plugins" BUILD_KRITA_QT_DESIGNER_PLUGINS "Builds Qt Designer plugins for Krita widgets (use -DBUILD_KRITA_QT_DESIGNER_PLUGINS=ON to enable).") option(ENABLE_UPDATERS "Enable updaters/update notifications" ON) configure_file(config-updaters.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-updaters.h) add_feature_info("Enable updaters" ENABLE_UPDATERS "Enable updaters/update notifications.") option(KRITA_ENABLE_PCH "Enable precompiled headers support" OFF) add_feature_info("Precompiled Headers" KRITA_ENABLE_PCH "precompiled headers make build process faster on some systems") option(USE_EXTERNAL_RAQM "Fetch Raqm dependency online instead of the embedded one" OFF) if(ANDROID) option(ANDROID_ENABLE_STDIO_FORWARDING "Enable forwarding of qDebug() and stdio messages to logcat" OFF) configure_file(config-android-stdio-forwarding.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-android-stdio-forwarding.h) add_feature_info("Enable debug logging on Android" ANDROID_ENABLE_STDIO_FORWARDING "Enable forwarding of qDebug() and stdio messages to logcat") endif() set(ADDRESS_SANITIZER_ENABLED FALSE) if (ECM_ENABLE_SANITIZERS MATCHES address) set(ADDRESS_SANITIZER_ENABLED TRUE) endif() add_feature_info("ASAN address sanitizer" ADDRESS_SANITIZER_ENABLED "crash Krita if it violates address access rules (-DECM_ENABLE_SANITIZERS=address)") # We don't want people to accidentally build unstable Krita versions if they # didn't mean to do so. This serves as an extra confirmation. You will get # errors during the configure step if you enable an unstable option. set(ALLOW_UNSTABLE "" CACHE STRING "Semicolon-separated set of features that make Krita unstable, but you want to build with them anyway") string(TOUPPER "${ALLOW_UNSTABLE}" ALLOW_UNSTABLE) add_feature_info("Unstable features allowed" ON "${ALLOW_UNSTABLE}") if(BUILD_WITH_QT6 AND NOT "QT6" IN_LIST ALLOW_UNSTABLE) message(FATAL_ERROR "Building Krita with Qt6 is not yet production-ready. Please don't " "package this and ship it as a stable version of the software.\n" "If you want to continue regardless, pass:\n" " -DALLOW_UNSTABLE=QT6" ) endif() # Branding. Available options: default, Beta, Plus, Next. Can be set from command line if ("${BRANDING}" STREQUAL "") if (DEFINED KRITA_STABLE) set(BRANDING "default") elseif (DEFINED KRITA_BETA OR DEFINED KRITA_RC) set(BRANDING "Beta") elseif (DEFINED KRITA_STABLE_BRANCH) # Alpha/pre-alpha in stable branch set(BRANDING "Plus") else () # Alpha/pre-alpha in master branch or other experiments set(BRANDING "Next") endif () endif() # Qt6 isn't stable, don't make it look like it is. if(BRANDING STREQUAL "default" AND BUILD_WITH_QT6) set(BRANDING "Beta") endif() message(STATUS "Branding selected: ${BRANDING}") include(MacroJPEG) ######################################################### ## Look for Python3 - it is also searched by KF5, ## ## so we should request the correct version in advance ## ######################################################### function(TestCompileLinkPythonLibs OUTPUT_VARNAME) include(CheckCXXSourceCompiles) set(CMAKE_REQUIRED_INCLUDES ${Python_INCLUDE_DIRS}) set(CMAKE_REQUIRED_LIBRARIES ${Python_LIBRARIES}) if (MINGW) set(CMAKE_REQUIRED_DEFINITIONS -D_hypot=hypot) endif (MINGW) unset(${OUTPUT_VARNAME} CACHE) CHECK_CXX_SOURCE_COMPILES(" // https://bugs.python.org/issue22411 #if defined(_MSC_VER) # ifdef _DEBUG # undef _DEBUG # endif /* _DEBUG */ #endif /* _MSC_VER */ #include int main(int argc, char *argv[]) { Py_InitializeEx(0); }" ${OUTPUT_VARNAME}) endfunction() if(NOT WIN32) # On Unix systems we ship our own version of Python and manually set PATH # pointing to that. This version of Python may differ from the one installed # in the system, so we should make sure that the version of Python mentioned # in VIRTUAL_ENV does **not** take precedence over the one we ship ourselves. if(DEFINED ENV{VIRTUAL_ENV}) message(WARNING "VIRTUAL_ENV environment variable is set! It may cause clashes with our own Python version. Instructing CMake to ignore the virtual environment...") set (Python_FIND_VIRTUALENV STANDARD) endif() endif() if(WIN32) set(Python_FIND_STRATEGY LOCATION) find_package(Python 3.8 COMPONENTS Development Interpreter) if (Python_FOUND) find_package(PythonLibrary 3.8) TestCompileLinkPythonLibs(CAN_USE_PYTHON_LIBS) if (NOT CAN_USE_PYTHON_LIBS) file(READ ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeError.log ERROR_LOG) string(REPLACE "\n" "\n " ERROR_LOG "${ERROR_LOG}") message(FATAL_ERROR "Compiling with Python library failed, please check whether the architecture is correct!\nCMakeError.log:\n ${ERROR_LOG}\n\n") endif (NOT CAN_USE_PYTHON_LIBS) endif (Python_FOUND) else(WIN32) find_package(PythonLibrary 3.8) endif(WIN32) ######################## ######################### ## Look for KDE and Qt ## ######################### ######################## if (BUILD_WITH_QT6) set(QT_MAJOR_VERSION 6) find_package(ECM 6.0 REQUIRED CONFIG) else() set(QT_MAJOR_VERSION 5) find_package(ECM 5.91 REQUIRED CONFIG) endif() # KDE Frameworks set(KF_MAJOR ${QT_MAJOR_VERSION}) if (KF_MAJOR STREQUAL "6") set(KF_DEP_VERSION "6.0.0") endif() set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${ECM_MODULE_PATH}) include(ECMOptionalAddSubdirectory) include(ECMAddAppIcon) include(ECMSetupVersion) include(ECMMarkNonGuiExecutable) include(ECMGenerateHeaders) include(GenerateExportHeader) include(ECMMarkAsTest) include(ECMInstallIcons) include(CMakePackageConfigHelpers) include(WriteBasicConfigVersionFile) include(CheckFunctionExists) include(CheckCXXSymbolExists) set (KDE_COMPILERSETTINGS_LEVEL "5.0") set (KDE_QT_MODERNCODE_DEFINITIONS_LEVEL "5.0") set (KDE_SKIP_PEDANTIC_WARNINGS_SETTINGS TRUE) set (KDE_SKIP_MISSING_INCLUDE_DIRS_WARNINGS_SETTINGS TRUE) set (KDE_SKIP_NULLPTR_WARNINGS_SETTINGS TRUE) include(KDECompilerSettings) include(KDEInstallDirs) include(KDECMakeSettings) if (WIN32) # Qt6 targets Windows10, so we shouldn't change it in any way if (QT_MAJOR_VERSION STREQUAL "5") # KDECompilerSettings sets Windows Vista as the default, # while MSVC's default is 0x0A00 (_WIN32_WINNT_WIN10, sdkddkver.h) and # MinGW's is 0x0601 (_WIN32_WINNT_WIN7, _mingw.h). # Both are enough to supply the APIs we need in main.cc, but since we # need the Windows 8 APIs anyway for the surface orientation and Store API, # we set the minimum here. remove_definitions(-D_WIN32_WINNT=0x0600 -DWINVER=0x0600 -D_WIN32_IE=0x0600) add_definitions(-D_WIN32_WINNT=0x0602 -DWINVER=0x0602 -D_WIN32_IE=0x0602) endif() if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC") if (MSVC) # or CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC" # KDE's CompilerSettings module sets -Wall -Wextra for Clang. # However, -Wall on clang-cl maps to -Weverything, which turns on way too # much, so we're using -W4 instead, which is mapped to clang's -Wall -Wextra. # Source: https://hg.mozilla.org/mozilla-central/rev/ffb7bfbfc328 string(REPLACE "-Wall -Wextra" "-W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") string(REPLACE "-Wall -Wextra" "-W4" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") # Allow KoColorSpaceMaths operators to build. add_compile_options("/permissive") endif() # Remove these invalid flags. string(REPLACE "-fno-common" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") string(REPLACE "-fno-operator-names" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") string(REPLACE "-fdiagnostics-color=always" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") string(REPLACE "-Wl,--no-undefined" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") string(REPLACE "-Wl,--no-undefined" "" CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}") string(REPLACE "-Wl,--fatal-warnings" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") string(REPLACE "-Wl,--fatal-warnings" "" CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}") endif() endif() # do not reorder to be alphabetical: this is the order in which the frameworks # depend on each other. find_package(KF${KF_MAJOR} ${MIN_FRAMEWORKS_VERSION} REQUIRED COMPONENTS Config WidgetsAddons Completion CoreAddons GuiAddons I18n ItemViews ) find_package(Qt${QT_MAJOR_VERSION} ${MIN_QT_VERSION} REQUIRED COMPONENTS Core Gui Widgets Xml Network PrintSupport Svg Test Concurrent Sql ) if (ANDROID) if (QT_MAJOR_VERSION STREQUAL "5") find_package(Qt${QT_MAJOR_VERSION} ${MIN_QT_VERSION} REQUIRED COMPONENTS AndroidExtras ) endif() endif() if (QT_MAJOR_VERSION STREQUAL "6") find_package(Qt${QT_MAJOR_VERSION} ${MIN_QT_VERSION} REQUIRED COMPONENTS Core5Compat OpenGL OpenGLWidgets SvgWidgets ) find_package(Qt${QT_MAJOR_VERSION} ${MIN_QT_VERSION} OPTIONAL_COMPONENTS WaylandClient ) find_package(KF6 ${MIN_FRAMEWORKS_VERSION} REQUIRED COMPONENTS ColorScheme ) # Qt 6.10 has split this into it's own CMake module, it's no longer included with Gui if (Qt6Gui_VERSION VERSION_GREATER_EQUAL "6.10.0") find_package(Qt6GuiPrivate ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE) get_target_property(Qt6Gui_PRIVATE_INCLUDE_DIRS Qt6::GuiPrivate INTERFACE_INCLUDE_DIRECTORIES) # QtGui depends on private headers form QtCore as well find_package(Qt6CorePrivate ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE) get_target_property(Qt6Core_PRIVATE_INCLUDE_DIRS Qt6::CorePrivate INTERFACE_INCLUDE_DIRECTORIES) # Currently we depend on the Qt6Gui_PRIVATE_INCLUDE_DIRS variable to selectively include # the needed headers, but it will fail to compile in 6.10 since the private headers exist # in separate directories. So we'll just shove them into the variable we expect for now. list(APPEND Qt6Gui_PRIVATE_INCLUDE_DIRS ${Qt6Core_PRIVATE_INCLUDE_DIRS}) endif() endif() set(HAVE_WAYLAND FALSE) if (TARGET Qt::WaylandClient) message(STATUS "Found Qt::WaylandClient, enabling kritawayland platform") set(HAVE_WAYLAND TRUE) # Qt 6.10 has split the private module, see above for a better explanation if (Qt6Gui_VERSION VERSION_GREATER_EQUAL "6.10.0") find_package(Qt6WaylandClientPrivate ${REQUIRED_QT_VERSION} REQUIRED NO_MODULE) get_target_property(Qt6WaylandClient_PRIVATE_INCLUDE_DIRS Qt6::WaylandClientPrivate INTERFACE_INCLUDE_DIRECTORIES) endif() endif() option(KRITA_USE_SURFACE_COLOR_MANAGEMENT_API "Use per-surface color management API (e.g. when using Wayland)" ${HAVE_WAYLAND}) add_feature_info("Enable per-surface color management API" KRITA_USE_SURFACE_COLOR_MANAGEMENT_API "adds support for an independent color space management for the canvas") if (NOT HAVE_WAYLAND AND KRITA_USE_SURFACE_COLOR_MANAGEMENT_API) message(WARNING "KRITA_USE_SURFACE_COLOR_MANAGEMENT_API was set when there is no Wayland support, surface management will be useless as no plugins are built") endif() configure_file(config-use-surface-color-management-api.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-use-surface-color-management-api.h) # # Check for the presence of custom patches in Qt # set(CMAKE_REQUIRED_INCLUDES ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS}) set(CMAKE_REQUIRED_LIBRARIES ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES}) check_cxx_symbol_exists(QT_HAS_ENTER_LEAVE_PATCH "QtGui/qevent.h" KRITA_QT_HAS_ENTER_LEAVE_PATCH) if (QT_MAJOR_VERSION STREQUAL "5") # in Qt5 we didn't have a separate definition for key-press/release patch set(KRITA_QT_HAS_UNBALANCED_KEY_PRESS_RELEASE_PATCH ${KRITA_QT_HAS_ENTER_LEAVE_PATCH}) else() check_cxx_symbol_exists(QT_HAS_UNBALANCED_KEY_PRESS_RELEASE_PATCH "QtGui/qevent.h" KRITA_QT_HAS_UNBALANCED_KEY_PRESS_RELEASE_PATCH) endif() unset(CMAKE_REQUIRED_INCLUDES) unset(CMAKE_REQUIRED_LIBRARIES) if (QT_MAJOR_VERSION STREQUAL "5") # in Qt5 we didn't have a separate definition for key-press/release patch set(KRITA_QT_HAS_UPDATE_COMPRESSION_PATCH FALSE) else() set(CMAKE_REQUIRED_INCLUDES ${Qt6Gui_INCLUDE_DIRS} ${Qt6Gui_PRIVATE_INCLUDE_DIRS}) set(CMAKE_REQUIRED_LIBRARIES ${Qt6Gui_LIBRARIES}) CHECK_CXX_SOURCE_COMPILES(" #include int main(int, char *[]) { bool (QRhi::*x)() const; x = &QRhi::isLastFrameCompletedOnGPU; Q_UNUSED(x); return 0; } " KRITA_QT_HAS_UPDATE_COMPRESSION_PATCH ) unset(CMAKE_REQUIRED_INCLUDES) unset(CMAKE_REQUIRED_LIBRARIES) endif() option(KRITA_QT_HAS_ENTER_LEAVE_PATCH "Qt has a custom patch for unbalanced enter/leave events" ON) add_feature_info("Qt: Unbalanced Enter/Leave patch" KRITA_QT_HAS_ENTER_LEAVE_PATCH "Krita will disable internal workarounds for unbalanced Enter/Leave") option(KRITA_QT_HAS_UNBALANCED_KEY_PRESS_RELEASE_PATCH "Qt has a custom patch for unbalanced KeyPress/KeyRelease events in non-latin layouts" ON) add_feature_info("Qt: Unbalanced KeyPress/KeyRelease in non-latin layout patch" KRITA_QT_HAS_UNBALANCED_KEY_PRESS_RELEASE_PATCH "Krita will disable internal workarounds for unbalanced KeyPress/KeyRelease events") option(KRITA_QT_HAS_UPDATE_COMPRESSION_PATCH "Qt has a custom patch for limiting FPS to the screen framerate" ON) add_feature_info("Qt: Compressed updates patch" KRITA_QT_HAS_UPDATE_COMPRESSION_PATCH "Krita will compress the screen updates to the maximum FPS of available displays") # # Check for the presence the Wintab switch in Qt5 # if (WIN32 AND QT_MAJOR_VERSION STREQUAL "5") set(CMAKE_REQUIRED_INCLUDES ${Qt5Core_INCLUDE_DIRS}) set(CMAKE_REQUIRED_LIBRARIES ${Qt5Core_LIBRARIES}) CHECK_CXX_SOURCE_COMPILES(" #include int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_MSWindowsUseWinTabAPI); } " QT5_HAS_WINTAB_SWITCH ) unset(CMAKE_REQUIRED_INCLUDES) unset(CMAKE_REQUIRED_LIBRARIES) #QT5_HAS_WINTAB_SWITCH configure_file(config_qt5_has_wintab_switch.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config_qt5_has_wintab_switch.h) endif () if (WIN32) if (QT_MAJOR_VERSION STREQUAL "5") set(CMAKE_REQUIRED_INCLUDES ${Qt5Core_INCLUDE_DIRS} ${Qt5Gui_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS}) set(CMAKE_REQUIRED_LIBRARIES ${Qt5Core_LIBRARIES} ${Qt5Gui_LIBRARIES} ${Qt5Widgets_LIBRARIES}) CHECK_CXX_SOURCE_COMPILES(" #include int main(int argc, char *argv[]) { QSurfaceFormat fmt; fmt.setColorSpace(QSurfaceFormat::scRGBColorSpace); fmt.setColorSpace(QSurfaceFormat::bt2020PQColorSpace); } " HAVE_HDR ) unset(CMAKE_REQUIRED_INCLUDES) unset(CMAKE_REQUIRED_LIBRARIES) else() set(CMAKE_REQUIRED_INCLUDES ${Qt6Core_INCLUDE_DIRS} ${Qt6Gui_INCLUDE_DIRS} ${Qt6Widgets_INCLUDE_DIRS} ${Qt6OpenGLWidgets_INCLUDE_DIRS}) set(CMAKE_REQUIRED_LIBRARIES ${Qt6Core_LIBRARIES} ${Qt6Gui_LIBRARIES} ${Qt6Widgets_LIBRARIES} ${Qt6OpenGLWidgets_LIBRARIES}) CHECK_CXX_SOURCE_COMPILES(" #include #include int main(int argc, char *argv[]) { QOpenGLWidget *w = nullptr; w->setTextureColorSpace(QColorSpace()); } " HAVE_HDR ) unset(CMAKE_REQUIRED_INCLUDES) unset(CMAKE_REQUIRED_LIBRARIES) endif() endif() configure_file(config-hdr.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-hdr.h) set(CMAKE_REQUIRED_INCLUDES ${Qt5Core_INCLUDE_DIRS} ${Qt5Gui_INCLUDE_DIRS} ${Qt5Widgets_INCLUDE_DIRS}) set(CMAKE_REQUIRED_LIBRARIES ${Qt5Core_LIBRARIES} ${Qt5Gui_LIBRARIES} ${Qt5Widgets_LIBRARIES}) CHECK_CXX_SOURCE_COMPILES(" #include int main(int argc, char *argv[]) { QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Round); QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::RoundPreferFloor); QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); } " HAVE_HIGH_DPI_SCALE_FACTOR_ROUNDING_POLICY ) configure_file(config-high-dpi-scale-factor-rounding-policy.h.in ${CMAKE_CURRENT_BINARY_DIR}/config-high-dpi-scale-factor-rounding-policy.h) CHECK_CXX_SOURCE_COMPILES(" #include int main(int argc, char *argv[]) { QMdiArea area; area.setOption(QMdiArea::AlwaysShowSubwindowNameInTitleBar); } " HAVE_QMDIAREA_ALWAYS_SHOW_SUBWINDOW_TITLE ) configure_file(config-qmdiarea-always-show-subwindow-title.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-qmdiarea-always-show-subwindow-title.h) if (WIN32) CHECK_CXX_SOURCE_COMPILES(" #include int main(int argc, char *argv[]) { QWindowsWindowFunctions::setHasBorderInFullScreenDefault(true); } " HAVE_SET_HAS_BORDER_IN_FULL_SCREEN_DEFAULT ) configure_file(config-set-has-border-in-full-screen-default.h.in ${CMAKE_CURRENT_BINARY_DIR}/config-set-has-border-in-full-screen-default.h) endif (WIN32) CHECK_CXX_SOURCE_COMPILES(" #include int main(int argc, char *argv[]) { QCoreApplication::setKritaAttribute(KRITA_QATTRIBUTE_ANDROID_EMULATE_MOUSE_BUTTONS_FOR_PAGE_UP_DOWN); } " KRITA_QT_HAS_ANDROID_EMULATE_MOUSE_BUTTONS_FOR_PAGE_UP_DOWN ) CHECK_CXX_SOURCE_COMPILES(" #include int main(int argc, char *argv[]) { QCoreApplication::setKritaAttribute(KRITA_QATTRIBUTE_ANDROID_IGNORE_HISTORIC_TABLET_EVENTS); } " KRITA_QT_HAS_ANDROID_IGNORE_HISTORIC_TABLET_EVENTS ) CHECK_CXX_SOURCE_COMPILES(" #include int main(int argc, char *argv[]) { QCoreApplication::setKritaAttribute(KRITA_QATTRIBUTE_ANDROID_EMULATE_MOUSE_BUTTONS_FOR_HIGH_FUNCTION_KEYS); } " KRITA_QT_HAS_ANDROID_EMULATE_MOUSE_BUTTONS_FOR_HIGH_FUNCTION_KEYS ) CHECK_CXX_SOURCE_COMPILES(" #include #ifndef KRITA_QSCROLLER_PATCH #error \"QScroller filter patch not present\" #endif int main(int argc, char *argv[]) {} " KRITA_QT_HAS_QSCROLLER_FILTER ) CHECK_CXX_SOURCE_COMPILES(" #include int main(int argc, char *argv[]) { return Qt::ANDROID_INPUT_PLATFORM_DATA_SOFT_INPUT_ADJUST_NOTHING; } " KRITA_QT_HAS_ANDROID_INPUT_PLATFORM_DATA_SOFT_INPUT_ADJUST_NOTHING ) set(CMAKE_REQUIRED_INCLUDES ${Qt${QT_MAJOR_VERSION}Gui_INCLUDE_DIRS} ${Qt${QT_MAJOR_VERSION}Gui_PRIVATE_INCLUDE_DIRS}) set(CMAKE_REQUIRED_LIBRARIES ${Qt${QT_MAJOR_VERSION}Gui_LIBRARIES}) CHECK_CXX_SOURCE_COMPILES(" #include int main(int argc, char *argv[]) { QPlatformScreen *screen = nullptr; screen->setDensityAdjustment(1.0); return screen->densityAdjustment(); } " KRITA_QT_HAS_ANDROID_QPLATFORMSCREEN_DENSITY_ADJUSTMENT ) configure_file(config-qt-patches-present.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-qt-patches-present.h) unset(CMAKE_REQUIRED_INCLUDES) unset(CMAKE_REQUIRED_LIBRARIES) include (MacroAddFileDependencies) include (MacroBoolTo01) include (MacroEnsureOutOfSourceBuild) macro_ensure_out_of_source_build("Compiling Krita inside the source directory is not possible. Please refer to the build instruction https://community.kde.org/Krita#Build_Instructions") # Note: OPTIONAL_COMPONENTS does not seem to be reliable # (as of ECM 5.15.0, CMake 3.2) find_package(Qt${QT_MAJOR_VERSION}Quick ${MIN_QT_VERSION}) set_package_properties(Qt${QT_MAJOR_VERSION}Quick PROPERTIES DESCRIPTION "QtQuick" URL "https://www.qt.io/" TYPE OPTIONAL PURPOSE "Optionally used for the touch gui for Krita") macro_bool_to_01(Qt${QT_MAJOR_VERSION}Quick_FOUND HAVE_QT_QUICK) find_package(Qt${QT_MAJOR_VERSION}QuickWidgets ${MIN_QT_VERSION}) set_package_properties(Qt${QT_MAJOR_VERSION}QuickWidgets PROPERTIES DESCRIPTION "QtQuickWidgets" URL "https://www.qt.io/" TYPE OPTIONAL PURPOSE "Optionally used for the touch gui for Krita") if (Qt${QT_MAJOR_VERSION}QuickWidgets_FOUND) # This is needed because Qt dependencies aren't added by ECM but by androideployqt, # so it doesn't benefit from our patch in ECM. list (APPEND ANDROID_EXTRA_LIBS $) find_package(Qt${QT_MAJOR_VERSION}QuickControls2 ${MIN_QT_VERSION}) set_package_properties(Qt${QT_MAJOR_VERSION}QuickControls2 PROPERTIES DESCRIPTION "QtQuickControls" URL "https://www.qt.io/" TYPE OPTIONAL PURPOSE "Optionally used for the touch gui for Krita") endif() if (NOT WIN32 AND NOT APPLE AND NOT ANDROID AND NOT HAIKU) if (QT_MAJOR_VERSION STREQUAL "5") find_package(Qt${QT_MAJOR_VERSION} ${MIN_QT_VERSION} REQUIRED X11Extras) endif() find_package(Qt${QT_MAJOR_VERSION}DBus ${MIN_QT_VERSION}) set_package_properties(Qt${QT_MAJOR_VERSION}DBus PROPERTIES DESCRIPTION "Qt DBUS integration" URL "https://www.qt.io/" TYPE OPTIONAL PURPOSE "Optionally used to provide a dbus api on Linux") macro_bool_to_01(Qt${QT_MAJOR_VERSION}DBus_FOUND HAVE_DBUS) find_package(KF${KF_MAJOR}Crash ${MIN_FRAMEWORKS_VERSION}) macro_bool_to_01(KF${KF_MAJOR}Crash_FOUND HAVE_KCRASH) set_package_properties(KF${KF_MAJOR}Crash PROPERTIES DESCRIPTION "KDE's Crash Handler" URL "https://api.kde.org/kcrash-index.html" TYPE OPTIONAL PURPOSE "Optionally used to provide crash reporting on Linux") find_package(X11 REQUIRED COMPONENTS Xinput) set(HAVE_X11 TRUE) add_definitions(-DHAVE_X11) else() set(HAVE_DBUS FALSE) set(HAVE_X11 FALSE) endif() add_definitions( -DQT_USE_QSTRINGBUILDER -DQT_NO_SIGNALS_SLOTS_KEYWORDS -DQT_NO_URL_CAST_FROM_STRING -DQT_USE_FAST_CONCATENATION -DQT_USE_FAST_OPERATOR_PLUS ) # MSVC is unable to disambiguate between definitions of QVector # and QPolygonF. This is a known upstream bug e.g.: # - https://phabricator.kde.org/D21314 # - https://codereview.qt-project.org/c/qt/qtbase/+/180229 # Starting with Qt 5.13, it is impossible to use strict iterators # wholesale because of: # https://github.com/qt/qtbase/commit/972f8845a85d6a07140025e4257cb8a1a2699b5d if (NOT (MSVC OR CMAKE_CXX_SIMULATE_ID STREQUAL "MSVC")) add_definitions(-DQT_STRICT_ITERATORS) endif() add_compile_definitions( QT_DISABLE_DEPRECATED_BEFORE=0x050E00 ) add_definitions(-DTRANSLATION_DOMAIN=\"krita\") # # The reason for this mode is that the Debug mode disable inlining # if(CMAKE_COMPILER_IS_GNUCXX) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fext-numeric-literals") endif() option(KRITA_DEVS "For Krita developers. This modifies the DEBUG build type to use -O3 -g, while still enabling Q_ASSERT. This is necessary because the Qt5 cmake modules normally append QT_NO_DEBUG to any build type that is not labeled Debug") if (KRITA_DEVS) set(CMAKE_CXX_FLAGS_DEBUG "-O3 -g" CACHE STRING "" FORCE) endif() if(UNIX) set(CMAKE_REQUIRED_LIBRARIES "${CMAKE_REQUIRED_LIBRARIES};m") endif() if(WIN32) if(MSVC) # C4522: 'class' : multiple assignment operators specified set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -wd4522 -wd4138 /Zc:__cplusplus") # libs\ui\dialogs\kis_about_application.cpp : fatal error C1128: number of sections exceeded object file format limit: compile with /bigobj set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj") # Enable intrinsics set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Oi") # Favor fast code set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Ot") # Function-level linking set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Gy") # Our code is UTF-8 encoded. add_compile_options(/utf-8) endif() endif() if (MSVC AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang") # Clang/CL is incompatible with this flag set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /RELEASE") set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} /RELEASE") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /RELEASE") endif() # Force enable a good many optimizations if (MSVC AND NOT BUILD_TESTING) # Aggressive inlining (Release) string(REPLACE "Ob2" "Ob3" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") # Aggressive inlining (RelWithDebInfo) string(REPLACE "Ob1" "Ob3" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") # Whole program optimization set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /GL") # For all objects: # - strip unused functions # - fold identical functions # - link-time code generation string(REPLACE "INCREMENTAL" "INCREMENTAL:NO" CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO}") string(REPLACE "INCREMENTAL" "INCREMENTAL:NO" CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO}") string(REPLACE "INCREMENTAL" "INCREMENTAL:NO" CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO}") set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} /OPT:ICF,REF /LTCG") set(CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO} /OPT:ICF,REF /LTCG") set(CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO} /OPT:ICF,REF /LTCG") endif() # KDECompilerSettings adds the `--export-all-symbols` linker flag. # We don't really need it. if(MINGW) string(REPLACE "-Wl,--export-all-symbols" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}") string(REPLACE "-Wl,--export-all-symbols" "" CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}") endif(MINGW) if(MINGW) # Hack CMake's variables to tell AR to create thin archives to reduce unnecessary writes. # Source of definition: https://github.com/Kitware/CMake/blob/v3.14.1/Modules/Platform/Windows-GNU.cmake#L128 # Thin archives: https://sourceware.org/binutils/docs/binutils/ar.html#index-thin-archives macro(mingw_use_thin_archive lang) foreach(rule CREATE_SHARED_MODULE CREATE_SHARED_LIBRARY LINK_EXECUTABLE) string(REGEX REPLACE "( [^ T]+) " "\\1T " CMAKE_${lang}_${rule} "${CMAKE_${lang}_${rule}}") endforeach() endmacro() mingw_use_thin_archive(CXX) endif(MINGW) # enable exceptions globally # WARNING: in MSVC this will NOT catch exceptions thrown through C code # see: # - https://learn.microsoft.com/en-us/cpp/build/reference/eh-exception-handling-model?view=msvc-170#arguments # - https://invent.kde.org/frameworks/extra-cmake-modules/-/blob/v5.101.0/kde-modules/KDECompilerSettings.cmake#L502-526 kde_enable_exceptions() function(krita_select_pch_file targetname pch_file_name) #TODO: make kritaimage and kritaglobal targets to link to its own PCH if (targetname STREQUAL "kritaglobal") set(${pch_file_name} kis_qt_only_pch.h PARENT_SCOPE) elseif (targetname STREQUAL "kritaimage") set(${pch_file_name} kis_global_pch.h PARENT_SCOPE) else () set(immediate_deps $) set(depends_on_kritaui $) set(depends_on_kritaimage $) set(depends_on_kritalibkis $) set(depends_on_kritalibpaintop $) set(${pch_file_name} $,kis_image_pch.h,kis_global_pch.h> PARENT_SCOPE) endif() endfunction() macro(kis_add_library) # the first run strips only options specific to kis_add_library # to create arguments for real add_library call cmake_parse_arguments(REAL "" PCH_FILE "" ${ARGV} ) add_library(${REAL_UNPARSED_ARGUMENTS}) if (KRITA_ENABLE_PCH) # the second run strips out all the option supported by the function # to let the script to calculate the number of source files in # the library set(options INTERFACE STATIC SHARED MODULE EXCLUDE_FROM_ALL OBJECT ALIAS) set(one_value_keywords PCH_FILE) set(multi_value_keywords) cmake_parse_arguments(LOCAL "${options}" "${one_value_keywords}" "" ${ARGV} ) list(LENGTH LOCAL_UNPARSED_ARGUMENTS source_count) list(GET REAL_UNPARSED_ARGUMENTS 0 NEW_LIBRARY_TARGET) if (NOT LOCAL_PCH_FILE) krita_select_pch_file(${NEW_LIBRARY_TARGET} LOCAL_PCH_FILE) #file(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/out/${NEW_LIBRARY_TARGET}.txt" CONTENT ${LOCAL_PCH_FILE}) endif() # if the number of sources in the library is greater # than a threshold value, then we can try to use PCH # for this library if (${source_count} GREATER "2" AND NOT LOCAL_INTERFACE AND NOT LOCAL_ALIAS AND LOCAL_PCH_FILE) set_property(TARGET ${NEW_LIBRARY_TARGET} PROPERTY PCH_WARN_INVALID TRUE ) target_precompile_headers(${NEW_LIBRARY_TARGET} PRIVATE "$<$:${CMAKE_SOURCE_DIR}/pch/${LOCAL_PCH_FILE}>") endif() endif() endmacro() # overcome some platform incompatibilities if(WIN32) if (MSVC) include_directories(${CMAKE_CURRENT_SOURCE_DIR}/winquirks) add_definitions(-D_USE_MATH_DEFINES) add_definitions(-DNOMINMAX) endif() endif() # set custom krita plugin installdir if (ANDROID) # use default ABI if (NOT DEFINED ANDROID_ABI) set (ANDROID_ABI arm64-v8a) endif() if (NOT DEFINED ANDROID_SDK_ROOT) message (FATAL_ERROR "ANDROID_SDK_ROOT argument is not set") endif() set (KRITA_PLUGIN_INSTALL_DIR ${KDE_INSTALL_LIBDIR}) # set (KDE_INSTALL_DATADIR ${CMAKE_INSTALL_PREFIX}/assets) # From ECM # Because Qt changes library suffix (to include arch), this changes name of # libraries that depend on Qt, but its Find file may not necessarily be # adapted for this. set(CMAKE_FIND_LIBRARY_SUFFIXES "_${CMAKE_ANDROID_ARCH_ABI}.so" ".so" ".a") else() set (KRITA_PLUGIN_INSTALL_DIR ${KDE_INSTALL_LIBDIR}/kritaplugins) endif() ########################### ############################ ## Required dependencies ## ############################ ########################### # FIXME: Still hardcoded if (ANDROID) set (Boost_COMPILER clang) find_package(unwindstack REQUIRED) endif() find_package(PNG REQUIRED "1.2.6") if (APPLE) # this is not added correctly on OSX -- see https://forum.kde.org/viewtopic.php?f=139&t=101867&p=221242#p221242 include_directories(SYSTEM ${PNG_INCLUDE_DIR}) endif() if (MINGW AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang") string(REGEX REPLACE "([0-9])\\.([0-9])(\\.[0-9])?" "\\1" KRITA_boost_COMPILER_VERSION ${CMAKE_CXX_COMPILER_VERSION}) set(Boost_COMPILER "mgw${KRITA_boost_COMPILER_VERSION}") endif() find_package(Boost 1.69 REQUIRED) set_package_properties(Boost PROPERTIES DESCRIPTION "Boost provides free peer-reviewed portable C++ source libraries." URL "https://www.boost.org" TYPE REQUIRED) target_link_libraries(Boost::boost INTERFACE Boost::disable_autolinking ) # Disallow usage of std::unary_function. # See https://github.com/boostorg/container_hash/issues/22 # and https://releases.llvm.org/15.0.0/projects/libcxx/docs/ReleaseNotes.html#deprecations-and-removals if(Boost_VERSION VERSION_LESS "1.81.0") target_compile_definitions(Boost::boost INTERFACE BOOST_NO_CXX98_FUNCTION_BASE ) endif() find_package(Immer REQUIRED) find_package(Zug REQUIRED) find_package(Lager REQUIRED) ## ## Test for GNU Scientific Library ## find_package(GSL) set_package_properties(GSL PROPERTIES URL "https://www.gnu.org/software/gsl" TYPE RECOMMENDED PURPOSE "Required by Krita's Transform tool.") macro_bool_to_01(GSL_FOUND HAVE_GSL) configure_file(config-gsl.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-gsl.h ) ########################### ############################ ## Optional dependencies ## ############################ ########################### find_package(WebP 1.2.0 COMPONENTS demux mux) set_package_properties(WebP PROPERTIES URL "https://developers.google.com/speed/webp" TYPE OPTIONAL PURPOSE "Required by the WebP plugin" ) ## ## Test for KSeExpr ## if (QT_MAJOR_VERSION STREQUAL "5") find_package(KSeExpr 4.0.0.0) else() find_package(KSeExpr 6.0.0.0) endif() set_package_properties(KSeExpr PROPERTIES URL "https://invent.kde.org/graphics/kseexpr" TYPE OPTIONAL PURPOSE "Required by the SeExpr generator layer" ) macro_bool_to_01(KSeExpr_FOUND HAVE_SEEXPR) configure_file(config-seexpr.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-seexpr.h ) find_package(ZLIB REQUIRED) set_package_properties(ZLIB PROPERTIES DESCRIPTION "Compression library" URL "https://www.zlib.net/" TYPE REQUIRED PURPOSE "Required by Krita's PNG and PSD support") macro_bool_to_01(ZLIB_FOUND HAVE_ZLIB) find_package(OpenEXR) macro_bool_to_01(OpenEXR_FOUND HAVE_OPENEXR) if(OpenEXR_FOUND) set(LINK_OPENEXR_LIB OpenEXR::IlmImf) endif() find_package(TIFF) set_package_properties(TIFF PROPERTIES DESCRIPTION "TIFF Library and Utilities" URL "http://www.libtiff.org" TYPE OPTIONAL PURPOSE "Required by the Krita TIFF filter") include(CheckLibTIFFPSDSupport) configure_file(config-tiff.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-tiff.h) find_package(JPEG) set_package_properties(JPEG PROPERTIES DESCRIPTION "Free library for JPEG image compression. Note that libjpeg8 is NOT supported." URL "https://www.libjpeg-turbo.org" TYPE OPTIONAL PURPOSE "Required by the Krita JPEG filter") if (JPEG_FOUND) macro_bool_to_01(JPEG_FOUND HAVE_JPEG) endif() find_package(libjpeg-turbo 2.1.3 COMPONENTS turbojpeg) set_package_properties(libjpeg-turbo PROPERTIES DESCRIPTION "libjpeg-turbo is a JPEG image codec that uses SIMD instructions (MMX, SSE2, AVX2, Neon, AltiVec) to accelerate baseline JPEG compression and decompression on x86, x86-64, Arm, and PowerPC systems, as well as progressive JPEG compression on x86 and x86-64 systems." URL "https://www.libjpeg-turbo.org" TYPE OPTIONAL PURPOSE "Required by the Krita JPEG and TIFF filters") macro_bool_to_01(libjpeg-turbo_FOUND HAVE_JPEG_TURBO) configure_file(config-jpeg.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-jpeg.h ) if(libjpeg-turbo_FOUND) set(JPEG_TURBO_LIBRARIES libjpeg-turbo::turbojpeg) endif() find_package(GIF) set_package_properties(GIF PROPERTIES DESCRIPTION "Library for loading and saving gif files." URL "http://giflib.sourceforge.net/" TYPE OPTIONAL PURPOSE "Required by the Krita GIF filter") find_package(HEIF "1.11.0") set_package_properties(HEIF PROPERTIES DESCRIPTION "Library for loading and saving heif files." URL "https://github.com/strukturag/libheif" TYPE OPTIONAL PURPOSE "Required by the Krita HEIF filter") find_package(OpenJPEG "2.3.0") set_package_properties(OpenJPEG PROPERTIES DESCRIPTION "Library for loading and saving jp2000 files." URL "https://www.openjpeg.org/" TYPE OPTIONAL PURPOSE "Required by the Krita JP2000 filter") find_package(JPEGXL 0.7.0) set_package_properties(JPEGXL PROPERTIES DESCRIPTION "JPEG XL is a royalty-free raster-graphics file format that supports both lossy and lossless compression and is experimentally supported by Chrome, Firefox, and Edge." URL "https://github.com/libjxl/libjxl" TYPE OPTIONAL PURPOSE "Required by the Krita JPEG-XL filter") find_package(FFTW3) set_package_properties(FFTW3 PROPERTIES DESCRIPTION "A fast, free C FFT library" URL "http://www.fftw.org/" TYPE OPTIONAL PURPOSE "Required by the Krita for fast convolution operators and some G'Mic features") macro_bool_to_01(FFTW3_FOUND HAVE_FFTW3) if (FFTW3_FOUND) # GMic uses the Threads library if available. find_library(FFTW3_THREADS_LIB fftw3_threads PATHS ${FFTW3_LIBRARY_DIRS}) endif() find_package(OpenColorIO 2.0.0) set_package_properties(OpenColorIO PROPERTIES DESCRIPTION "The OpenColorIO Library" URL "https://www.opencolorio.org" TYPE OPTIONAL PURPOSE "Required by the Krita LUT docker") macro_bool_to_01(OpenColorIO_FOUND HAVE_OCIO) configure_file(config-ocio.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-ocio.h) set_package_properties(PythonLibrary PROPERTIES DESCRIPTION "Python Library" URL "https://www.python.org" TYPE OPTIONAL PURPOSE "Required by the Krita PyQt plugin") macro_bool_to_01(Python_Development_FOUND HAVE_PYTHONLIBS) find_package(SIP "4.19.13") set_package_properties(SIP PROPERTIES DESCRIPTION "Support for generating SIP Python bindings" URL "https://github.com/Python-SIP/sip" TYPE OPTIONAL PURPOSE "Required by the Krita PyQt plugin") macro_bool_to_01(SIP_FOUND HAVE_SIP) if (QT_MAJOR_VERSION STREQUAL "5") find_package(PyQt5 "5.6.0") set_package_properties(PyQt5 PROPERTIES DESCRIPTION "Python bindings for Qt5." URL "https://www.riverbankcomputing.com/software/pyqt/download" TYPE OPTIONAL PURPOSE "Required by the Krita PyQt plugin") macro_bool_to_01(PYQT5_FOUND HAVE_PYQT5) set(PYQT_VERSION_TAG ${PYQT5_VERSION_TAG}) set(PYQT_SIP_NAME ${PYQT5_SIP_NAME}) set(PYQT_SIP_TAGS ${PYQT5_SIP_TAGS}) set(PYQT_SIP_DIR ${PYQT5_SIP_DIR}) elseif (QT_MAJOR_VERSION STREQUAL "6") find_package(PyQt6 "6.7.0") set_package_properties(PyQt6 PROPERTIES DESCRIPTION "Python bindings for Qt6." URL "https://www.riverbankcomputing.com/software/pyqt/download" TYPE OPTIONAL PURPOSE "Required by the Krita PyQt plugin") macro_bool_to_01(PYQT6_FOUND HAVE_PYQT6) set(PYQT_VERSION_TAG ${PYQT6_VERSION_TAG}) set(PYQT_SIP_NAME ${PYQT6_SIP_NAME}) set(PYQT_SIP_TAGS ${PYQT6_SIP_TAGS}) set(PYQT_SIP_DIR ${PYQT6_SIP_DIR}) endif() find_package(Mlt7) set_package_properties(Mlt7 PROPERTIES DESCRIPTION "Media Lovin' Toolkit (Multimedia Framework)" URL "https://mltframework.org/" PURPOSE "Required to do audio/video synchronization and processing. No MLT = No Audio! ") if (Mlt7_FOUND) find_package(SDL2 REQUIRED) set_package_properties(SDL2 PROPERTIES DESCRIPTION "Simple DirectMedia Layer 2" URL "https://www.libsdl.org/" PURPOSE "Required for MLT to render audio buffers. Required **only** when MLT is found on the system." ) endif() macro_bool_to_01(Mlt7_FOUND HAVE_MLT) configure_file(config-mlt.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-mlt.h) find_package(LibMyPaint 1.4.0) set_package_properties(LibMyPaint PROPERTIES DESCRIPTION "MyPaint brush engine API for C/C++" TYPE OPTIONAL PURPOSE "Required for the MyPaint brush engine") macro_bool_to_01(LibMyPaint_FOUND HAVE_LIBMYPAINT) configure_file(config-mypaint.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-mypaint.h ) ## ## Look for OpenGL ## # TODO: see if there is a better check for QtGui being built with opengl support (and thus the QOpenGL* classes) if (QT_MAJOR_VERSION STREQUAL "5") if(Qt5Gui_OPENGL_IMPLEMENTATION) message(STATUS "Found QtGui OpenGL support") else() message(FATAL_ERROR "Did NOT find QtGui OpenGL support. Check your Qt configuration. You cannot build Krita without Qt OpenGL support.") endif() endif() ## ## Test for eigen3 ## find_package(Eigen3 5 NO_MODULE) if(NOT Eigen3_FOUND) find_package(Eigen3 3.3 REQUIRED NO_MODULE) endif() set_package_properties(Eigen3 PROPERTIES DESCRIPTION "C++ template library for linear algebra" URL "http://eigen.tuxfamily.org" TYPE REQUIRED) ## ## Test for exiv2 ## find_package(LibExiv2 0.16 REQUIRED) ## ## Test for lcms ## find_package(LCMS2 2.4 REQUIRED) set_package_properties(LCMS2 PROPERTIES DESCRIPTION "LittleCMS Color management engine" URL "http://www.littlecms.com" TYPE REQUIRED PURPOSE "Will be used for color management and is necessary for Krita") if(LCMS2_FOUND) if(NOT ${LCMS2_VERSION} VERSION_LESS 2.4 ) set(HAVE_LCMS24 TRUE) endif() set(HAVE_REQUIRED_LCMS_VERSION TRUE) set(HAVE_LCMS2 TRUE) include(CheckIncludeFileCXX) set(CMAKE_REQUIRED_INCLUDES ${LCMS2_INCLUDE_DIRS}) set(CMAKE_REQUIRED_LIBRARIES ${LCMS2_LIBRARIES}) if(LCMS2_FAST_FLOAT_INCLUDE_DIR) message(STATUS "Found LittleCMS's fast float plugin") set(HAVE_LCMS_FAST_FLOAT_PLUGIN 1) endif() endif() ## ## Test for xsimd ## ## xsimd has `SameMajorVersion` compatibility option set ## in `write_basic_package_version_file`, so we cannot just ## write a version range in the find_package call. Instead we ## should try all the supported versions manually ## ## We're trying out more recent versions first to make ## set_package_properties report the lowest one if no ## xsimd is found ## foreach(xsimd_version 14 13 12 11 10 9 8.1.0) if(NOT xsimd_FOUND) find_package(xsimd ${xsimd_version}) endif() endforeach() set_package_properties(xsimd PROPERTIES DESCRIPTION "C++ wrappers for SIMD intrinsics" URL "https://github.com/xtensor-stack/xsimd" TYPE REQUIRED PURPOSE "Required by Krita for vectorization") if (xsimd_FOUND) macro(ko_compile_for_all_implementations_no_scalar _objs _src) if("aarch64" IN_LIST XSIMD_ARCH) xsimd_compile_for_all_implementations(${_objs} ${_src} FLAGS ${xsimd_ARCHITECTURE_FLAGS} ONLY NEON64) endif() if ("arm" IN_LIST XSIMD_ARCH) xsimd_compile_for_all_implementations(${_objs} ${_src} FLAGS ${xsimd_ARCHITECTURE_FLAGS} ONLY NEON) endif() if ("x86" IN_LIST XSIMD_ARCH OR "x86-64" IN_LIST XSIMD_ARCH) xsimd_compile_for_all_implementations(${_objs} ${_src} FLAGS ${xsimd_ARCHITECTURE_FLAGS} ONLY SSE2 SSSE3 SSE4_1 AVX AVX2+FMA) endif() endmacro() macro(ko_compile_for_all_implementations _objs _src) xsimd_compile_for_all_implementations(${_objs} ${_src} FLAGS ${xsimd_ARCHITECTURE_FLAGS} ONLY Scalar) ko_compile_for_all_implementations_no_scalar(${_objs} ${_src}) endmacro() else() # Make noop functions as they are used in nested cmake files # without guards macro(ko_compile_for_all_implementations_no_scalar _objs _src) endmacro() macro(ko_compile_for_all_implementations _objs _src) endmacro() endif() ## ## Test endianness ## include (TestBigEndian) test_big_endian(CMAKE_WORDS_BIGENDIAN) ## ## Test for qt-poppler ## find_package(Poppler COMPONENTS Qt${QT_MAJOR_VERSION}) set_package_properties(Poppler PROPERTIES DESCRIPTION "A PDF rendering library" URL "https://poppler.freedesktop.org/" TYPE OPTIONAL PURPOSE "Required by the Krita PDF filter.") ## ## Test for libav on Android ## if(ANDROID) find_package(PkgConfig REQUIRED) set_package_properties(PkgConfig PROPERTIES DESCRIPTION "pkg-config" URL "https://www.freedesktop.org/wiki/Software/pkg-config/" TYPE REQUIRED PURPOSE "Needed to find ffmpeg libraries on Android." ) pkg_check_modules(LibAV REQUIRED IMPORTED_TARGET GLOBAL libavcodec libavfilter libavformat libavutil libswscale ) if(TARGET PkgConfig::LibAV) add_library(LibAV ALIAS PkgConfig::LibAV) endif() # The PkgConfig and FeatureSummary modules don't play nice with each other # on their own, so this has to be set manually for the summary to show up. if(TARGET LibAV) set_property(GLOBAL APPEND PROPERTY PACKAGES_FOUND LibAV) else() set_property(GLOBAL APPEND PROPERTY PACKAGES_NOT_FOUND LibAV) endif() set_package_properties(LibAV PROPERTIES DESCRIPTION "FFmpeg libraries" URL "https://ffmpeg.org/" TYPE REQUIRED PURPOSE "Needed to render animations and timelapses on Android." ) endif() ## ## Test for quazip ## find_package(QUAZIP 0.6) set_package_properties(QUAZIP PROPERTIES DESCRIPTION "A library for reading and writing zip files" URL "https://stachenov.github.io/quazip/" TYPE REQUIRED PURPOSE "Needed for reading and writing KRA and ORA files" ) ## ## Test for KDcraw ## if (QT_MAJOR_VERSION STREQUAL "6") find_package(KDcrawQt6 5.0.0) set_package_properties(KDcrawQt6 PROPERTIES DESCRIPTION "A thread-safe wrapper around libraw" URL "https://invent.kde.org/graphics/libkdcraw" TYPE OPTIONAL PURPOSE "Needed for reading RAW files" ) else() find_package(KF5KDcraw 5.0.0) set_package_properties(KF5KDcraw PROPERTIES DESCRIPTION "A thread-safe wrapper around libraw" URL "https://invent.kde.org/graphics/libkdcraw" TYPE OPTIONAL PURPOSE "Needed for reading RAW files" ) endif() ## ## Check for freetype ## find_package(Freetype 2.11.0 REQUIRED) set_package_properties(Freetype PROPERTIES DESCRIPTION "A library for rendering glyphs" URL "https://download.savannah.gnu.org/releases/freetype" TYPE REQUIRED PURPOSE "Needed for rendering text vector shapes." ) ## ## Check for HarfBuzz ## if (QT_MAJOR_VERSION STREQUAL "6") find_package(HarfBuzz 2.7.4 REQUIRED) else() find_package(HarfBuzz 4.0 REQUIRED) endif() set_package_properties(HarfBuzz PROPERTIES DESCRIPTION "OpenType text shaping engine" URL "https://harfbuzz.github.io" TYPE REQUIRED PURPOSE "Needed for rendering text vector shapes." ) if (HarfBuzz_FOUND) list(APPEND ANDROID_EXTRA_LIBS ${HarfBuzz_LIBRARIES}) endif() # Note: We now build a patched raqm from source with Krita. ## ## Check for fontconfig ## find_package(Fontconfig 2.13.1 REQUIRED) set_package_properties(Fontconfig PROPERTIES TYPE REQUIRED PURPOSE "Needed for getting font file information." ) ## ## Check for libunibreak ## find_package(libunibreak 5.0 REQUIRED) set_package_properties(libunibreak PROPERTIES DESCRIPTION "Implementation of the line breaking and word breaking algorithms as described in Unicode Standard Annex 14 and Unicode Standard Annex 29" URL "https://github.com/adah1972/libunibreak" TYPE REQUIRED PURPOSE "Needed for rendering text vector shapes." ) ## ## Build vendored libraries ## # Allow specification of a directory with pre-downloaded # requirements. This download directory is used for 3rdparty_vendor # download if(DEFINED ENV{EXTERNALS_DOWNLOAD_DIR}) set(EXTERNALS_DOWNLOAD_DIR $ENV{EXTERNALS_DOWNLOAD_DIR}) endif() if(NOT IS_DIRECTORY ${EXTERNALS_DOWNLOAD_DIR}) message(WARNING "No externals download dir set, default location inside build tree is used. Use -DEXTERNALS_DOWNLOAD_DIR to override") else() file(TO_CMAKE_PATH "${EXTERNALS_DOWNLOAD_DIR}" EXTERNALS_DOWNLOAD_DIR) endif() add_subdirectory(3rdparty_vendor) ## ## Test for Atomics ## include(CheckAtomic) ############################ ############################# ## Add Krita helper macros ## ############################# ############################ include(KritaAddBrokenUnitTest) include(MacroKritaAddBenchmark) #################### ##################### ## Define includes ## ##################### #################### # for config.h and includes (if any?) include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR} ) add_subdirectory(sdk/tests) add_subdirectory(libs) add_subdirectory(qmlmodules) add_subdirectory(plugins) if (BUILD_TESTING) add_subdirectory(benchmarks) endif() add_subdirectory(krita) configure_file(KoConfig.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/KoConfig.h ) configure_file(KoTestConfig.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/KoTestConfig.h ) configure_file(config_convolution.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config_convolution.h) check_function_exists(powf HAVE_POWF) configure_file(config-powf.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-powf.h) if(WIN32) include(${CMAKE_CURRENT_LIST_DIR}/packaging/windows/installer/ConfigureInstallerNsis.cmake) include(${CMAKE_CURRENT_LIST_DIR}/packaging/windows/msix/ConfigureMsixFiles.cmake) endif() message("\nBroken tests:") foreach(tst ${KRITA_BROKEN_TESTS}) message(" * ${tst}") endforeach() if(APPLE) # fix macos test rpath macos_test_fixrpath(${KRITA_TESTS_TARGET}) endif() feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) if (ANDROID) # ECM passes this to Qt, which was already capable of detecting it.. set (ANDROID_SDK_COMPILE_API "36") # To assist stdcpp-path in deployment.json file set(ANDROID_SYSROOT_PREFIX "${ANDROID_TOOLCHAIN_ROOT}/sysroot/usr" CACHE STRING "" FORCE) # copied regex from ECM's toolchain string(REGEX REPLACE "-(clang)?([0-9].[0-9])?$" "" ECM_ANDROID_STL_ARCH ${ANDROID_TOOLCHAIN_NAME}) if (NOT (CMAKE_CXX_STANDARD_LIBRARIES MATCHES "[^ ]*c\\+\\+[^ ]*\\.so")) set (KRITA_ANDROID_STL_PATH "${ANDROID_TOOLCHAIN_ROOT}/sysroot/usr/lib/${ECM_ANDROID_STL_ARCH}/lib${ANDROID_STL}.so") if (NOT EXISTS ${KRITA_ANDROID_STL_PATH}) message(FATAL_ERROR "STL does not exist at the right location, please use NDK r20+") endif() set (CMAKE_CXX_STANDARD_LIBRARIES "${CMAKE_CXX_STANDARD_LIBRARIES} \"${KRITA_ANDROID_STL_PATH}\"" CACHE STRING "" FORCE) endif() endif() if(DEFINED QTANDROID_EXPORTED_TARGET AND NOT TARGET "create-apk") set (_CMAKE_ANDROID_DIR "${ECM_DIR}/../toolchain") list(LENGTH QTANDROID_EXPORTED_TARGET targetsCount) include(${_CMAKE_ANDROID_DIR}/ECMAndroidDeployQt.cmake) math(EXPR last "${targetsCount}-1") foreach(idx RANGE 0 ${last}) list(GET QTANDROID_EXPORTED_TARGET ${idx} exportedTarget) list(GET ANDROID_APK_DIR ${idx} APK_DIR) if(APK_DIR AND NOT EXISTS "${ANDROID_APK_DIR}/AndroidManifest.xml" AND IS_ABSOLUTE ANDROID_APK_DIR) message(FATAL_ERROR "Cannot find ${APK_DIR}/AndroidManifest.xml according to ANDROID_APK_DIR. ${ANDROID_APK_DIR} ${exportedTarget}") elseif(NOT APK_DIR) get_filename_component(_qt5Core_install_prefix "${Qt5Core_DIR}/../../../" ABSOLUTE) set(APK_DIR "${_qt5Core_install_prefix}/src/android/templates/") endif() ecm_androiddeployqt("${exportedTarget}" "${ECM_ADDITIONAL_FIND_ROOT_PATH}") set_target_properties(create-apk-${exportedTarget} PROPERTIES ANDROID_APK_DIR "${APK_DIR}") endforeach() elseif(ANDROID) message(STATUS "You can export a target by specifying -DQTANDROID_EXPORTED_TARGET= and -DANDROID_APK_DIR=") endif() ki18n_install(po)