qt5base-lts/cmake/QtBaseGlobalTargets.cmake
Alexandru Croitor 26059d1b9b CMake: Allow building bundled 3rd party libraries in qtbase
A few things are needed to accomplish that:

- the python scripts do not ignore certain system_foo features anymore
  (it is a hardcoded list for now just to be safe)

- configurejson2cmake now outputs
  qt_find_package(WrapSystemFoo) calls for bundled libraries
  (see below)

- the harfbuzz .pro file is modified to accommodate pro2cmake
  not being able to correctly parse some conditional scopes

- the freetype .pro file is modified to make sure linking of the
  library succeeds without duplicate symbol errors, which qmake
  doesn't encounter due to magical exclusion of cpp files that are
  included in other cpp files (presumably for include moc_foo.cpp
  support)

- feature evaluation for Core, Gui, Network now happens in the
  qtbase/src directory, so that bundled libraries can be conditionally
  built

- for each bundled library there are now two FindWrap scripts:
  - FindWrapSystemFoo which finds an installed library in the system
  - FindWrapFoo which either uses the system installed library or
    the built bundled one depending on a condition

- projects that intend to use bundled libraries need to link against
  WrapFoo::WrapFoo instead of WrapSystemFoo::WrapSystemFoo targets
  (this is handled by pro2cmake).
  Unfortunately manually added qt_find_package(WrapFoo) calls might
  still be needed as is the case for WrapFreetype and others.

- a new cmake/QtFindWrapHelper.cmake file is added that provides
  a macro to simplify creation of WrapFoo targets that link against
  a bundled or system library. The implementation is fairly ugly
  due to CMake macro constraints, but it was deemed better than
  copy-pasting a bunch of almost identical code across all
  FindWrapFoo.cmake files.

- a qtzlib header-only module is now created when using bundled
  zlib, to provide public syncqt created headers for consumers
  that need them. These are projects that have
  'QT_PRIVATE += zlib-private' in their .pro files
  (e.g. qtimageformats, qtlocation, qt3d, etc.)
  This is unfortunately needed due to QtNetwork using zlib
  types in its private C++ API.

The change includes support for building the following bundled
libraries:
- zlib
- libpng
- libjpeg
- Freetype
- Harfbuzz-ng
- PCRE2

The following 3rd party libraries are still using an old
implementation within the CMake build system, and should be migrated
to the new one in the near future:
- double-conversion
- Old harfbuzz

The are a few libraries that are not yet ported:
- system-sqlite
- systemxcb
- maybe others

Among other things, this change allows building qtbase on Windows
without requiring vcpkg.

Task-number: QTBUG-82167
Change-Id: I35ecea0d832f66c1943c82e618de4a51440971a5
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Reviewed-by: Leander Beernaert <leander.beernaert@qt.io>
2020-02-25 15:43:16 +01:00

291 lines
13 KiB
CMake

## QtPlatform Target:
add_library(Platform INTERFACE)
add_library(Qt::Platform ALIAS Platform)
target_include_directories(Platform
INTERFACE
$<BUILD_INTERFACE:${QT_PLATFORM_DEFINITION_DIR_ABSOLUTE}>
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/${INSTALL_INCLUDEDIR}>
$<INSTALL_INTERFACE:${QT_PLATFORM_DEFINITION_DIR}>
$<INSTALL_INTERFACE:${INSTALL_INCLUDEDIR}>
)
target_compile_definitions(Platform INTERFACE ${QT_PLATFORM_DEFINITIONS})
# When building on android we need to link against the logging library
# in order to satisfy linker dependencies. Both of these libraries are part of
# the NDK.
if (ANDROID)
target_link_libraries(Platform INTERFACE log)
endif()
qt_enable_msvc_cplusplus_define(Platform INTERFACE)
set(__GlobalConfig_path_suffix "${INSTALL_CMAKE_NAMESPACE}")
qt_path_join(__GlobalConfig_build_dir ${QT_CONFIG_BUILD_DIR} ${__GlobalConfig_path_suffix})
qt_path_join(__GlobalConfig_install_dir ${QT_CONFIG_INSTALL_DIR} ${__GlobalConfig_path_suffix})
set(__GlobalConfig_install_dir_absolute "${__GlobalConfig_install_dir}")
if(QT_WILL_INSTALL)
# Need to prepend the install prefix when doing prefix builds, because the config install dir
# is relative then.
qt_path_join(__GlobalConfig_install_dir_absolute
${CMAKE_INSTALL_PREFIX} ${__GlobalConfig_install_dir_absolute})
endif()
# Generate and install Qt6 config file.
configure_package_config_file(
"${PROJECT_SOURCE_DIR}/cmake/QtConfig.cmake.in"
"${__GlobalConfig_build_dir}/${INSTALL_CMAKE_NAMESPACE}Config.cmake"
INSTALL_DESTINATION "${__GlobalConfig_install_dir}"
)
write_basic_package_version_file(
${__GlobalConfig_build_dir}/${INSTALL_CMAKE_NAMESPACE}ConfigVersion.cmake
VERSION ${PROJECT_VERSION}
COMPATIBILITY AnyNewerVersion
)
# Generate and install Qt6Tools config file.
configure_package_config_file(
"${PROJECT_SOURCE_DIR}/cmake/QtToolsConfig.cmake.in"
"${__GlobalConfig_build_dir}/${INSTALL_CMAKE_NAMESPACE}ToolsConfig.cmake"
INSTALL_DESTINATION "${__GlobalConfig_install_dir}"
)
write_basic_package_version_file(
${__GlobalConfig_build_dir}/${INSTALL_CMAKE_NAMESPACE}ToolsConfigVersion.cmake
VERSION ${PROJECT_VERSION}
COMPATIBILITY AnyNewerVersion
)
qt_install(FILES
"${__GlobalConfig_build_dir}/${INSTALL_CMAKE_NAMESPACE}Config.cmake"
"${__GlobalConfig_build_dir}/${INSTALL_CMAKE_NAMESPACE}ConfigVersion.cmake"
DESTINATION "${__GlobalConfig_install_dir}"
COMPONENT Devel
)
qt_install(FILES
"${__GlobalConfig_build_dir}/${INSTALL_CMAKE_NAMESPACE}ToolsConfig.cmake"
"${__GlobalConfig_build_dir}/${INSTALL_CMAKE_NAMESPACE}ToolsConfigVersion.cmake"
DESTINATION "${__GlobalConfig_install_dir}Tools"
COMPONENT Devel
)
# Generate toolchain file for convenience
if(QT_HOST_PATH)
get_filename_component(init_qt_host_path "${QT_HOST_PATH}" ABSOLUTE)
set(init_qt_host_path "set(QT_HOST_PATH \"${init_qt_host_path}\" CACHE PATH \"\" FORCE)")
endif()
if(CMAKE_TOOLCHAIN_FILE)
set(init_original_toolchain_file "set(qt_chainload_toolchain_file \"${CMAKE_TOOLCHAIN_FILE}\")")
endif()
if(VCPKG_CHAINLOAD_TOOLCHAIN_FILE)
list(APPEND init_vcpkg "set(VCPKG_CHAINLOAD_TOOLCHAIN_FILE \"${VCPKG_CHAINLOAD_TOOLCHAIN_FILE}\")")
endif()
if(VCPKG_TARGET_TRIPLET)
list(APPEND init_vcpkg "set(VCPKG_TARGET_TRIPLET \"${VCPKG_TARGET_TRIPLET}\" CACHE STRING \"\")")
endif()
# On Windows compilers aren't easily mixed. Avoid that qtbase is built using cl.exe for example and then for another
# build gcc is picked up from %PATH%. The same goes when using a custom compiler on other platforms, such as ICC.
list(APPEND init_platform "set(CMAKE_CXX_COMPILER \"${CMAKE_CXX_COMPILER}\" CACHE STRING \"\")")
list(APPEND init_platform "set(CMAKE_C_COMPILER \"${CMAKE_C_COMPILER}\" CACHE STRING \"\")")
if(APPLE)
# For simulator_and_device build, we should not explicitly set the sysroot.
list(LENGTH CMAKE_OSX_ARCHITECTURES _qt_osx_architectures_count)
if(CMAKE_OSX_SYSROOT AND NOT _qt_osx_architectures_count GREATER 1 AND APPLE_UIKIT)
list(APPEND init_platform "set(CMAKE_OSX_SYSROOT \"${CMAKE_OSX_SYSROOT}\" CACHE PATH \"\")")
endif()
unset(_qt_osx_architectures_count)
if(CMAKE_OSX_DEPLOYMENT_TARGET)
list(APPEND init_platform
"set(CMAKE_OSX_DEPLOYMENT_TARGET \"${CMAKE_OSX_DEPLOYMENT_TARGET}\" CACHE STRING \"\")")
endif()
if(APPLE_UIKIT)
list(APPEND init_platform
"set(CMAKE_SYSTEM_NAME \"${CMAKE_SYSTEM_NAME}\" CACHE STRING \"\")")
set(_qt_osx_architectures_escaped "${CMAKE_OSX_ARCHITECTURES}")
string(REPLACE ";" "LITERAL_SEMICOLON"
_qt_osx_architectures_escaped "${_qt_osx_architectures_escaped}")
list(APPEND init_platform
"set(CMAKE_OSX_ARCHITECTURES \"${_qt_osx_architectures_escaped}\" CACHE STRING \"\")")
unset(_qt_osx_architectures_escaped)
endif()
elseif(ANDROID)
list(APPEND init_platform "set(ANDROID_NATIVE_API_LEVEL \"${ANDROID_NATIVE_API_LEVEL}\" CACHE STRING \"\")")
list(APPEND init_platform "set(ANDROID_STL \"${ANDROID_STL}\" CACHE STRING \"\")")
list(APPEND init_platform "set(ANDROID_ABI \"${ANDROID_ABI}\" CACHE STRING \"\")")
list(APPEND init_platform "if (NOT DEFINED ANDROID_SDK_ROOT)")
list(APPEND init_platform " set(ANDROID_SDK_ROOT \"${ANDROID_SDK_ROOT}\" CACHE STRING \"\")")
list(APPEND init_platform "endif()")
endif()
string(REPLACE ";" "\n" init_vcpkg "${init_vcpkg}")
string(REPLACE ";" "\n" init_platform "${init_platform}")
string(REPLACE "LITERAL_SEMICOLON" ";" init_platform "${init_platform}")
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/qt.toolchain.cmake.in" "${__GlobalConfig_build_dir}/qt.toolchain.cmake" @ONLY)
qt_install(FILES "${__GlobalConfig_build_dir}/qt.toolchain.cmake" DESTINATION "${__GlobalConfig_install_dir}" COMPONENT Devel)
# Also provide a convenience cmake wrapper
if(UNIX)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/bin/qt-cmake.in" "${QT_BUILD_DIR}/${INSTALL_BINDIR}/qt-cmake" @ONLY)
qt_install(PROGRAMS "${QT_BUILD_DIR}/${INSTALL_BINDIR}/qt-cmake" DESTINATION "${INSTALL_BINDIR}")
else()
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/bin/qt-cmake.bat.in" "${QT_BUILD_DIR}/${INSTALL_BINDIR}/qt-cmake.bat" @ONLY)
qt_install(PROGRAMS "${QT_BUILD_DIR}/${INSTALL_BINDIR}/qt-cmake.bat" DESTINATION "${INSTALL_BINDIR}")
endif()
# Provide a private convenience wrapper with options which should not be propagated via the public
# qt-cmake wrapper e.g. CMAKE_GENERATOR.
# These options can not be set in a toolchain file, but only on the command line.
# These options should not be in the public wrapper, because a consumer of Qt might want to build
# their CMake app with the Unix Makefiles generator, while Qt should be built with the Ninja
# generator.
# The private wrapper is more conveient for building Qt itself, because a developer doesn't need
# to specify the same options for each qt module built.
set(__qt_cmake_extra "-G\"${CMAKE_GENERATOR}\"")
if(UNIX)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/bin/qt-cmake.in"
"${QT_BUILD_DIR}/${INSTALL_BINDIR}/qt-cmake-private" @ONLY)
qt_install(PROGRAMS "${QT_BUILD_DIR}/${INSTALL_BINDIR}/qt-cmake-private" DESTINATION "${INSTALL_BINDIR}")
else()
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/bin/qt-cmake.bat.in"
"${QT_BUILD_DIR}/${INSTALL_BINDIR}/qt-cmake-private.bat" @ONLY)
qt_install(PROGRAMS "${QT_BUILD_DIR}/${INSTALL_BINDIR}/qt-cmake-private.bat" DESTINATION "${INSTALL_BINDIR}")
endif()
unset(__qt_cmake_extra)
## Library to hold global features:
## These features are stored and accessed via Qt::GlobalConfig, but the
## files always lived in Qt::Core, so we keep it that way
add_library(GlobalConfig INTERFACE)
target_include_directories(GlobalConfig INTERFACE
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/QtCore>
$<INSTALL_INTERFACE:include>
$<INSTALL_INTERFACE:include/QtCore>
)
qt_feature_module_begin(NO_MODULE
PUBLIC_FILE src/corelib/global/qconfig.h
PRIVATE_FILE src/corelib/global/qconfig_p.h
)
include("${CMAKE_CURRENT_SOURCE_DIR}/configure.cmake")
# Do what mkspecs/features/uikit/default_pre.prf does, aka enable sse2 for
# simulator_and_device_builds.
if(APPLE_UIKIT AND NOT QT_UIKIT_SDK)
set(__QtFeature_custom_enabled_cache_variables
TEST_subarch_sse2
FEATURE_sse2
QT_FEATURE_sse2)
endif()
qt_feature_module_end(GlobalConfig OUT_VAR_PREFIX "__GlobalConfig_")
qt_generate_global_config_pri_file()
add_library(Qt::GlobalConfig ALIAS GlobalConfig)
add_library(GlobalConfigPrivate INTERFACE)
target_link_libraries(GlobalConfigPrivate INTERFACE GlobalConfig)
target_include_directories(GlobalConfigPrivate INTERFACE
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/QtCore/${PROJECT_VERSION}>
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include/QtCore/${PROJECT_VERSION}/QtCore>
$<INSTALL_INTERFACE:include/QtCore/${PROJECT_VERSION}>
$<INSTALL_INTERFACE:include/QtCore/${PROJECT_VERSION}/QtCore>
)
add_library(Qt::GlobalConfigPrivate ALIAS GlobalConfigPrivate)
# defines PlatformCommonInternal PlatformModuleInternal PlatformPluginInternal PlatformToolInternal
include(QtInternalTargets)
set(__export_targets Platform
GlobalConfig
GlobalConfigPrivate
PlatformCommonInternal
PlatformModuleInternal
PlatformPluginInternal
PlatformToolInternal)
set(__export_name "${INSTALL_CMAKE_NAMESPACE}Targets")
qt_install(TARGETS ${__export_targets} EXPORT "${__export_name}")
qt_install(EXPORT ${__export_name}
NAMESPACE ${QT_CMAKE_EXPORT_NAMESPACE}::
DESTINATION "${__GlobalConfig_install_dir}")
qt_internal_export_modern_cmake_config_targets_file(TARGETS ${__export_targets}
EXPORT_NAME_PREFIX ${INSTALL_CMAKE_NAMESPACE}
CONFIG_INSTALL_DIR
${__GlobalConfig_install_dir})
## Install some QtBase specific CMake files:
qt_copy_or_install(FILES
cmake/ModuleDescription.json.in
cmake/QtBuild.cmake
cmake/QtBuildInformation.cmake
cmake/QtCompilerFlags.cmake
cmake/QtCompilerOptimization.cmake
cmake/QtFeature.cmake
cmake/QtFindWrapHelper.cmake
cmake/QtPlatformSupport.cmake
cmake/QtPlatformAndroid.cmake
cmake/QtPostProcess.cmake
cmake/QtSetup.cmake
cmake/QtModuleConfig.cmake.in
cmake/QtModuleDependencies.cmake.in
cmake/QtModuleToolsDependencies.cmake.in
cmake/QtModuleToolsConfig.cmake.in
cmake/QtModuleToolsVersionlessTargets.cmake.in
cmake/QtStandaloneTestsConfig.cmake.in
cmake/QtPlugins.cmake.in
cmake/QtPluginConfig.cmake.in
cmake/QtPluginDependencies.cmake.in
DESTINATION "${__GlobalConfig_install_dir}"
)
file(COPY cmake/QtFeature.cmake DESTINATION "${__GlobalConfig_build_dir}")
# TODO: Check whether this is the right place to install these
qt_copy_or_install(DIRECTORY cmake/3rdparty DESTINATION "${__GlobalConfig_install_dir}")
# Install our custom Find modules, which will be used by the find_dependency() calls
# inside the generated ModuleDependencies cmake files.
qt_copy_or_install(DIRECTORY cmake/
DESTINATION "${__GlobalConfig_install_dir}"
FILES_MATCHING PATTERN "Find*.cmake"
PATTERN "tests" EXCLUDE
PATTERN "3rdparty" EXCLUDE
)
# Configure and install the QtBuildInternals package.
set(__build_internals_path_suffix "${INSTALL_CMAKE_NAMESPACE}BuildInternals")
qt_path_join(__build_internals_build_dir ${QT_CONFIG_BUILD_DIR} ${__build_internals_path_suffix})
qt_path_join(__build_internals_install_dir ${QT_CONFIG_INSTALL_DIR}
${__build_internals_path_suffix})
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake"
"${__build_internals_build_dir}/${INSTALL_CMAKE_NAMESPACE}BuildInternalsConfig.cmake"
@ONLY
)
qt_install(FILES
"${__build_internals_build_dir}/${INSTALL_CMAKE_NAMESPACE}BuildInternalsConfig.cmake"
"${__build_internals_build_dir}/QtBuildInternalsExtra.cmake"
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/QtBuildInternals/QtBuildInternalsAndroid.cmake"
DESTINATION "${__build_internals_install_dir}"
COMPONENT Devel
)
# Generate the new resource API
set(QT_CORE_RESOURCE_GENERATED_FILE_NAME "${INSTALL_CMAKE_NAMESPACE}CoreResource.cmake" CACHE INTERNAL "")
set(QT_CORE_RESOURCE_GENERATED_FILE_PATH "${CMAKE_CURRENT_BINARY_DIR}/${QT_CORE_RESOURCE_GENERATED_FILE_NAME}" CACHE INTERNAL "")
configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/cmake/QtResource.cmake.in"
"${QT_CORE_RESOURCE_GENERATED_FILE_PATH}"
@ONLY
)
include(${QT_CORE_RESOURCE_GENERATED_FILE_PATH})