2023-04-28 21:02:53 +01:00
|
|
|
# Bundles libraries with an output executable.
|
|
|
|
# Parameters:
|
|
|
|
# - TYPE: "qt" or "standalone". The type of app to bundle.
|
|
|
|
# - "qt" uses windeployqt/macdeployqt to bundle Qt and other libraries.
|
|
|
|
# - "standalone" copies dependent libraries to a "libs" folder alongside the executable file.
|
|
|
|
# - EXECUTABLE_PATH: Path to the executable binary.
|
|
|
|
|
|
|
|
# TODO: This does not really work fully for Windows yet, some libraries are missing from the output.
|
|
|
|
# TODO: Leaving a basic framework of Windows support here to be iterated on in the future.
|
|
|
|
if (WIN32)
|
|
|
|
message(FATAL_ERROR "Advanced library bundling is not yet supported for Windows.")
|
|
|
|
endif()
|
|
|
|
|
|
|
|
if ("${TYPE}" STREQUAL "qt")
|
|
|
|
get_filename_component(executable_dir ${EXECUTABLE_PATH} DIRECTORY)
|
|
|
|
|
|
|
|
# Bundle dependencies using appropriate Qt tool.
|
|
|
|
if (WIN32)
|
|
|
|
find_program(WINDEPLOYQT_EXECUTABLE windeployqt)
|
|
|
|
execute_process(COMMAND ${WINDEPLOYQT_EXECUTABLE} ${EXECUTABLE_PATH}
|
|
|
|
--no-compiler-runtime --no-system-d3d-compiler --no-opengl-sw --no-translations
|
|
|
|
--plugindir "${executable_dir}/plugins")
|
|
|
|
elseif (APPLE)
|
|
|
|
get_filename_component(contents_dir ${executable_dir} DIRECTORY)
|
|
|
|
get_filename_component(bundle_dir ${contents_dir} DIRECTORY)
|
|
|
|
|
|
|
|
find_program(MACDEPLOYQT_EXECUTABLE macdeployqt)
|
|
|
|
execute_process(COMMAND ${MACDEPLOYQT_EXECUTABLE} ${bundle_dir} -executable=${EXECUTABLE_PATH} -always-overwrite)
|
2023-05-11 20:47:18 +01:00
|
|
|
|
|
|
|
# Bundling libraries can rewrite path information and break code signatures of system libraries.
|
|
|
|
# Perform an ad-hoc re-signing on the whole app bundle to fix this.
|
|
|
|
execute_process(COMMAND codesign --deep -fs - ${bundle_dir})
|
2023-04-28 21:02:53 +01:00
|
|
|
else()
|
|
|
|
message(FATAL_ERROR "Unsupported OS for Qt-based library bundling.")
|
|
|
|
endif()
|
|
|
|
else()
|
|
|
|
# Resolve dependent library files.
|
|
|
|
file(GET_RUNTIME_DEPENDENCIES
|
|
|
|
EXECUTABLES ${EXECUTABLE_PATH}
|
|
|
|
RESOLVED_DEPENDENCIES_VAR resolved_deps
|
|
|
|
UNRESOLVED_DEPENDENCIES_VAR unresolved_deps
|
|
|
|
POST_EXCLUDE_REGEXES ".*system32/.*\\.dll")
|
|
|
|
|
|
|
|
# Determine libraries directory.
|
|
|
|
get_filename_component(executable_dir ${EXECUTABLE_PATH} DIRECTORY)
|
|
|
|
if (WIN32)
|
|
|
|
# Same directory since we don't have rpath.
|
|
|
|
set(lib_dir ${executable_dir})
|
|
|
|
else()
|
|
|
|
set(lib_dir ${executable_dir}/libs)
|
|
|
|
endif()
|
|
|
|
|
|
|
|
# Copy library files to bundled output.
|
|
|
|
file(MAKE_DIRECTORY ${lib_dir})
|
|
|
|
foreach (lib_file ${resolved_deps})
|
|
|
|
# Use native copy to turn symlinks into normal files.
|
|
|
|
execute_process(COMMAND cp -L ${lib_file} ${lib_dir})
|
|
|
|
endforeach()
|
|
|
|
|
|
|
|
# Add libs directory to executable rpath where applicable.
|
|
|
|
if (APPLE)
|
|
|
|
execute_process(COMMAND install_name_tool -add_rpath "@loader_path/libs" ${EXECUTABLE_PATH})
|
|
|
|
elseif (UNIX)
|
|
|
|
execute_process(COMMAND patchelf --set-rpath '$ORIGIN/../libs' ${EXECUTABLE_PATH})
|
|
|
|
endif()
|
|
|
|
endif()
|