build: Improvements to bundled libraries support. (#6435)
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# To use this as a script, make sure you pass in the variables SRC_DIR BUILD_DIR and TARGET_FILE
|
||||
# To use this as a script, make sure you pass in the variables BASE_DIR, SRC_DIR, BUILD_DIR, and TARGET_FILE
|
||||
|
||||
if(WIN32)
|
||||
set(PLATFORM "windows")
|
||||
@@ -10,29 +10,15 @@ else()
|
||||
message(FATAL_ERROR "Cannot build installer for this unsupported platform")
|
||||
endif()
|
||||
|
||||
set(DIST_DIR "${BUILD_DIR}/dist")
|
||||
set(ARCHIVE "${PLATFORM}.7z")
|
||||
list(APPEND CMAKE_MODULE_PATH "${BASE_DIR}/CMakeModules")
|
||||
include(DownloadExternals)
|
||||
download_qt_external(tools_ifw QT_PREFIX)
|
||||
|
||||
file(MAKE_DIRECTORY ${BUILD_DIR})
|
||||
file(MAKE_DIRECTORY ${DIST_DIR})
|
||||
file(DOWNLOAD https://github.com/citra-emu/ext-windows-bin/raw/master/qtifw/${ARCHIVE}
|
||||
"${BUILD_DIR}/${ARCHIVE}" SHOW_PROGRESS)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf "${BUILD_DIR}/${ARCHIVE}"
|
||||
WORKING_DIRECTORY "${BUILD_DIR}/")
|
||||
file(GLOB_RECURSE INSTALLER_BASE "${QT_PREFIX}/**/installerbase*")
|
||||
file(GLOB_RECURSE BINARY_CREATOR "${QT_PREFIX}/**/binarycreator*")
|
||||
|
||||
set(TARGET_NAME "citra-setup-${PLATFORM}")
|
||||
set(CONFIG_FILE "${SRC_DIR}/config/config_${PLATFORM}.xml")
|
||||
set(INSTALLER_BASE "${BUILD_DIR}/installerbase_${PLATFORM}")
|
||||
set(BINARY_CREATOR "${BUILD_DIR}/binarycreator_${PLATFORM}")
|
||||
set(PACKAGES_DIR "${BUILD_DIR}/packages")
|
||||
file(MAKE_DIRECTORY ${PACKAGES_DIR})
|
||||
|
||||
if (UNIX OR APPLE)
|
||||
execute_process(COMMAND chmod 744 ${BINARY_CREATOR})
|
||||
endif()
|
||||
|
||||
execute_process(COMMAND ${BINARY_CREATOR} -t ${INSTALLER_BASE} -n -c ${CONFIG_FILE} -p ${PACKAGES_DIR} ${TARGET_FILE})
|
||||
|
||||
if (APPLE)
|
||||
execute_process(COMMAND chmod 744 ${TARGET_FILE}.app/Contents/MacOS/${TARGET_NAME})
|
||||
endif()
|
||||
|
62
CMakeModules/BundleLibraries.cmake
Normal file
62
CMakeModules/BundleLibraries.cmake
Normal file
@@ -0,0 +1,62 @@
|
||||
# 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)
|
||||
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()
|
@@ -4,15 +4,95 @@
|
||||
# remote_path: path to the file to download, relative to the remote repository root
|
||||
# prefix_var: name of a variable which will be set with the path to the extracted contents
|
||||
function(download_bundled_external remote_path lib_name prefix_var)
|
||||
set(prefix "${CMAKE_BINARY_DIR}/externals/${lib_name}")
|
||||
if (NOT EXISTS "${prefix}")
|
||||
message(STATUS "Downloading binaries for ${lib_name}...")
|
||||
file(DOWNLOAD
|
||||
https://github.com/citra-emu/ext-windows-bin/raw/master/${remote_path}${lib_name}.7z
|
||||
"${CMAKE_BINARY_DIR}/externals/${lib_name}.7z" SHOW_PROGRESS)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf "${CMAKE_BINARY_DIR}/externals/${lib_name}.7z"
|
||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/externals")
|
||||
endif()
|
||||
message(STATUS "Using bundled binaries at ${prefix}")
|
||||
set(${prefix_var} "${prefix}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
get_external_prefix(${lib_name} prefix)
|
||||
if (NOT EXISTS "${prefix}")
|
||||
message(STATUS "Downloading binaries for ${lib_name}...")
|
||||
|
||||
if (WIN32)
|
||||
set(repo_base "ext-windows-bin/raw/master")
|
||||
elseif (APPLE)
|
||||
set(repo_base "ext-macos-bin/raw/main")
|
||||
else()
|
||||
message(FATAL_ERROR "Bundled libraries are unsupported for this OS.")
|
||||
endif()
|
||||
|
||||
file(DOWNLOAD
|
||||
https://github.com/citra-emu/${repo_base}/${remote_path}${lib_name}.7z
|
||||
"${CMAKE_BINARY_DIR}/externals/${lib_name}.7z" SHOW_PROGRESS)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E tar xf "${CMAKE_BINARY_DIR}/externals/${lib_name}.7z"
|
||||
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/externals")
|
||||
endif()
|
||||
|
||||
# For packages that include the /usr/local prefix, include it in the prefix path.
|
||||
if (EXISTS "${prefix}/usr/local")
|
||||
set(prefix "${prefix}/usr/local")
|
||||
endif()
|
||||
|
||||
message(STATUS "Using bundled binaries at ${prefix}")
|
||||
set(${prefix_var} "${prefix}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# This function downloads Qt using aqt.
|
||||
# Params:
|
||||
# target: Qt dependency to install. Specify a version number to download Qt, or "tools_(name)" for a specific build tool.
|
||||
# prefix_var: Name of a variable which will be set with the path to the extracted contents.
|
||||
function(download_qt_external target prefix_var)
|
||||
# Determine installation parameters for OS, architecture, and compiler
|
||||
if (WIN32)
|
||||
set(host "windows")
|
||||
if (MINGW)
|
||||
set(arch_path "mingw81")
|
||||
elseif ((MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1940) AND "x86_64" IN_LIST ARCHITECTURE)
|
||||
if ("arm64" IN_LIST ARCHITECTURE)
|
||||
set(arch_path "msvc2019_arm64")
|
||||
elseif ("x86_64" IN_LIST ARCHITECTURE)
|
||||
set(arch_path "msvc2019_64")
|
||||
else()
|
||||
message(FATAL_ERROR "Unsupported bundled Qt architecture. Disable CITRA_USE_BUNDLED_QT and provide your own.")
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "Unsupported bundled Qt toolchain. Disable CITRA_USE_BUNDLED_QT and provide your own.")
|
||||
endif()
|
||||
set(arch "win64_${arch_path}")
|
||||
elseif (APPLE)
|
||||
set(host "mac")
|
||||
set(arch "clang_64")
|
||||
set(arch_path "macos")
|
||||
else()
|
||||
set(host "linux")
|
||||
set(arch "gcc_64")
|
||||
set(arch_path "linux")
|
||||
endif()
|
||||
|
||||
get_external_prefix(qt base_path)
|
||||
if (target MATCHES "tools_.*")
|
||||
set(prefix "${base_path}")
|
||||
set(install_args install-tool --outputdir ${base_path} ${host} desktop ${target})
|
||||
else()
|
||||
set(prefix "${base_path}/${target}/${arch_path}")
|
||||
set(install_args install-qt --outputdir ${base_path} ${host} desktop ${target} ${arch})
|
||||
endif()
|
||||
|
||||
if (NOT EXISTS "${prefix}")
|
||||
message(STATUS "Downloading binaries for Qt...")
|
||||
if (WIN32)
|
||||
set(aqt_path "${CMAKE_BINARY_DIR}/externals/aqt.exe")
|
||||
file(DOWNLOAD
|
||||
https://github.com/miurahr/aqtinstall/releases/download/v3.1.4/aqt.exe
|
||||
${aqt_path} SHOW_PROGRESS)
|
||||
execute_process(COMMAND ${aqt_path} ${install_args})
|
||||
else()
|
||||
# aqt does not offer binary releases for other platforms, so download and run from pip.
|
||||
set(aqt_install_path "${CMAKE_BINARY_DIR}/externals/aqt")
|
||||
execute_process(COMMAND python3 -m pip install --target=${aqt_install_path} aqtinstall)
|
||||
execute_process(COMMAND ${CMAKE_COMMAND} -E env PYTHONPATH=${aqt_install_path} python3 -m aqt ${install_args})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
message(STATUS "Using downloaded Qt binaries at ${prefix}")
|
||||
set(${prefix_var} "${prefix}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(get_external_prefix lib_name prefix_var)
|
||||
set(${prefix_var} "${CMAKE_BINARY_DIR}/externals/${lib_name}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
Reference in New Issue
Block a user