From 79878b167f1b95dfd50a00d8ca36d9074b861ac3 Mon Sep 17 00:00:00 2001 From: Yuhang Zhao Date: Fri, 28 Jul 2023 14:09:47 +0800 Subject: [PATCH] update --- utils.cmake | 424 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 324 insertions(+), 100 deletions(-) diff --git a/utils.cmake b/utils.cmake index acdfb3c..64331af 100644 --- a/utils.cmake +++ b/utils.cmake @@ -22,6 +22,89 @@ SOFTWARE. ]] +function(are_paths_equal lhs rhs out_var) + if(NOT lhs OR NOT rhs) + message(AUTHOR_WARNING "are_paths_equal: You have to pass two paths to this function!") + return() + endif() + if("x${lhs}" STREQUAL "x" OR "x${rhs}" STREQUAL "x") + message(AUTHOR_WARNING "are_paths_equal: Empty paths are not allowed!") + return() + endif() + if(NOT out_var) + message(AUTHOR_WARNING "are_paths_equal: You need to specify an output variable!") + return() + endif() + cmake_path(NORMAL_PATH lhs OUTPUT_VARIABLE path1) + cmake_path(NORMAL_PATH rhs OUTPUT_VARIABLE path2) + if(path1 STREQUAL path2) + set(${out_var} TRUE PARENT_SCOPE) + else() + set(${out_var} FALSE PARENT_SCOPE) + endif() +endfunction() + +function(compute_install_dir) + cmake_parse_arguments(arg "NO_64BIT_SUFFIX;ROOT" "IS_MULTI_CONFIG;BIN_DIR;LIB_DIR;INCLUDE_DIR;QML_DIR;DATA_DIR;INFO_DIR;MAN_DIR;DOC_DIR;LOCALE_DIR" "" ${ARGN}) + if(arg_UNPARSED_ARGUMENTS) + message(AUTHOR_WARNING "compute_install_dir: Unrecognized arguments: ${arg_UNPARSED_ARGUMENTS}") + endif() + set(__dir_suffix "") + if(CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT arg_NO_64BIT_SUFFIX) + set(__dir_suffix "64") + endif() + include(GNUInstallDirs) + if("x${CMAKE_INSTALL_QMLDIR}" STREQUAL "x") + set(CMAKE_INSTALL_QMLDIR "qml") + endif() + set(__bin_dir "${CMAKE_INSTALL_BINDIR}${__dir_suffix}") + set(__lib_dir "${CMAKE_INSTALL_LIBDIR}${__dir_suffix}") + set(__inc_dir "${CMAKE_INSTALL_INCLUDEDIR}") + set(__qml_dir "${CMAKE_INSTALL_QMLDIR}") + set(__data_dir "${CMAKE_INSTALL_DATADIR}") + set(__info_dir "${CMAKE_INSTALL_INFODIR}") + set(__man_dir "${CMAKE_INSTALL_MANDIR}") + set(__doc_dir "${CMAKE_INSTALL_DOCDIR}") + set(__locale_dir "${CMAKE_INSTALL_LOCALEDIR}") + if("x${CMAKE_BUILD_TYPE}" STREQUAL "x" AND NOT "x${CMAKE_CONFIGURATION_TYPES}" STREQUAL "x") + if(arg_IS_MULTI_CONFIG) + set(${arg_IS_MULTI_CONFIG} TRUE PARENT_SCOPE) + endif() + if(NOT arg_ROOT) + set(__subdir "/$>") + string(APPEND __bin_dir "${__subdir}") + string(APPEND __lib_dir "${__subdir}") + endif() + endif() + if(arg_BIN_DIR) + set(${arg_BIN_DIR} "${__bin_dir}" PARENT_SCOPE) + endif() + if(arg_LIB_DIR) + set(${arg_LIB_DIR} "${__lib_dir}" PARENT_SCOPE) + endif() + if(arg_INCLUDE_DIR) + set(${arg_INCLUDE_DIR} "${__inc_dir}" PARENT_SCOPE) + endif() + if(arg_QML_DIR) + set(${arg_QML_DIR} "${__qml_dir}" PARENT_SCOPE) + endif() + if(arg_DATA_DIR) + set(${arg_DATA_DIR} "${__data_dir}" PARENT_SCOPE) + endif() + if(arg_INFO_DIR) + set(${arg_INFO_DIR} "${__info_dir}" PARENT_SCOPE) + endif() + if(arg_MAN_DIR) + set(${arg_MAN_DIR} "${__man_dir}" PARENT_SCOPE) + endif() + if(arg_DOC_DIR) + set(${arg_DOC_DIR} "${__doc_dir}" PARENT_SCOPE) + endif() + if(arg_LOCALE_DIR) + set(${arg_LOCALE_DIR} "${__locale_dir}" PARENT_SCOPE) + endif() +endfunction() + function(setup_project) cmake_parse_arguments(PROJ_ARGS "QT_PROJECT;ENABLE_LTO;WARNINGS_ARE_ERRORS;MAX_WARNING;NO_WARNING;RTTI;EXCEPTIONS" "QML_IMPORT_DIR" "LANGUAGES" ${ARGN}) if(NOT PROJ_ARGS_LANGUAGES) @@ -167,35 +250,21 @@ function(setup_project) set(CMAKE_FRAMEWORK_MULTI_CONFIG_POSTFIX_DEBUG "_debug" PARENT_SCOPE) endif() endif() - set(__dir_suffix "") - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(__dir_suffix "64") + set(__is_multi_config FALSE) + set(__bin_dir "") + set(__lib_dir "") + compute_install_dir(IS_MULTI_CONFIG __is_multi_config BIN_DIR __bin_dir LIB_DIR __lib_dir) + if(NOT DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${__bin_dir}" PARENT_SCOPE) endif() - include(GNUInstallDirs) - set(__bin_dir "${CMAKE_INSTALL_BINDIR}${__dir_suffix}") - set(__lib_dir "${CMAKE_INSTALL_LIBDIR}${__dir_suffix}") - set(__ar_dir "${CMAKE_INSTALL_LIBDIR}${__dir_suffix}") - if(DEFINED CMAKE_BUILD_TYPE AND NOT "x${CMAKE_BUILD_TYPE}" STREQUAL "x") - if(NOT DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${__bin_dir}" PARENT_SCOPE) - endif() - if(NOT DEFINED CMAKE_LIBRARY_OUTPUT_DIRECTORY) - set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${__lib_dir}" PARENT_SCOPE) - endif() - if(NOT DEFINED CMAKE_ARCHIVE_OUTPUT_DIRECTORY) - set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${__ar_dir}" PARENT_SCOPE) - endif() - elseif(DEFINED CMAKE_CONFIGURATION_TYPES AND NOT "x${CMAKE_CONFIGURATION_TYPES}" STREQUAL "x") - set(__subdir "$>") - if(NOT DEFINED CMAKE_RUNTIME_OUTPUT_DIRECTORY) - set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${__bin_dir}/${__subdir}" PARENT_SCOPE) - endif() - if(NOT DEFINED CMAKE_LIBRARY_OUTPUT_DIRECTORY) - set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${__lib_dir}/${__subdir}" PARENT_SCOPE) - endif() - if(NOT DEFINED CMAKE_ARCHIVE_OUTPUT_DIRECTORY) - set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${__ar_dir}/${__subdir}" PARENT_SCOPE) - endif() + if(NOT DEFINED CMAKE_LIBRARY_OUTPUT_DIRECTORY) + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${__lib_dir}" PARENT_SCOPE) + endif() + if(NOT DEFINED CMAKE_ARCHIVE_OUTPUT_DIRECTORY) + set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${PROJECT_BINARY_DIR}/${__lib_dir}" PARENT_SCOPE) + endif() + if(__is_multi_config) + compute_install_dir(ROOT BIN_DIR __bin_dir LIB_DIR __lib_dir) foreach(__type ${CMAKE_CONFIGURATION_TYPES}) string(TOUPPER ${__type} __type_upper) string(TOLOWER ${__type} __type_lower) @@ -209,7 +278,7 @@ function(setup_project) endif() set(__ar_var CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${__type_upper}) if(NOT DEFINED ${__ar_var}) - set(${__ar_var} "${PROJECT_BINARY_DIR}/${__ar_dir}/${__type_lower}" PARENT_SCOPE) + set(${__ar_var} "${PROJECT_BINARY_DIR}/${__lib_dir}/${__type_lower}" PARENT_SCOPE) endif() endforeach() endif() @@ -228,7 +297,8 @@ function(setup_project) set(CMAKE_VISIBILITY_INLINES_HIDDEN ON PARENT_SCOPE) endif() if(NOT DEFINED CMAKE_INSTALL_RPATH_USE_LINK_PATH) - set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON PARENT_SCOPE) + # We'll handle RPATHs manually later. + set(CMAKE_INSTALL_RPATH_USE_LINK_PATH OFF PARENT_SCOPE) endif() if(APPLE) if(NOT DEFINED CMAKE_MACOSX_RPATH) @@ -236,7 +306,15 @@ function(setup_project) endif() else() if(NOT DEFINED CMAKE_INSTALL_RPATH) - set(CMAKE_INSTALL_RPATH "$ORIGIN/../${__lib_dir}" PARENT_SCOPE) + # Don't set RPATHs globally. We'll handle RPATHs for each target separately later. + set(CMAKE_INSTALL_RPATH "" PARENT_SCOPE) + endif() + endif() + if(NOT DEFINED CMAKE_INSTALL_PREFIX) + if(WIN32) + set(CMAKE_INSTALL_PREFIX "C:/Packages/${PROJECT_NAME}" PARENT_SCOPE) + else() + set(CMAKE_INSTALL_PREFIX "/opt/packages/${PROJECT_NAME}" PARENT_SCOPE) endif() endif() if(PROJ_ARGS_QT_PROJECT) @@ -560,6 +638,7 @@ function(setup_compile_params) target_compile_definitions(${__target} PRIVATE WINVER=${_WIN32_WINNT_WIN10} _WIN32_WINNT=${_WIN32_WINNT_WIN10} _WIN32_IE=${_WIN32_WINNT_WIN10} NTDDI_VERSION=${NTDDI_WIN10_NI} + GDIPVER=0x0110 # Enable GDI+ v1.1, which is available since Windows Vista. ) endif() if(MSVC) @@ -604,6 +683,11 @@ function(setup_compile_params) if(CMAKE_SIZEOF_VOID_P EQUAL 8) target_compile_options(${__target} PRIVATE /d2FH4) endif() + if(COM_ARGS_INTELCET) + target_link_options(${__target} PRIVATE $<$:/CETCOMPAT>) + else() + target_link_options(${__target} PRIVATE $<$:/CETCOMPAT:NO>) + endif() endif() if(MSVC_VERSION GREATER_EQUAL 1924) # Visual Studio 2019 version 16.4 target_compile_options(${__target} PRIVATE $<$:/ZH:SHA_256>) @@ -611,6 +695,16 @@ function(setup_compile_params) if(MSVC_VERSION GREATER_EQUAL 1925) # Visual Studio 2019 version 16.5 target_compile_options(${__target} PRIVATE $<$:/QIntel-jcc-erratum>) endif() + if(MSVC_VERSION GREATER_EQUAL 1927) # Visual Studio 2019 version 16.7 + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + if(COM_ARGS_EHCONTGUARD) + target_compile_options(${__target} PRIVATE $<$:/guard:ehcont>) + target_link_options(${__target} PRIVATE $<$:/guard:ehcont>) + else() + target_compile_options(${__target} PRIVATE $<$:/guard:ehcont->) + endif() + endif() + endif() if(MSVC_VERSION GREATER_EQUAL 1929) # Visual Studio 2019 version 16.10 target_compile_options(${__target} PRIVATE /await:strict) elseif(MSVC_VERSION GREATER_EQUAL 1900) # Visual Studio 2015 @@ -622,11 +716,9 @@ function(setup_compile_params) if(COM_ARGS_CFGUARD) target_compile_options(${__target} PRIVATE $<$:/guard:cf>) target_link_options(${__target} PRIVATE $<$:/GUARD:CF>) - endif() - if(COM_ARGS_INTELCET) - if(MSVC_VERSION GREATER_EQUAL 1920) # Visual Studio 2019 version 16.0 - target_link_options(${__target} PRIVATE $<$:/CETCOMPAT>) - endif() + else() + target_compile_options(${__target} PRIVATE $<$:/guard:cf->) + target_link_options(${__target} PRIVATE $<$:/GUARD:NO>) endif() if(COM_ARGS_SPECTRE) if(MSVC_VERSION GREATER_EQUAL 1925) # Visual Studio 2019 version 16.5 @@ -635,12 +727,6 @@ function(setup_compile_params) target_compile_options(${__target} PRIVATE /Qspectre) endif() endif() - if(COM_ARGS_EHCONTGUARD) - if((MSVC_VERSION GREATER_EQUAL 1927) AND (CMAKE_SIZEOF_VOID_P EQUAL 8)) # Visual Studio 2019 version 16.7 - target_compile_options(${__target} PRIVATE $<$:/guard:ehcont>) - target_link_options(${__target} PRIVATE $<$:/guard:ehcont>) - endif() - endif() if(COM_ARGS_PERMISSIVE) target_compile_options(${__target} PRIVATE /Zc:auto /Zc:forScope /Zc:implicitNoexcept /Zc:noexceptTypes /Zc:referenceBinding @@ -904,17 +990,13 @@ function(prepare_package_export) if(PKG_ARGS_UNPARSED_ARGUMENTS) message(AUTHOR_WARNING "prepare_package_export: Unrecognized arguments: ${PKG_ARGS_UNPARSED_ARGUMENTS}") endif() - include(CMakePackageConfigHelpers) - include(GNUInstallDirs) - set(__dir_suffix "") - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(__dir_suffix "64") - endif() - set(__lib_dir "${CMAKE_INSTALL_LIBDIR}${__dir_suffix}") + set(__lib_dir "") + compute_install_dir(LIB_DIR __lib_dir) set(__config_name "${PKG_ARGS_PACKAGE_NAME}Config") set(__config_file "${__config_name}.cmake") set(__version_name "${__config_name}Version") set(__versoin_file "${__version_name}.cmake") + include(CMakePackageConfigHelpers) write_basic_package_version_file( "${CMAKE_CURRENT_BINARY_DIR}/${__versoin_file}" VERSION ${PKG_ARGS_PACKAGE_VERSION} @@ -953,23 +1035,13 @@ function(setup_package_export) if(PKG_ARGS_UNPARSED_ARGUMENTS) message(AUTHOR_WARNING "setup_package_export: Unrecognized arguments: ${PKG_ARGS_UNPARSED_ARGUMENTS}") endif() - set(__dir_suffix "") - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(__dir_suffix "64") - endif() - include(GNUInstallDirs) - set(__bin_dir "${CMAKE_INSTALL_BINDIR}${__dir_suffix}") - set(__lib_dir "${CMAKE_INSTALL_LIBDIR}${__dir_suffix}") - set(__ar_dir "${CMAKE_INSTALL_LIBDIR}${__dir_suffix}") + set(__bin_dir "") + set(__lib_dir "") + set(__include_dir "") + compute_install_dir(BIN_DIR __bin_dir LIB_DIR __lib_dir INCLUDE_DIR __include_dir) set(__cmake_dir "${__lib_dir}/cmake") - if((NOT DEFINED CMAKE_BUILD_TYPE OR "x${CMAKE_BUILD_TYPE}" STREQUAL "x") AND NOT "x${CMAKE_CONFIGURATION_TYPES}" STREQUAL "x") - set(__subdir "/$>") - string(APPEND __bin_dir "${__subdir}") - string(APPEND __lib_dir "${__subdir}") - string(APPEND __ar_dir "${__subdir}") - endif() - set(__inc_dir "${CMAKE_INSTALL_INCLUDEDIR}/${PKG_ARGS_PACKAGE_NAME}") - set(__inc_dir_list "${CMAKE_INSTALL_INCLUDEDIR}" "${__inc_dir}") + set(__inc_dir "${__include_dir}/${PKG_ARGS_PACKAGE_NAME}") + set(__inc_dir_list "${__include_dir}" "${__inc_dir}") if(PKG_ARGS_COMPONENT) set(__inc_dir "${__inc_dir}/${PKG_ARGS_COMPONENT}") list(APPEND __inc_dir_list "${__inc_dir}") @@ -988,7 +1060,7 @@ function(setup_package_export) BUNDLE DESTINATION . RUNTIME DESTINATION "${__bin_dir}" LIBRARY DESTINATION "${__lib_dir}" - ARCHIVE DESTINATION "${__ar_dir}" + ARCHIVE DESTINATION "${__lib_dir}" ) export(EXPORT ${__export_name} FILE "${CMAKE_CURRENT_BINARY_DIR}/cmake/${__export_file}" @@ -1019,25 +1091,14 @@ function(install2) if(arg_UNPARSED_ARGUMENTS) message(AUTHOR_WARNING "install2: Unrecognized arguments: ${arg_UNPARSED_ARGUMENTS}") endif() - set(__dir_suffix "") - if(CMAKE_SIZEOF_VOID_P EQUAL 8) - set(__dir_suffix "64") - endif() - include(GNUInstallDirs) - set(__bin_dir "${CMAKE_INSTALL_BINDIR}${__dir_suffix}") - set(__lib_dir "${CMAKE_INSTALL_LIBDIR}${__dir_suffix}") - set(__ar_dir "${CMAKE_INSTALL_LIBDIR}${__dir_suffix}") - if((NOT DEFINED CMAKE_BUILD_TYPE OR "x${CMAKE_BUILD_TYPE}" STREQUAL "x") AND NOT "x${CMAKE_CONFIGURATION_TYPES}" STREQUAL "x") - set(__subdir "/$>") - string(APPEND __bin_dir "${__subdir}") - string(APPEND __lib_dir "${__subdir}") - string(APPEND __ar_dir "${__subdir}") - endif() + set(__bin_dir "") + set(__lib_dir "") + compute_install_dir(BIN_DIR __bin_dir LIB_DIR __lib_dir) install(TARGETS ${arg_TARGETS} BUNDLE DESTINATION . RUNTIME DESTINATION "${__bin_dir}" LIBRARY DESTINATION "${__lib_dir}" - ARCHIVE DESTINATION "${__ar_dir}" + ARCHIVE DESTINATION "${__lib_dir}" ) endfunction() @@ -1050,12 +1111,16 @@ function(deploy_qt_runtime) if(DEPLOY_ARGS_UNPARSED_ARGUMENTS) message(AUTHOR_WARNING "deploy_qt_runtime: Unrecognized arguments: ${DEPLOY_ARGS_UNPARSED_ARGUMENTS}") endif() - find_package(QT NAMES Qt6 Qt5 QUIET COMPONENTS Core) - if(NOT (Qt5_FOUND OR Qt6_FOUND)) - message(AUTHOR_WARNING "deploy_qt_runtime: You need to install the QtCore module first to be able to deploy the Qt libraries.") - return() + if(NOT TARGET Qt6::Core AND NOT TARGET Qt5::Core) + find_package(Qt6 QUIET COMPONENTS Core) + if(NOT TARGET Qt6::Core) + find_package(Qt5 QUIET COMPONENTS Core) + if(NOT TARGET Qt5::Core) + message(AUTHOR_WARNING "deploy_qt_runtime: You need to install the QtCore module first to be able to deploy the Qt libraries.") + return() + endif() + endif() endif() - find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core) # "QT_QMAKE_EXECUTABLE" is usually defined by QtCreator. if(NOT DEFINED QT_QMAKE_EXECUTABLE) get_target_property(QT_QMAKE_EXECUTABLE Qt::qmake IMPORTED_LOCATION) @@ -1242,10 +1307,12 @@ function(setup_translations) # really can't use them until Qt6 (the functions have been completely # re-written in Qt6 and according to my experiments they work reliably # now finally). - find_package(Qt6 QUIET COMPONENTS LinguistTools) - if(NOT Qt6LinguistTools_FOUND) - message(AUTHOR_WARNING "setup_translations: You need to install the Qt Linguist Tools first to be able to create translations.") - return() + if(NOT TARGET Qt6::LinguistTools) + find_package(Qt6 QUIET COMPONENTS LinguistTools) + if(NOT TARGET Qt6::LinguistTools) + message(AUTHOR_WARNING "setup_translations: You need to install the Qt Linguist Tools first to be able to create translations.") + return() + endif() endif() set(__ts_dir translations) if(TRANSLATION_ARGS_TS_DIR) @@ -1539,11 +1606,15 @@ function(query_qt_paths) if(QT_ARGS_UNPARSED_ARGUMENTS) message(AUTHOR_WARNING "query_qt_paths: Unrecognized arguments: ${QT_ARGS_UNPARSED_ARGUMENTS}") endif() - find_package(QT NAMES Qt6 Qt5 QUIET COMPONENTS Core) - find_package(Qt${QT_VERSION_MAJOR} QUIET COMPONENTS Core) - if(NOT (Qt6_FOUND OR Qt5_FOUND)) - message(AUTHOR_WARNING "You need to install the QtCore module first to be able to query Qt installation paths.") - return() + if(NOT TARGET Qt6::Core AND NOT TARGET Qt5::Core) + find_package(Qt6 QUIET COMPONENTS Core) + if(NOT TARGET Qt6::Core) + find_package(Qt5 QUIET COMPONENTS Core) + if(NOT TARGET Qt5::Core) + message(AUTHOR_WARNING "You need to install the QtCore module first to be able to query Qt installation paths.") + return() + endif() + endif() endif() # /whatever/Qt/6.5.0/gcc_64/lib/cmake/Qt6 set(__qt_inst_dir "${Qt${QT_VERSION_MAJOR}_DIR}") @@ -1581,11 +1652,15 @@ function(query_qt_library_info) if(QT_ARGS_UNPARSED_ARGUMENTS) message(AUTHOR_WARNING "query_qt_library_info: Unrecognized arguments: ${QT_ARGS_UNPARSED_ARGUMENTS}") endif() - find_package(QT NAMES Qt6 Qt5 QUIET COMPONENTS Core) - find_package(Qt${QT_VERSION_MAJOR} QUIET COMPONENTS Core) - if(NOT (Qt6_FOUND OR Qt5_FOUND)) - message(AUTHOR_WARNING "You need to install the QtCore module first to be able to query Qt library information.") - return() + if(NOT TARGET Qt6::Core AND NOT TARGET Qt5::Core) + find_package(Qt6 QUIET COMPONENTS Core) + if(NOT TARGET Qt6::Core) + find_package(Qt5 QUIET COMPONENTS Core) + if(NOT TARGET Qt5::Core) + message(AUTHOR_WARNING "You need to install the QtCore module first to be able to query Qt library information.") + return() + endif() + endif() endif() if(QT_ARGS_STATIC OR QT_ARGS_SHARED) get_target_property(__lib_type Qt${QT_VERSION_MAJOR}::Core TYPE) @@ -1634,3 +1709,152 @@ function(dump_target_info) message("${__target}'s link options: ${__link_options}") endforeach() endfunction() + +function(compute_relative_rpath) + cmake_parse_arguments(arg "" "RPATH;INSTALL_LOCATION;OUTPUT_VARIABLE" "" ${ARGN}) + if(NOT arg_RPATH) + message(AUTHOR_WARNING "compute_relative_rpath: You need to specify the RPATH parameter!") + return() + endif() + if(NOT arg_INSTALL_LOCATION) + message(AUTHOR_WARNING "compute_relative_rpath: You need to specify the INSTALL_LOCATION parameter!") + return() + endif() + if(NOT arg_OUTPUT_VARIABLE) + message(AUTHOR_WARNING "compute_relative_rpath: You need to specify the OUTPUT_VARIABLE parameter!") + return() + endif() + if(arg_UNPARSED_ARGUMENTS) + message(AUTHOR_WARNING "compute_relative_rpath: Unrecognized arguments: ${arg_UNPARSED_ARGUMENTS}") + endif() + if("x${CMAKE_INSTALL_PREFIX}" STREQUAL "x") + message(AUTHOR_WARNING "compute_relative_rpath: CMAKE_INSTALL_PREFIX is empty!") + return() + endif() + set(__lib_dir "") + compute_install_dir(LIB_DIR __lib_dir) + set(__lib_dir_absolute "${CMAKE_INSTALL_PREFIX}/${__lib_dir}") + set(__rpath_absolute "") + cmake_path(ABSOLUTE_PATH "${arg_RPATH}" BASE_DIRECTORY "${__lib_dir_absolute}" OUTPUT_VARIABLE __rpath_absolute) + set(__install_location_absolute "${arg_INSTALL_LOCATION}") + if(NOT IS_ABSOLUTE "${__install_location_absolute}") + set(__install_location_absolute "${CMAKE_INSTALL_PREFIX}/${arg_INSTALL_LOCATION}") + endif() + set(__rpath_relative "") + cmake_path(RELATIVE_PATH "${__rpath_absolute}" BASE_DIRECTORY "${__install_location_absolute}" OUTPUT_VARIABLE __rpath_relative) + if("x${__rpath_relative}" STREQUAL "x") + # We may get an empty string if the given absolute paths are equal. + set(__rpath_relative ".") + endif() + if(APPLE) + set(__rpath_base "@loader_path") + else() + set(__rpath_base "$ORIGIN") + else() + if(__rpath_relative STREQUAL ".") + set(__rpath_relative "${__rpath_base}") + else() + set(__rpath_relative "${__rpath_base}/${__rpath_relative}") + endif() + set(${arg_OUTPUT_VARIABLE} "${__rpath_relative}" PARENT_SCOPE) +endfunction() + +function(setup_target_rpaths) + # RPATH is not supported on Windows and Android platform. + if(WIN32 OR ANDROID) + return() + endif() + cmake_parse_arguments(arg "" "" "TARGETS" ${ARGN}) + if(NOT arg_TARGETS) + message(AUTHOR_WARNING "setup_target_rpaths: you have to specify at least one target!") + return() + endif() + if(arg_UNPARSED_ARGUMENTS) + message(AUTHOR_WARNING "setup_target_rpaths: Unrecognized arguments: ${arg_UNPARSED_ARGUMENTS}") + endif() + if("x${CMAKE_INSTALL_PREFIX}" STREQUAL "x") + message(AUTHOR_WARNING "setup_target_rpaths: CMAKE_INSTALL_PREFIX is empty!") + return() + endif() + set(__lib_dir "") + compute_install_dir(LIB_DIR __lib_dir) + set(__lib_dir_absolute "${CMAKE_INSTALL_PREFIX}/${__lib_dir}") + set(__is_system_dir -1) + set(__scopes PLATFORM CXX C) + foreach(__scope ${__scopes}) + set(__var_name "CMAKE_${__scope}_IMPLICIT_LINK_DIRECTORIES") + if("x${__var_name}" STREQUAL "x") + continue() + endif() + list(FIND ${__var_name} "${__lib_dir_absolute}" __is_system_dir) + if(__is_system_dir GREATER_EQUAL 0) + break() + endif() + endforeach() + if(__is_system_dir LESS 0) + set(__default_install_rpath "${__lib_dir_absolute}") + endif() + foreach(__target ${arg_TARGETS}) + if(NOT TARGET ${__target}) + message(AUTHOR_WARNING "${__target} is not a valid CMake target!") + continue() + endif() + get_target_property(__target_type ${__target} TYPE) + if(__target_type STREQUAL "INTERFACE_LIBRARY") + message(AUTHOR_WARNING "You should not set RPATH for ${__target}, which is an interface library.") + continue() + endif() + set(__install_rpath "") + if(APPLE) + get_target_property(__is_framework ${__target} FRAMEWORK) + if(__is_framework) + set(__install_rpath "/${__target}.framework/Versions/Current") + endif() + get_target_property(__is_bundle ${__target} MACOSX_BUNDLE) + if(__is_bundle AND NOT __is_framework) + set(__install_rpath "/${__target}.app/Contents/MacOS") + endif() + else() + compute_relative_rpath(RPATH "${__default_install_rpath}" INSTALL_LOCATION "${__lib_dir}" OUTPUT_VARIABLE __install_rpath) + endif() + if(NOT "x${__install_rpath}" STREQUAL "x") + set(__install_prefix "") + if(NOT "x${CMAKE_STAGING_PREFIX}" STREQUAL "x") + set(__install_prefix "${CMAKE_STAGING_PREFIX}") + else() + set(__install_prefix "${CMAKE_INSTALL_PREFIX}") + endif() + set(__will_install FALSE) + if("x${__install_prefix}" STREQUAL "x") + else() + set(__equal FALSE) + are_paths_equal(__install_prefix PROJECT_BINARY_DIR __equal) + if(__equal) + else() + set(__win_path "C:/Program Files/${PROJECT_NAME}") + are_paths_equal(__install_prefix __win_path __equal) + if(__equal) + else() + set(__win_path "C:/Program Files (x86)/${PROJECT_NAME}") + are_paths_equal(__install_prefix __win_path __equal) + if(__equal) + else() + set(__unix_path "/usr/local") + are_paths_equal(__install_prefix __unix_path __equal) + if(__equal) + else() + set(__will_install TRUE) + endif() + endif() + endif() + endif() + endif() + if(__will_install) + set(__prop_name "INSTALL_RPATH") + else() + set(__prop_name "BUILD_RPATH") + endif() + set_target_properties(${__target} PROPERTIES "${__prop_name}" "${__install_rpath}") + endif() + endforeach() +endif()