Skip to content

Commit

Permalink
Add support for qt_helper_lib()
Browse files Browse the repository at this point in the history
Add qt_add_3rdparty_library() function as a replacement for qmake's
qt_helper_lib feature.

All 3rdparty libraries will be available under the Qt:: alias when built
through this method so that they can properly register as dependencies
of a Qt module.

This patch also adds Qt3rdPartyLibraryConfig.cmake.in to export the
CMake configuration for static builds and shared libraries.

Change-Id: I52bf3a95ca22fccd9ab54343468847bb1b570c28
Fixes: QTBUG-81969
Reviewed-by: Liang Qi <[email protected]>
Reviewed-by: Alexandru Croitor <[email protected]>
  • Loading branch information
Leander Beernaert authored and alcroito committed Feb 12, 2020
1 parent a2eb09a commit 572c03e
Show file tree
Hide file tree
Showing 3 changed files with 201 additions and 0 deletions.
26 changes: 26 additions & 0 deletions cmake/Qt3rdPartyLibraryConfig.cmake.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
@PACKAGE_INIT@

include(CMakeFindDependencyMacro)

get_filename_component(_import_prefix "${CMAKE_CURRENT_LIST_FILE}" PATH)
get_filename_component(_import_prefix "${_import_prefix}" REALPATH)

# Extra cmake code begin
@extra_cmake_code@
# Extra cmake code end

# Find required dependencies, if any.
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@[email protected]")
include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@[email protected]")
endif()

if (NOT QT_NO_CREATE_TARGETS)
include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@[email protected]")
if(NOT QT_NO_CREATE_VERSIONLESS_TARGETS)
include("${CMAKE_CURRENT_LIST_DIR}/@INSTALL_CMAKE_NAMESPACE@@[email protected]")
endif()
endif()

foreach(extra_cmake_include @extra_cmake_includes@)
include("${CMAKE_CURRENT_LIST_DIR}/${extra_cmake_include}")
endforeach()
136 changes: 136 additions & 0 deletions cmake/QtBuild.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2936,6 +2936,142 @@ function(qt_add_cmake_library target)

endfunction()

#
# This function replaces qmake's qt_helper_lib feature. It is intended to
# compile 3rdparty libraries as part of the build.
#
function(qt_add_3rdparty_library target)
# Process arguments:
qt_parse_all_arguments(arg "qt_add_3rdparty_library"
"SHARED;MODULE;STATIC;INTERFACE;EXCEPTIONS"
"OUTPUT_DIRECTORY"
"${__default_private_args};${__default_public_args}"
${ARGN}
)

### Define Targets:
if(${arg_INTERFACE})
add_library("${target}" INTERFACE)
elseif(${arg_STATIC} OR (${arg_MODULE} AND NOT BUILD_SHARED_LIBS))
add_library("${target}" STATIC)
elseif(${arg_SHARED})
add_library("${target}" SHARED)
elseif(${arg_MODULE})
add_library("${target}" MODULE)
set_property(TARGET ${name} PROPERTY C_VISIBILITY_PRESET default)
set_property(TARGET ${name} PROPERTY CXX_VISIBILITY_PRESET default)

if(APPLE)
# CMake defaults to using .so extensions for loadable modules, aka plugins,
# but Qt plugins are actually suffixed with .dylib.
set_property(TARGET "${target}" PROPERTY SUFFIX ".dylib")
endif()
else()
add_library("${target}")
endif()

if (NOT arg_ARCHIVE_INSTALL_DIRECTORY AND arg_INSTALL_DIRECTORY)
set(arg_ARCHIVE_INSTALL_DIRECTORY "${arg_INSTALL_DIRECTORY}")
endif()

qt_internal_add_qt_repo_known_module(${target})
qt_internal_add_target_aliases(${target})

if (ANDROID)
qt_android_apply_arch_suffix("${target}")
endif()

qt_skip_warnings_are_errors_when_repo_unclean("${target}")

if(NOT arg_HEADER_MODULE)
set_target_properties(${target} PROPERTIES
LIBRARY_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_LIBDIR}"
RUNTIME_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_BINDIR}"
ARCHIVE_OUTPUT_DIRECTORY "${QT_BUILD_DIR}/${INSTALL_LIBDIR}"
VERSION ${PROJECT_VERSION}
SOVERSION ${PROJECT_VERSION_MAJOR}
QT_MODULE_IS_3RDPARTY_LIBRARY TRUE
)
qt_handle_multi_config_output_dirs("${target}")

set_target_properties(${target} PROPERTIES
OUTPUT_NAME "${INSTALL_CMAKE_NAMESPACE}${target}"
)
endif()

if(NOT arg_INTERFACE)
# This property is used for super builds with static libraries. We use
# it in QtPlugins.cmake.in to avoid "polluting" the dependency chain
# for the target in it's project directory.
# E.g: When we process find_package(Qt6 ... Gui) in QtDeclarative, the
# rules in QtPugins.cmake add all the known Gui plugins as interface
# dependencies. This in turn causes circular dependencies on every
# plugin which links against Gui. Plugin A -> GUI -> Plugin A ....
set_target_properties(${target} PROPERTIES QT_BUILD_PROJECT_NAME ${PROJECT_NAME})
endif()

if(NOT arg_EXCEPTIONS AND NOT arg_INTERFACE)
qt_internal_set_no_exceptions_flags("${target}")
endif()

qt_extend_target("${target}"
SOURCES ${arg_SOURCES}
INCLUDE_DIRECTORIES
${arg_INCLUDE_DIRECTORIES}
PUBLIC_INCLUDE_DIRECTORIES
${arg_PUBLIC_INCLUDE_DIRECTORIES}
PUBLIC_DEFINES
${arg_PUBLIC_DEFINES}
DEFINES
${arg_DEFINES}
PUBLIC_LIBRARIES ${arg_PUBLIC_LIBRARIES}
LIBRARIES ${arg_LIBRARIES}
COMPILE_OPTIONS ${arg_COMPILE_OPTIONS}
PUBLIC_COMPILE_OPTIONS ${arg_PUBLIC_COMPILE_OPTIONS}
LINK_OPTIONS ${arg_LINK_OPTIONS}
PUBLIC_LINK_OPTIONS ${arg_PUBLIC_LINK_OPTIONS}
MOC_OPTIONS ${arg_MOC_OPTIONS}
ENABLE_AUTOGEN_TOOLS ${arg_ENABLE_AUTOGEN_TOOLS}
DISABLE_AUTOGEN_TOOLS ${arg_DISABLE_AUTOGEN_TOOLS}
${install_arguments}
)

if(NOT BUILD_SHARED_LIBS OR arg_SHARED)
set(path_suffix "${INSTALL_CMAKE_NAMESPACE}${target}")
qt_path_join(config_build_dir ${QT_CONFIG_BUILD_DIR} ${path_suffix})
qt_path_join(config_install_dir ${QT_CONFIG_INSTALL_DIR} ${path_suffix})
set(export_name "${INSTALL_CMAKE_NAMESPACE}${target}Targets")

configure_package_config_file(
"${QT_CMAKE_DIR}/Qt3rdPartyLibraryConfig.cmake.in"
"${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${target}Config.cmake"
INSTALL_DESTINATION "${config_install_dir}"
)

write_basic_package_version_file(
"${config_build_dir}/${INSTALL_CMAKE_NAMESPACE}${target}ConfigVersion.cmake"
VERSION ${PROJECT_VERSION}
COMPATIBILITY AnyNewerVersion
)

qt_install(TARGETS ${target}
EXPORT "${export_name}"
DESTINATION "${config_install_dir}"
)

qt_install(EXPORT ${export_name}
NAMESPACE "${QT_CMAKE_EXPORT_NAMESPACE}::"
DESTINATION "${config_install_dir}"
)

qt_internal_export_modern_cmake_config_targets_file(
TARGETS ${target}
EXPORT_NAME_PREFIX ${INSTALL_CMAKE_NAMESPACE}${target}
CONFIG_INSTALL_DIR "${config_install_dir}"
)
endif()
endfunction()

function(qt_get_tool_cmake_configuration out_var)
qt_get_main_cmake_configuration("${out_var}")
string(TOUPPER "${${out_var}}" upper_config)
Expand Down
39 changes: 39 additions & 0 deletions util/cmake/pro2cmake.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@ def nested_dict():
api[2]["qt_add_resource"] = "qt_add_resource"
api[2]["qt_add_qml_module"] = "qt_add_qml_module"
api[2]["qt_add_cmake_library"] = "qt_add_cmake_library"
api[2]["qt_add_3rdparty_library"] = "qt_add_3rdparty_library"

return api

Expand Down Expand Up @@ -2802,6 +2803,41 @@ def write_main_part(
cm_fh.write(ignored_keys_report)


def write_3rdparty_library(cm_fh: IO[str], scope: Scope, *, indent: int = 0) -> str:

# Remove default QT libs.
scope._append_operation("QT", RemoveOperation(["core", "gui"]))

target_name = re.sub(r"^qt", "", scope.TARGET)
target_name = target_name.replace("-", "_")

library_type = ""

if "dll" in scope.get("CONFIG"):
library_type = "SHARED"
else:
library_type = "STATIC"

extra_lines = []

if library_type:
extra_lines.append(library_type)

write_main_part(
cm_fh,
target_name,
"Generic Library",
get_cmake_api_call("qt_add_3rdparty_library"),
scope,
extra_lines=extra_lines,
indent=indent,
known_libraries={},
extra_keys=[],
)

return target_name


def write_generic_library(cm_fh: IO[str], scope: Scope, *, indent: int = 0) -> str:

target_name = scope.TARGET
Expand Down Expand Up @@ -3524,6 +3560,9 @@ def handle_app_or_lib(

if is_jar:
write_jar(cm_fh, scope, indent=indent)
elif "qt_helper_lib" in scope.get("_LOADED"):
assert not is_example
target = write_3rdparty_library(cm_fh, scope, indent=indent)
elif is_example:
target = write_example(cm_fh, scope, gui, indent=indent, is_plugin=is_plugin)
elif is_qt_plugin:
Expand Down

0 comments on commit 572c03e

Please sign in to comment.