Skip to content

Commit

Permalink
Run macdeployqt only once at install time
Browse files Browse the repository at this point in the history
Instead of running macdeployqt once for each extra helper binary and
plugin (plus the main run for the application itself), collect all the
binaries that should be processed and run macdeloyqt only once after
all the binaries have been installed.

This also moves the main app macdeployqt call from a POST_BUILD step
to an install(CODE) step, making increment rebuilds of the app faster.

To ensure that macdeployqt is called after all the binaries are
installed, a new post_install subdirectory is needed to
circumvent CMake's limitation regarding the default order of
installation.
CMake first runs the current directory install() calls and then it's
child subdirectory ones. Because we want macdeployqt to be the last
install() call, it needs to be done inside a subdirectory that is
added last.

Note due to a bug in macdeployqt, the deployed app inside the .dmg
file will fail to run on arm macs, due to broken code signature.
See https://bugreports.qt.io/browse/QTBUG-101696 for details.

For the final release, the release-tool should take care of proper
resigning.
  • Loading branch information
alcroito authored and phoerious committed Mar 20, 2022
1 parent 60f7744 commit ab153a2
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 47 deletions.
3 changes: 2 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
# Support Visual Studio Code
include(CMakeToolsHelpers OPTIONAL)
include(FeatureSummary)
include(KPXCHelpers)
include(KPXCMacDeployHelpers)

include(CheckCCompilerFlag)
include(CheckCXXCompilerFlag)
Expand Down Expand Up @@ -476,6 +476,7 @@ if(APPLE)
message(FATAL_ERROR "macdeployqt is required to build on macOS")
endif()
message(STATUS "Using macdeployqt: ${MACDEPLOYQT_EXE}")
set(MACDEPLOYQT_EXTRA_BINARIES "")
elseif(WIN32)
find_program(WINDEPLOYQT_EXE windeployqt HINTS ${Qt5_PREFIX}/bin ${Qt5_PREFIX}/tools/qt5/bin ENV PATH)
if(NOT WINDEPLOYQT_EXE)
Expand Down
33 changes: 0 additions & 33 deletions cmake/KPXCHelpers.cmake

This file was deleted.

61 changes: 61 additions & 0 deletions cmake/KPXCMacDeployHelpers.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Running macdeployqt on a POST_BUILD copied binaries is pointless when using CPack because
# the copied binaries will be overriden by the corresponding install(TARGETS) commands.
# That's why we run macdeployqt using install(CODE) on the already installed binaries.
# The precondition is that all install(TARGETS) calls have to be called before this function is
# called.
# macdeloyqt is called only once, but it is given all executables that should be processed.
function(kpxc_run_macdeployqt_at_install_time)
set(NO_VALUE_OPTIONS)
set(SINGLE_VALUE_OPTIONS
APP_NAME
)
set(MULTI_VALUE_OPTIONS
EXTRA_BINARIES
)
cmake_parse_arguments(PARSE_ARGV 0 ARG
"${NO_VALUE_OPTIONS}" "${SINGLE_VALUE_OPTIONS}" "${MULTI_VALUE_OPTIONS}"
)

set(ESCAPED_PREFIX "\${CMAKE_INSTALL_PREFIX}")
set(APP_BUNDLE_NAME "${ARG_APP_NAME}.app")
set(APP_BUNDLE_PATH "${ESCAPED_PREFIX}/${APP_BUNDLE_NAME}")

# Collect extra binaries and plugins that should be handled by macdpeloyqt.
set(EXTRA_BINARIES "")
foreach(EXTRA_BINARY ${ARG_EXTRA_BINARIES})
set(INSTALLED_BINARY_PATH "${ESCAPED_PREFIX}/${EXTRA_BINARY}")
list(APPEND EXTRA_BINARIES "-executable=${INSTALLED_BINARY_PATH}")
endforeach()

list(JOIN EXTRA_BINARIES " " EXTRA_BINARIES_STR)

if(CMAKE_VERSION VERSION_GREATER "3.14")
set(COMMAND_ECHO "COMMAND_ECHO STDOUT")
else()
set(COMMAND_ECHO "")
endif()

set(COMMAND_ARGS
${MACDEPLOYQT_EXE}
${APP_BUNDLE_PATH}

# Adjusts dependency rpaths of extra binaries
${EXTRA_BINARIES_STR}

# Silences warnings on subsequent re-installations
-always-overwrite
)

install(CODE
"
execute_process(
COMMAND ${COMMAND_ARGS}
${COMMAND_ECHO}
RESULT_VARIABLE EXIT_CODE
)
if(NOT EXIT_CODE EQUAL 0)
message(FATAL_ERROR
\"Running ${COMMAND_ARGS} failed with exit code \${EXIT_CODE}.\")
endif()
")
endfunction()
10 changes: 4 additions & 6 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -409,12 +409,6 @@ if(APPLE AND WITH_APP_BUNDLE)
set(CPACK_STRIP_FILES ON)
set(CPACK_PACKAGE_FILE_NAME "${PROGNAME}-${KEEPASSXC_VERSION}")
include(CPack)

add_custom_command(TARGET ${PROGNAME}
POST_BUILD
COMMAND ${MACDEPLOYQT_EXE} ${PROGNAME}.app 2> /dev/null
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src
COMMENT "Deploying app bundle")
endif()

install(TARGETS ${PROGNAME}
Expand Down Expand Up @@ -530,3 +524,7 @@ if(WIN32)
endif()

endif()

# The install commands in this subdirectory will be executed after all the install commands in the
# current scope are ran. It is required for correct functtioning of macdeployqt.
add_subdirectory(post_install)
4 changes: 2 additions & 2 deletions src/autotype/mac/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@ if(WITH_APP_BUNDLE)
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src
COMMENT "Copying autotype plugin into app bundle")

kpxc_run_macdeployqt_on_installed_helper_binary(
"${PROGNAME}" "${PLUGIN_INSTALL_DIR}/libkeepassxc-autotype-cocoa.so")
set_property(GLOBAL APPEND PROPERTY
_MACDEPLOYQT_EXTRA_BINARIES "${PLUGIN_INSTALL_DIR}/libkeepassxc-autotype-cocoa.so")
endif()
5 changes: 2 additions & 3 deletions src/cli/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ if(APPLE AND WITH_APP_BUNDLE)
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_BINARY_DIR}/keepassxc-cli ${CLI_APP_DIR}/keepassxc-cli
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src
COMMENT "Copying keepassxc-cli into app bundle")

kpxc_run_macdeployqt_on_installed_helper_binary(
"${PROGNAME}" "${CLI_INSTALL_DIR}/keepassxc-cli")
set_property(GLOBAL APPEND PROPERTY
_MACDEPLOYQT_EXTRA_BINARIES "${CLI_INSTALL_DIR}/keepassxc-cli")
endif()
13 changes: 13 additions & 0 deletions src/post_install/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# The install commands in this subdirectory will be executed after all the install commands in the
# current scope are ran. It is required for correct functtioning of macdeployqt.

if(APPLE AND WITH_APP_BUNDLE)
# Run macdeloyqt on the main app and any extra binaries and plugins as specified by the
# _MACDEPLOYQT_EXTRA_BINARIES global property.
# All install(TARGETS) calls should have already been called.
get_property(MACDEPLOYQT_EXTRA_BINARIES GLOBAL PROPERTY _MACDEPLOYQT_EXTRA_BINARIES)
kpxc_run_macdeployqt_at_install_time(
APP_NAME "${PROGNAME}"
EXTRA_BINARIES ${MACDEPLOYQT_EXTRA_BINARIES}
)
endif()
4 changes: 2 additions & 2 deletions src/proxy/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ if(WITH_XC_BROWSER)
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/src
COMMENT "Copying keepassxc-proxy into app bundle")

kpxc_run_macdeployqt_on_installed_helper_binary(
"${PROGNAME}" "${PROXY_INSTALL_DIR}/keepassxc-proxy")
set_property(GLOBAL APPEND PROPERTY
_MACDEPLOYQT_EXTRA_BINARIES "${PROXY_INSTALL_DIR}/keepassxc-proxy")
endif()

if(WIN32)
Expand Down

0 comments on commit ab153a2

Please sign in to comment.