diff --git a/bin/qt-cmake.bat.in b/bin/qt-cmake.bat.in index 6e5b27010b..2645c0320f 100644 --- a/bin/qt-cmake.bat.in +++ b/bin/qt-cmake.bat.in @@ -1 +1,10 @@ -"@CMAKE_COMMAND@" -DCMAKE_TOOLCHAIN_FILE="@__GlobalConfig_install_dir_absolute@/qt.toolchain.cmake" @__qt_cmake_extra@ %* +@echo off +:: The directory of this script is the expanded absolute path of the "$qt_prefix/bin" directory. +set script_dir_path=%~dp0 + +:: Try to use original cmake, otherwise to make it relocatable, use any cmake found in PATH. +set cmake_path=@CMAKE_COMMAND@ +if not exist "%cmake_path%" set cmake_path=cmake + +set toolchain_path=%script_dir_path%/@__GlobalConfig_relative_path_from_bin_dir_to_cmake_config_dir@/qt.toolchain.cmake +"%cmake_path%" -DCMAKE_TOOLCHAIN_FILE="%toolchain_path%" @__qt_cmake_extra@ %* diff --git a/bin/qt-cmake.in b/bin/qt-cmake.in index 2b42592267..f719257f60 100755 --- a/bin/qt-cmake.in +++ b/bin/qt-cmake.in @@ -1,3 +1,17 @@ #!/bin/sh -exec @CMAKE_COMMAND@ -DCMAKE_TOOLCHAIN_FILE=@__GlobalConfig_install_dir_absolute@/qt.toolchain.cmake @__qt_cmake_extra@ "$@" +# The directory of this script is the expanded absolute path of the "$qt_prefix/bin" directory. +script_dir_path=`dirname $0` +script_dir_path=`(cd "$script_dir_path"; /bin/pwd)` + +# Try to use original cmake, otherwise to make it relocatable, use any cmake found in PATH. +original_cmake_path="@CMAKE_COMMAND@" +cmake_path=$original_cmake_path +if ! test -f "$cmake_path"; then + cmake_path="cmake" +fi + +toolchain_path="$script_dir_path/@__GlobalConfig_relative_path_from_bin_dir_to_cmake_config_dir@/qt.toolchain.cmake" + +# Find the qt toolchain relative to the absolute bin dir path where the script is located. +exec "$cmake_path" -DCMAKE_TOOLCHAIN_FILE="$toolchain_path" @__qt_cmake_extra@ "$@" diff --git a/cmake/QtBaseGlobalTargets.cmake b/cmake/QtBaseGlobalTargets.cmake index c82ef410a3..d00d536194 100644 --- a/cmake/QtBaseGlobalTargets.cmake +++ b/cmake/QtBaseGlobalTargets.cmake @@ -23,12 +23,21 @@ 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}") +set(__qt_bin_dir_absolute "${QT_INSTALL_DIR}/${INSTALL_BINDIR}") 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}) + ${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX} + ${__GlobalConfig_install_dir_absolute}) + qt_path_join(__qt_bin_dir_absolute + ${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX} ${__qt_bin_dir_absolute}) endif() +# Compute relative path from $qt_prefix/bin dir to global CMake config install dir, to use in the +# unix-y qt-cmake shell script, to make it work even if the installed Qt is relocated. +file(RELATIVE_PATH + __GlobalConfig_relative_path_from_bin_dir_to_cmake_config_dir + ${__qt_bin_dir_absolute} ${__GlobalConfig_install_dir_absolute}) # Generate and install Qt6 config file. configure_package_config_file( @@ -158,7 +167,9 @@ endif() string(REPLACE ";" "\n" init_vcpkg "${init_vcpkg}") string(REPLACE ";" "\n" init_platform "${init_platform}") string(REPLACE "LITERAL_SEMICOLON" ";" init_platform "${init_platform}") +qt_compute_relative_path_from_cmake_config_dir_to_prefix() configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/qt.toolchain.cmake.in" "${__GlobalConfig_build_dir}/qt.toolchain.cmake" @ONLY) +unset(qt_path_from_cmake_config_dir_to_prefix) qt_install(FILES "${__GlobalConfig_build_dir}/qt.toolchain.cmake" DESTINATION "${__GlobalConfig_install_dir}" COMPONENT Devel) # Also provide a convenience cmake wrapper @@ -196,7 +207,8 @@ unset(__qt_cmake_extra) # Instead a template CMakeLists.txt project is used which sets up all the necessary private bits # and then calls add_subdirectory on the provided project path. set(__qt_cmake_standalone_test_bin_name "qt-cmake-standalone-test") -set(__qt_cmake_private_path "${CMAKE_INSTALL_PREFIX}/${INSTALL_BINDIR}/qt-cmake-private") +set(__qt_cmake_private_path + "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${INSTALL_BINDIR}/qt-cmake-private") set(__qt_cmake_standalone_test_path "${__build_internals_install_dir}/${__build_internals_standalone_test_template_dir}") if(UNIX) diff --git a/cmake/QtBuild.cmake b/cmake/QtBuild.cmake index 7ed47fc4f2..1581b39a28 100644 --- a/cmake/QtBuild.cmake +++ b/cmake/QtBuild.cmake @@ -13,7 +13,8 @@ function(qt_configure_process_path name default docstring) else() get_filename_component(given_path_as_abs "${${name}}" ABSOLUTE BASE_DIR "${CMAKE_INSTALL_PREFIX}") - file(RELATIVE_PATH rel_path "${CMAKE_INSTALL_PREFIX}" "${given_path_as_abs}") + file(RELATIVE_PATH rel_path "${CMAKE_INSTALL_PREFIX}" + "${given_path_as_abs}") # If absolute path given, check that it's inside the prefix (error out if not). # TODO: Figure out if we need to support paths that are outside the prefix. @@ -75,6 +76,59 @@ qt_configure_process_path(INSTALL_DESCRIPTIONSDIR "${INSTALL_DATADIR}/modules" "Module description files directory") +function(qt_internal_set_up_global_paths) + # Compute the values of QT_BUILD_DIR, QT_INSTALL_DIR, QT_CONFIG_BUILD_DIR, QT_CONFIG_INSTALL_DIR + # taking into account whether the current build is a prefix build or a non-prefix build, + # and whether it is a superbuild or non-superbuild. + # A third case is when another module or standalone tests are built against a super-built Qt. + # The layout for the third case is the same as for non-superbuilds. + # + # These values should be prepended to file paths in commands or properties, + # in order to correctly place generated Config files, generated Targets files, + # excutables / libraries, when copying / installing files, etc. + # + # The build dir variables will always be absolute paths. + # The QT_INSTALL_DIR variable will have a relative path in a prefix build, + # which means that it can be empty, so use qt_join_path to prevent accidental absolute paths. + if(QT_SUPERBUILD) + # In this case, we always copy all the build products in qtbase/{bin,lib,...} + if(QT_WILL_INSTALL) + set(QT_BUILD_DIR "${QtBase_BINARY_DIR}") + set(QT_INSTALL_DIR "") + else() + set(QT_BUILD_DIR "${QtBase_BINARY_DIR}") + set(QT_INSTALL_DIR "${QtBase_BINARY_DIR}") + endif() + else() + if(QT_WILL_INSTALL) + # In the usual prefix build case, the build dir is the current module build dir, + # and the install dir is the prefix, so we don't set it. + set(QT_BUILD_DIR "${CMAKE_BINARY_DIR}") + set(QT_INSTALL_DIR "") + else() + # When doing a non-prefix build, both the build dir and install dir are the same, + # pointing to the qtbase build dir. + set(QT_BUILD_DIR "${CMAKE_INSTALL_PREFIX}") + set(QT_INSTALL_DIR "${QT_BUILD_DIR}") + endif() + endif() + + set(__config_path_part "${INSTALL_LIBDIR}/cmake") + set(QT_CONFIG_BUILD_DIR "${QT_BUILD_DIR}/${__config_path_part}") + set(QT_CONFIG_INSTALL_DIR "${QT_INSTALL_DIR}") + if(QT_CONFIG_INSTALL_DIR) + string(APPEND QT_CONFIG_INSTALL_DIR "/") + endif() + string(APPEND QT_CONFIG_INSTALL_DIR ${__config_path_part}) + + set(QT_BUILD_DIR "${QT_BUILD_DIR}" PARENT_SCOPE) + set(QT_INSTALL_DIR "${QT_INSTALL_DIR}" PARENT_SCOPE) + set(QT_CONFIG_BUILD_DIR "${QT_CONFIG_BUILD_DIR}" PARENT_SCOPE) + set(QT_CONFIG_INSTALL_DIR "${QT_CONFIG_INSTALL_DIR}" PARENT_SCOPE) +endfunction() +qt_internal_set_up_global_paths() +qt_get_relocatable_install_prefix(QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX) + # The variables might have already been set in QtBuildInternalsExtra.cmake if the file is included # while building a new module and not QtBase. In that case, stop overriding the value. if(NOT INSTALL_CMAKE_NAMESPACE) @@ -94,8 +148,11 @@ if(NOT QT_MKSPECS_DIR) if("${QT_BUILD_INTERNALS_PATH}" STREQUAL "") get_filename_component(QT_MKSPECS_DIR "${CMAKE_CURRENT_LIST_DIR}/../mkspecs" ABSOLUTE) else() - # We can rely on CMAKE_INSTALL_PREFIX being set by QtBuildInternalsExtra.cmake - get_filename_component(QT_MKSPECS_DIR "${CMAKE_INSTALL_PREFIX}/${INSTALL_MKSPECSDIR}" ABSOLUTE) + # We can rely on QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX being set by + # QtBuildInternalsExtra.cmake. + get_filename_component( + QT_MKSPECS_DIR + "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${INSTALL_MKSPECSDIR}" ABSOLUTE) endif() set(QT_MKSPECS_DIR "${QT_MKSPECS_DIR}" CACHE INTERNAL "") endif() @@ -138,7 +195,7 @@ function(qt_setup_tool_path_command) if(NOT WIN32) return() endif() - set(bindir "${CMAKE_INSTALL_PREFIX}/${INSTALL_BINDIR}") + set(bindir "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${INSTALL_BINDIR}") file(TO_NATIVE_PATH "${bindir}" bindir) list(APPEND command COMMAND) list(APPEND command set PATH=${bindir}$%PATH%) @@ -305,51 +362,6 @@ else() set(QT_PATH_SEPARATOR ":") endif() -# Compute the values of QT_BUILD_DIR, QT_INSTALL_DIR, QT_CONFIG_BUILD_DIR, QT_CONFIG_INSTALL_DIR -# taking into account whether the current build is a prefix build or a non-prefix build, -# and whether it is a superbuild or non-superbuild. -# A third case is when another module or standalone tests are built against a super-built Qt. -# The layout for the third case is the same as for non-superbuilds. -# -# These values should be prepended to file paths in commands or properties, -# in order to correctly place generated Config files, generated Targets files, -# excutables / libraries, when copying / installing files, etc. -# -# The build dir variables will always be absolute paths. -# The QT_INSTALL_DIR variable will have a relative path in a prefix build, -# which means that it can be empty, so use qt_join_path to prevent accidental absolute paths. -if(QT_SUPERBUILD) - # In this case, we always copy all the build products in qtbase/{bin,lib,...} - if(QT_WILL_INSTALL) - set(QT_BUILD_DIR "${QtBase_BINARY_DIR}") - set(QT_INSTALL_DIR "") - else() - set(QT_BUILD_DIR "${QtBase_BINARY_DIR}") - set(QT_INSTALL_DIR "${QtBase_BINARY_DIR}") - endif() -else() - if(QT_WILL_INSTALL) - # In the usual prefix build case, the build dir is the current module build dir, - # and the install dir is the prefix, so we don't set it. - set(QT_BUILD_DIR "${CMAKE_BINARY_DIR}") - set(QT_INSTALL_DIR "") - else() - # When doing a non-prefix build, both the build dir and install dir are the same, - # pointing to the qtbase build dir. - set(QT_BUILD_DIR "${CMAKE_INSTALL_PREFIX}") - set(QT_INSTALL_DIR "${QT_BUILD_DIR}") - endif() -endif() - -set(__config_path_part "${INSTALL_LIBDIR}/cmake") -set(QT_CONFIG_BUILD_DIR "${QT_BUILD_DIR}/${__config_path_part}") -set(QT_CONFIG_INSTALL_DIR "${QT_INSTALL_DIR}") -if(QT_CONFIG_INSTALL_DIR) - string(APPEND QT_CONFIG_INSTALL_DIR "/") -endif() -string(APPEND QT_CONFIG_INSTALL_DIR ${__config_path_part}) -unset(__config_path_part) - # This is used to hold extra cmake code that should be put into QtBuildInternalsExtra.cmake file # at the QtPostProcess stage. set(QT_BUILD_INTERNALS_EXTRA_CMAKE_CODE "") @@ -848,10 +860,10 @@ function(qt_generate_qt_conf) "[EffectivePaths] Prefix=.. [DevicePaths] -Prefix=${CMAKE_INSTALL_PREFIX} +Prefix=${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX} [Paths] -Prefix=${CMAKE_INSTALL_PREFIX} -HostPrefix=${CMAKE_INSTALL_PREFIX} +Prefix=${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX} +HostPrefix=${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX} Sysroot= SysrootifyPrefix=false TargetSpec=${QT_QMAKE_TARGET_MKSPEC} @@ -1021,7 +1033,7 @@ function(qt_ensure_sync_qt) message(STATUS "Using host syncqt found at: ${QT_SYNCQT}") else() get_filename_component(syncqt_absolute_path - "${CMAKE_INSTALL_PREFIX}/${INSTALL_LIBEXECDIR}/syncqt.pl" + "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${INSTALL_LIBEXECDIR}/syncqt.pl" ABSOLUTE) set(QT_SYNCQT "${syncqt_absolute_path}" CACHE FILEPATH "syncqt script") message(STATUS "Using installed syncqt found at: ${QT_SYNCQT}") @@ -3319,15 +3331,17 @@ function(qt_add_test name) set_tests_properties(${name} PROPERTIES TIMEOUT ${arg_TIMEOUT}) endif() - # Get path to /bin, as well as CMAKE_INSTALL_PREFIX/bin, then + # Get path to /bin, as well as CMAKE_INSTALL_PREFIX/bin, then # prepend them to the PATH environment variable. # It's needed on Windows to find the shared libraries and plugins. - # original_qtbase_install_prefix is the CMAKE_INSTALL_PREFIX specified when building qtbase. + # qt_relocatable_install_prefix is dynamically computed from the location of where the Qt CMake + # package is found. # The regular CMAKE_INSTALL_PREFIX can be different for example when building standalone tests. - # Latest CMAKE_INSTALL_PREFIX takes priority for the PATH environment variable. + # Any given CMAKE_INSTALL_PREFIX takes priority over qt_relocatable_install_prefix for the + # PATH environment variable. set(install_prefixes "${CMAKE_INSTALL_PREFIX}") - if(QT_BUILD_INTERNALS_ORIGINAL_INSTALL_PREFIX) - list(APPEND install_prefixes "${QT_BUILD_INTERNALS_ORIGINAL_INSTALL_PREFIX}") + if(QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX) + list(APPEND install_prefixes "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}") endif() set(test_env_path "PATH=${CMAKE_CURRENT_BINARY_DIR}") @@ -4083,13 +4097,13 @@ function(qt_add_docs) endif() if (NOT QT_SUPERBUILD OR QT_WILL_INSTALL) - set(qdoc_bin "${CMAKE_INSTALL_PREFIX}/${INSTALL_BINDIR}/qdoc") - set(qtattributionsscanner_bin "${CMAKE_INSTALL_PREFIX}/${INSTALL_BINDIR}/qtattributionsscanner") - set(qhelpgenerator_bin "${CMAKE_INSTALL_PREFIX}/${INSTALL_BINDIR}/qhelpgenerator") + set(qdoc_bin "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${INSTALL_BINDIR}/qdoc") + set(qtattributionsscanner_bin "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${INSTALL_BINDIR}/qtattributionsscanner") + set(qhelpgenerator_bin "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${INSTALL_BINDIR}/qhelpgenerator") else() - set(qdoc_bin "${CMAKE_INSTALL_PREFIX}/qtbase/${INSTALL_BINDIR}/qdoc") - set(qtattributionsscanner_bin "${CMAKE_INSTALL_PREFIX}/qtbase/${INSTALL_BINDIR}/qtattributionsscanner") - set(qhelpgenerator_bin "${CMAKE_INSTALL_PREFIX}/qtbase/${INSTALL_BINDIR}/qhelpgenerator") + set(qdoc_bin "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/qtbase/${INSTALL_BINDIR}/qdoc") + set(qtattributionsscanner_bin "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/qtbase/${INSTALL_BINDIR}/qtattributionsscanner") + set(qhelpgenerator_bin "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/qtbase/${INSTALL_BINDIR}/qhelpgenerator") endif() get_target_property(target_type ${target} TYPE) @@ -4122,11 +4136,11 @@ function(qt_add_docs) set(qdoc_output_dir "${CMAKE_BINARY_DIR}/${INSTALL_DOCDIR}/${doc_target}") set(index_dir "${CMAKE_BINARY_DIR}/${INSTALL_DOCDIR}") elseif (QT_SUPERBUILD) - set(qdoc_output_dir "${CMAKE_INSTALL_PREFIX}/qtbase/${INSTALL_DOCDIR}/${doc_target}") - set(index_dir "${CMAKE_INSTALL_PREFIX}/qtbase/${INSTALL_DOCDIR}") + set(qdoc_output_dir "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/qtbase/${INSTALL_DOCDIR}/${doc_target}") + set(index_dir "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/qtbase/${INSTALL_DOCDIR}") else() - set(qdoc_output_dir "${CMAKE_INSTALL_PREFIX}/${INSTALL_DOCDIR}/${doc_target}") - set(index_dir "${CMAKE_INSTALL_PREFIX}/${INSTALL_DOCDIR}") + set(qdoc_output_dir "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${INSTALL_DOCDIR}/${doc_target}") + set(index_dir "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${INSTALL_DOCDIR}") endif() # qtattributionsscanner @@ -4149,10 +4163,12 @@ function(qt_add_docs) "${include_path_args}" ) - if (QT_SUPERBUILD AND NOT QT_WILL_INSTALL) - set(qt_install_docs_env "${CMAKE_INSTALL_PREFIX}/qtbase/${INSTALL_DOCDIR}") - else() + if (QT_WILL_INSTALL) set(qt_install_docs_env "${CMAKE_INSTALL_PREFIX}/${INSTALL_DOCDIR}") + elseif (QT_SUPERBUILD) + set(qt_install_docs_env "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/qtbase/${INSTALL_DOCDIR}") + else() + set(qt_install_docs_env "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${INSTALL_DOCDIR}") endif() set(qdoc_env_args @@ -4560,19 +4576,22 @@ function(qt_generate_qconfig_cpp) # TODO: Clean this up, there's a bunch of unrealistic assumptions here. # See qtConfOutput_preparePaths in qtbase/configure.pri. if(WIN32) - set(lib_location_absolute_path "${CMAKE_INSTALL_PREFIX}/${INSTALL_BINDIR}") + set(lib_location_absolute_path + "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${INSTALL_BINDIR}") else() - set(lib_location_absolute_path "${CMAKE_INSTALL_PREFIX}/${INSTALL_LIBDIR}") + set(lib_location_absolute_path + "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${INSTALL_LIBDIR}") endif() file(RELATIVE_PATH from_lib_location_to_prefix - "${lib_location_absolute_path}" "${CMAKE_INSTALL_PREFIX}") + "${lib_location_absolute_path}" "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}") if(QT_HOST_PATH) set(host_prefix "${QT_HOST_PATH}") set(host_bin_dir_absolute_path "${QT_HOST_PATH}/${INSTALL_BINDIR}") else() - set(host_prefix "${CMAKE_INSTALL_PREFIX}") - set(host_bin_dir_absolute_path "${CMAKE_INSTALL_PREFIX}/${INSTALL_BINDIR}") + set(host_prefix "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}") + set(host_bin_dir_absolute_path + "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${INSTALL_BINDIR}") endif() file(RELATIVE_PATH from_host_bin_dir_to_host_prefix @@ -4581,7 +4600,7 @@ function(qt_generate_qconfig_cpp) # TODO: Fix this to use the equivalent of extprefix on CMake (CMAKE_STAGING_PREFIX?) # For now just assume ext prefix is same as regular prefix. file(RELATIVE_PATH from_host_bin_dir_to_ext_prefix - "${host_bin_dir_absolute_path}" "${CMAKE_INSTALL_PREFIX}") + "${host_bin_dir_absolute_path}" "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}") set(QT_CONFIGURE_LIBLOCATION_TO_PREFIX_PATH "${from_lib_location_to_prefix}") diff --git a/cmake/QtBuildInformation.cmake b/cmake/QtBuildInformation.cmake index 08d49aeba8..784c79a8b0 100644 --- a/cmake/QtBuildInformation.cmake +++ b/cmake/QtBuildInformation.cmake @@ -24,14 +24,14 @@ function(qt_print_build_instructions) message("Qt is now configured for building. Just run '${build_command}'.") if(QT_WILL_INSTALL) message("Once everything is built, you must run '${install_command}'.") - message("Qt will be installed into '${CMAKE_INSTALL_PREFIX}'") + message("Qt will be installed into '${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}'") else() message("Once everything is built, Qt is installed.") message("You should NOT run '${install_command}'") message("Note that this build cannot be deployed to other machines or devices.") endif() message("To configure and build other modules, you can use the following convenience script: - ${CMAKE_INSTALL_PREFIX}/${INSTALL_BINDIR}/qt-cmake") + ${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${INSTALL_BINDIR}/qt-cmake") message("\nIf reconfiguration fails for some reason, try to remove 'CMakeCache.txt' \ from the build directory \n") endfunction() diff --git a/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake b/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake index eb3ff084f9..baf77105b9 100644 --- a/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake +++ b/cmake/QtBuildInternals/QtBuildInternalsConfig.cmake @@ -263,6 +263,40 @@ macro(qt_build_tests) endif() endmacro() +function(qt_compute_relative_path_from_cmake_config_dir_to_prefix) + # Compute the reverse relative path from the CMake config dir to the install prefix. + # This is used in QtBuildInternalsExtras to create a relocatable relative install prefix path. + # This path is used for finding syncqt and other things, regardless of initial install prefix + # (e.g installed Qt was archived and unpacked to a different path on a different machine). + # + # This is meant to be called only once when configuring qtbase. + # + # Similar code exists in Qt6CoreConfigExtras.cmake.in and src/corelib/CMakeLists.txt which + # might not be needed anymore. + if(QT_WILL_INSTALL) + get_filename_component(clean_config_prefix + "${CMAKE_INSTALL_PREFIX}/${QT_CONFIG_INSTALL_DIR}" ABSOLUTE) + else() + get_filename_component(clean_config_prefix "${QT_CONFIG_BUILD_DIR}" ABSOLUTE) + endif() + file(RELATIVE_PATH + qt_path_from_cmake_config_dir_to_prefix + ${clean_config_prefix} ${CMAKE_INSTALL_PREFIX}) + set(qt_path_from_cmake_config_dir_to_prefix "${qt_path_from_cmake_config_dir_to_prefix}" + PARENT_SCOPE) +endfunction() + +function(qt_get_relocatable_install_prefix out_var) + # We need to compute it only once while building qtbase. Afterwards it's loaded from + # QtBuildInternalsExtras.cmake. + if(QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX) + return() + endif() + # The QtBuildInternalsExtras value is dynamically computed, whereas the initial qtbase + # configuration uses an absolute path. + set(${out_var} "${CMAKE_INSTALL_PREFIX}" PARENT_SCOPE) +endfunction() + function(qt_restore_backed_up_install_prefix) # Restore the CMAKE_INSTALL_PREFIX that was set before loading BuildInternals. # Useful for standalone tests, we don't want to accidentally install a test into the Qt prefix. diff --git a/cmake/QtBuildInternalsExtra.cmake.in b/cmake/QtBuildInternalsExtra.cmake.in index ea945a913d..7ab25082c2 100644 --- a/cmake/QtBuildInternalsExtra.cmake.in +++ b/cmake/QtBuildInternalsExtra.cmake.in @@ -5,18 +5,26 @@ set(QT_CMAKE_EXPORT_NAMESPACE @QT_CMAKE_EXPORT_NAMESPACE@) set(INSTALL_CMAKE_NAMESPACE @INSTALL_CMAKE_NAMESPACE@) set(QT_BUILD_INTERNALS_PATH "${CMAKE_CURRENT_LIST_DIR}") -# Propagate the original install prefix, so that a developer building a child module can -# specify CMAKE_PREFIX_PATH for finding the Qt modules instead of CMAKE_INSTALL_PREFIX. -set(CMAKE_INSTALL_PREFIX @CMAKE_INSTALL_PREFIX@ CACHE PATH - "Install path prefix, prepended onto install directories." FORCE) +# The relocatable install prefix is meant to be used to find things like host binaries (syncqt), +# when the CMAKE_INSTALL_PREFIX is overridden to point to a different path (like when building a +# a Qt repo using Conan, which will set a random install prefix instead of installing into the +# original Qt install prefix). +get_filename_component(QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX + ${CMAKE_CURRENT_LIST_DIR}/../@qt_path_from_cmake_config_dir_to_prefix@ + ABSOLUTE) -# Save the original install prefix in an additional variable. -# While CMAKE_INSTALL_PREFIX may be overridden in certain cases (like for standalone tests building -# or for singular qt-cmake-standalone-test usage), we still need the original qtbase install prefix -# to know where the shared libraries are located to inject them into PATH when running tests via -# ctest. -set(QT_BUILD_INTERNALS_ORIGINAL_INSTALL_PREFIX @CMAKE_INSTALL_PREFIX@ CACHE PATH - "Original install prefix specified when building qtbase." FORCE) +# If no explicit CMAKE_INSTALL_PREFIX is provided, force set the original Qt installation prefix, +# so that further modules / repositories are installed into same original location. +# This means by default when configuring qtsvg / qtdeclarative, they will be installed the regular +# Qt installation prefix. +# If an explicit installation prefix is specified, honor it. +# This is an attempt to support Conan, aka handle installation of modules into a +# different installation prefix than the original one. Also allow to opt out via a special variable. +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT AND + NOT QT_BUILD_INTERNALS_NO_FORCE_SET_INSTALL_PREFIX) + set(CMAKE_INSTALL_PREFIX @CMAKE_INSTALL_PREFIX@ CACHE PATH + "Install path prefix, prepended onto install directories." FORCE) +endif() # Propagate developer builds to other modules via BuildInternals package. if(@FEATURE_developer_build@) diff --git a/cmake/QtPostProcess.cmake b/cmake/QtPostProcess.cmake index 9ad7515e53..1434999c06 100644 --- a/cmake/QtPostProcess.cmake +++ b/cmake/QtPostProcess.cmake @@ -382,6 +382,7 @@ function(qt_generate_build_internals_extra_cmake_code) string(APPEND QT_EXTRA_BUILD_INTERNALS_VARS "${install_prefix_content}") + qt_compute_relative_path_from_cmake_config_dir_to_prefix() configure_file( "${CMAKE_CURRENT_LIST_DIR}/QtBuildInternalsExtra.cmake.in" "${extra_file_path}" diff --git a/cmake/QtSetup.cmake b/cmake/QtSetup.cmake index 6bc3c74f69..39142fa332 100644 --- a/cmake/QtSetup.cmake +++ b/cmake/QtSetup.cmake @@ -51,8 +51,8 @@ set(CMAKE_C_VISIBILITY_PRESET hidden) set(CMAKE_CXX_VISIBILITY_PRESET hidden) set(CMAKE_VISIBILITY_INLINES_HIDDEN 1) -# Detect non-prefix builds, either when the install prefix is set to the binary dir -# or when enabling developer builds and no prefix is specified. +# Detect non-prefix builds: either when the qtbase install prefix is set to the binary dir +# or when a developer build is explicitly enabled and no install prefix is specified. # This detection only happens when building qtbase, and later is propagated via the generated # QtBuildInternalsExtra.cmake file. if (PROJECT_NAME STREQUAL "QtBase" AND NOT QT_BUILD_STANDALONE_TESTS) @@ -62,8 +62,8 @@ if (PROJECT_NAME STREQUAL "QtBase" AND NOT QT_BUILD_STANDALONE_TESTS) set(__qt_will_install_value OFF) # Handle non-prefix builds by setting the CMake install prefix to point to qtbase's build # dir. - # While building another repo (like qtsvg), the CMAKE_INSTALL_PREFIX or CMAKE_PREFIX_PATH - # (either work) should be set on the command line to point to the qtbase build dir. + # While building another repo (like qtsvg) the CMAKE_PREFIX_PATH + # should be set on the command line to point to the qtbase build dir. set(CMAKE_INSTALL_PREFIX ${QtBase_BINARY_DIR} CACHE PATH "Install path prefix, prepended onto install directories." FORCE) else() diff --git a/cmake/qt.toolchain.cmake.in b/cmake/qt.toolchain.cmake.in index 63e5ee3d59..d623d9c0fb 100644 --- a/cmake/qt.toolchain.cmake.in +++ b/cmake/qt.toolchain.cmake.in @@ -11,8 +11,14 @@ if(qt_chainload_toolchain_file) unset(qt_chainload_toolchain_file) endif() -list(PREPEND CMAKE_PREFIX_PATH "@CMAKE_INSTALL_PREFIX@") -list(PREPEND CMAKE_FIND_ROOT_PATH "@CMAKE_INSTALL_PREFIX@") +# Compute dynamically the Qt installation prefix from the location of this file. This allows +# the usage of the toolchain file when the Qt installation is relocated. +get_filename_component(QT_TOOLCHAIN_RELOCATABLE_INSTALL_PREFIX + ${CMAKE_CURRENT_LIST_DIR}/../@qt_path_from_cmake_config_dir_to_prefix@ + ABSOLUTE) + +list(PREPEND CMAKE_PREFIX_PATH "${QT_TOOLCHAIN_RELOCATABLE_INSTALL_PREFIX}") +list(PREPEND CMAKE_FIND_ROOT_PATH "${QT_TOOLCHAIN_RELOCATABLE_INSTALL_PREFIX}") if(QT_HOST_PATH) list(APPEND CMAKE_PREFIX_PATH "${QT_HOST_PATH}") diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt index f03d694471..ff28b2d20c 100644 --- a/src/corelib/CMakeLists.txt +++ b/src/corelib/CMakeLists.txt @@ -8,11 +8,13 @@ qt_find_package(WrapPCRE2 PROVIDED_TARGETS WrapPCRE2::WrapPCRE2) # compute the reverse relative path from QtCoreConfigExtras to the install prefix # this is used in QtCoreConfigExtras to make its install paths relocatable if(QT_WILL_INSTALL) - get_filename_component(_clean_prefix "${CMAKE_INSTALL_PREFIX}/${QT_CONFIG_INSTALL_DIR}" ABSOLUTE) + get_filename_component(_clean_prefix + "${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}/${QT_CONFIG_INSTALL_DIR}" ABSOLUTE) else() get_filename_component(_clean_prefix "${QT_CONFIG_BUILD_DIR}" ABSOLUTE) endif() -file(RELATIVE_PATH QT_INVERSE_CONFIG_INSTALL_DIR ${_clean_prefix} ${CMAKE_INSTALL_PREFIX}) +file(RELATIVE_PATH QT_INVERSE_CONFIG_INSTALL_DIR + ${_clean_prefix} ${QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX}) # special case end diff --git a/src/corelib/global/qconfig.cpp.in b/src/corelib/global/qconfig.cpp.in index 7fa21bcfed..6f61f4333c 100644 --- a/src/corelib/global/qconfig.cpp.in +++ b/src/corelib/global/qconfig.cpp.in @@ -1,10 +1,10 @@ /* Installation date */ static const char qt_configure_installation [12+11] = "qt_instdate=2012-12-20"; /* Installation Info */ -static const char qt_configure_prefix_path_str [12+256] = "qt_prfxpath=@CMAKE_INSTALL_PREFIX@"; +static const char qt_configure_prefix_path_str [12+256] = "qt_prfxpath=@QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX@"; #ifdef QT_BUILD_QMAKE -static const char qt_configure_ext_prefix_path_str [12+256] = "qt_epfxpath=@CMAKE_INSTALL_PREFIX@"; -static const char qt_configure_host_prefix_path_str [12+256] = "qt_hpfxpath=@CMAKE_INSTALL_PREFIX@"; +static const char qt_configure_ext_prefix_path_str [12+256] = "qt_epfxpath=@QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX@"; +static const char qt_configure_host_prefix_path_str [12+256] = "qt_hpfxpath=@QT_BUILD_INTERNALS_RELOCATABLE_INSTALL_PREFIX@"; #endif static const short qt_configure_str_offsets[] = { @QT_CONFIG_STR_OFFSETS_FIRST@