Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Windeployqt.cmake multi-config generator support #274

Open
JohannesWilde opened this issue Aug 24, 2023 · 1 comment
Open

Windeployqt.cmake multi-config generator support #274

JohannesWilde opened this issue Aug 24, 2023 · 1 comment

Comments

@JohannesWilde
Copy link

I came here from the great article Using windeployqt with CPack. I tried to incorporate it into my own project - which I also want to build using MSVC.

The MSVC generator complained during generation for "${CMAKE_CURRENT_BINARY_DIR}/${target}_path" that file to be written multiple times with different content.

One possible solution seemed to have been to use "${CMAKE_CURRENT_BINARY_DIR}/${target}_$<CONFIG>_path" instead - with the current CMake version requirement of 3.2 however the corresponding command in install(Code can't use this generator expression either. A first try using ${CMAKE_BUILD_TYPE} for the install(Code seemed to work. But I couldn't quite find out, whether this was arbitrary or should always be the case.

My solution then was to up the CMake version requirement to 3.14 [or enfore CMP0087 to be NEW]. This allowed me to use generator-expressions in the install(Code command and therefore enables one to get rid of the temporary "${CMAKE_CURRENT_BINARY_DIR}/${target}_path".

Would it be possible to update the Windeployqt.cmake in this repo as well? It would require a newer CMake version however...

Attached are my patches for Windeployqt.cmake:

patch_codeInstallGeneratorExpression.patch
patch_versionCheck.patch


# The MIT License (MIT)
#
# Copyright (c) 2017 Nathan Osman
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

find_package(Qt5Core REQUIRED)

# Retrieve the absolute path to qmake and then use that path to find
# the windeployqt binary
get_target_property(_qmake_executable Qt5::qmake IMPORTED_LOCATION)
get_filename_component(_qt_bin_dir "${_qmake_executable}" DIRECTORY)
find_program(WINDEPLOYQT_EXECUTABLE windeployqt HINTS "${_qt_bin_dir}")

# Running this with MSVC 2015 requires CMake 3.6+
if((MSVC_VERSION VERSION_EQUAL 1900 OR MSVC_VERSION VERSION_GREATER 1900)
        AND CMAKE_VERSION VERSION_LESS "3.6")
    message(WARNING "Deploying with MSVC 2015+ requires CMake 3.6+")
endif()

# Add commands that copy the Qt runtime to the target's output directory after
# build and install the Qt runtime to the specified directory
function(windeployqt target directory)

    if (CMAKE_VERSION VERSION_LESS "3.14")
        message(FATAL_ERROR "Windeployqt.cmake requires at least CMake 3.14.")
    else ()
        cmake_policy(GET CMP0087 CMP0087_VALUE)

        if (NOT "${CMP0087_VALUE}" STREQUAL "NEW")
            # As to use Generator-expressions in install(Code) CMP0087 needs to be new.
            # The use of a generator-expression is required especially for Multi-Config-Generators.
            message(FATAL_ERROR "Windeployqt.cmake requires CMP0087 to be set to NEW [it is \"${CMP0087_VALUE}\"].")
        endif ()

        unset(CMP0087_VALUE)
    endif ()

    # Run windeployqt immediately after build
    add_custom_command(TARGET ${target} POST_BUILD
        COMMAND "${CMAKE_COMMAND}" -E
            env PATH="${_qt_bin_dir}" "${WINDEPLOYQT_EXECUTABLE}"
                --verbose 0
                --no-compiler-runtime
                --no-angle
                --no-opengl-sw
                \"$<TARGET_FILE:${target}>\"
    )

    # Before installation, run a series of commands that copy each of the Qt
    # runtime files to the appropriate directory for installation
    install(CODE
        "
        execute_process(
            COMMAND \"${CMAKE_COMMAND}\" -E
                env PATH=\"${_qt_bin_dir}\" \"${WINDEPLOYQT_EXECUTABLE}\"
                    --dry-run
                    --no-compiler-runtime
                    --no-angle
                    --no-opengl-sw
                    --list mapping
                    \"$<TARGET_FILE:${target}>\"
            OUTPUT_VARIABLE _output
            OUTPUT_STRIP_TRAILING_WHITESPACE
        )
        separate_arguments(_files WINDOWS_COMMAND \${_output})
        while(_files)
            list(GET _files 0 _src)
            list(GET _files 1 _dest)
            execute_process(
                COMMAND \"${CMAKE_COMMAND}\" -E
                    copy \${_src} \"\${CMAKE_INSTALL_PREFIX}/${directory}/\${_dest}\"
            )
            list(REMOVE_AT _files 0 1)
        endwhile()
        "
    )

    # windeployqt doesn't work correctly with the system runtime libraries,
    # so we fall back to one of CMake's own modules for copying them over
    set(CMAKE_INSTALL_UCRT_LIBRARIES TRUE)
    include(InstallRequiredSystemLibraries)
    foreach(lib ${CMAKE_INSTALL_SYSTEM_RUNTIME_LIBS})
        get_filename_component(filename "${lib}" NAME)
        add_custom_command(TARGET ${target} POST_BUILD
            COMMAND "${CMAKE_COMMAND}" -E
                copy_if_different "${lib}" \"$<TARGET_FILE_DIR:${target}>\"
        )
    endforeach()

endfunction()

mark_as_advanced(WINDEPLOYQT_EXECUTABLE)

@aiyolo
Copy link

aiyolo commented Sep 16, 2024

This patch is useful, thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants