mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-07-23 05:32:42 -04:00
440 lines
20 KiB
CMake
440 lines
20 KiB
CMake
# add_mod(<target> [FEATURES <feature>...] SOURCES <file>... MOD_JSON <mod.json>
|
|
# [RUNTIME_LIBRARIES <file>...] [RES_DIR <res>] [OVERLAY_DIR <overlay>]
|
|
# [TEXTURES_DIR <textures>] [OUTPUT_DIR <dir>] [BUNDLE])
|
|
set(DUSK_MODS_OUTPUT_DIR "${CMAKE_BINARY_DIR}/mods" CACHE PATH "Directory to write mod packages into")
|
|
set(DUSKLIGHT_SDK_STUB_URL "https://github.com/encounter/dusklight/releases/download/sdk"
|
|
CACHE STRING "Base URL for game link stubs downloaded by out-of-tree mod builds")
|
|
|
|
function(_mod_lib_info out_platform_var out_name_var)
|
|
set(_arch "${CMAKE_SYSTEM_PROCESSOR}")
|
|
if (APPLE AND CMAKE_OSX_ARCHITECTURES)
|
|
list(LENGTH CMAKE_OSX_ARCHITECTURES _count)
|
|
if (_count GREATER 1)
|
|
message(FATAL_ERROR "add_mod: universal binaries are not supported")
|
|
endif ()
|
|
set(_arch "${CMAKE_OSX_ARCHITECTURES}")
|
|
endif ()
|
|
string(TOLOWER "${CMAKE_SYSTEM_NAME}" _platform)
|
|
if (_platform STREQUAL "darwin")
|
|
set(_platform "macos")
|
|
endif ()
|
|
string(TOLOWER "${_arch}" _arch)
|
|
if (_arch MATCHES "^(i[3-6]86|x86)$")
|
|
set(_arch "x86")
|
|
endif ()
|
|
if (WIN32)
|
|
set(_ext ".dll")
|
|
else ()
|
|
set(_ext ".so")
|
|
endif ()
|
|
set(${out_platform_var} "${_platform}-${_arch}" PARENT_SCOPE)
|
|
set(${out_name_var} "mod${_ext}" PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
# For out-of-tree builds without a game binary: download the version-independent link stub
|
|
# (generated by symgen) for the target platform.
|
|
function(_mod_download_link_stub out_var)
|
|
_mod_lib_info(_platform _lib_name)
|
|
if (WIN32)
|
|
set(_asset "${_platform}.lib")
|
|
elseif (ANDROID)
|
|
set(_asset "stub-${_platform}.so")
|
|
else ()
|
|
set(_asset "stub-${_platform}")
|
|
endif ()
|
|
set(_stub "${CMAKE_BINARY_DIR}/dusklight-sdk-stubs/${_asset}")
|
|
if (NOT EXISTS "${_stub}")
|
|
message(STATUS "Mod SDK: downloading link stub ${_asset}")
|
|
file(DOWNLOAD "${DUSKLIGHT_SDK_STUB_URL}/${_asset}" "${_stub}.tmp" STATUS _status)
|
|
list(GET _status 0 _code)
|
|
if (NOT _code EQUAL 0)
|
|
list(GET _status 1 _error)
|
|
file(REMOVE "${_stub}.tmp")
|
|
message(FATAL_ERROR
|
|
"Mod SDK: failed to download ${DUSKLIGHT_SDK_STUB_URL}/${_asset}: ${_error}\n"
|
|
"Set DUSK_GAME_EXE to a game binary or link stub to skip the download.")
|
|
endif ()
|
|
file(RENAME "${_stub}.tmp" "${_stub}")
|
|
endif ()
|
|
set(${out_var} "${_stub}" PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
function(_mod_resolve_source_path out_var path)
|
|
if (IS_ABSOLUTE "${path}")
|
|
set(_path "${path}")
|
|
else ()
|
|
set(_path "${CMAKE_CURRENT_SOURCE_DIR}/${path}")
|
|
endif ()
|
|
set(${out_var} "${_path}" PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
function(_mod_collect_assets out_var dir)
|
|
if (NOT IS_DIRECTORY "${dir}")
|
|
message(FATAL_ERROR "add_mod: asset directory does not exist: ${dir}")
|
|
endif ()
|
|
|
|
file(GLOB_RECURSE _files CONFIGURE_DEPENDS LIST_DIRECTORIES false "${dir}/*")
|
|
set(${out_var} ${_files} PARENT_SCOPE)
|
|
endfunction()
|
|
|
|
function(_mod_add_webgpu_headers target_name)
|
|
if (NOT TARGET dawn::dawncpp_headers AND NOT TARGET dawn::webgpu_dawn)
|
|
include("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../extern/aurora/cmake/AuroraDependencyVersions.cmake")
|
|
set(AURORA_DAWN_PROVIDER "package" CACHE STRING "How to provide Dawn for the mod SDK")
|
|
include("${CMAKE_CURRENT_FUNCTION_LIST_DIR}/../extern/aurora/cmake/AuroraDawnProvider.cmake")
|
|
endif ()
|
|
|
|
if (TARGET dawn::dawncpp_headers)
|
|
target_link_libraries(${target_name} PRIVATE dawn::dawncpp_headers)
|
|
elseif (TARGET dawn::webgpu_dawn)
|
|
target_link_libraries(${target_name} PRIVATE dawn::webgpu_dawn)
|
|
else ()
|
|
message(FATAL_ERROR "add_mod: FEATURES webgpu could not provide WebGPU headers")
|
|
endif ()
|
|
endfunction()
|
|
|
|
function(add_mod target_name)
|
|
cmake_parse_arguments(ARG "BUNDLE" "MOD_JSON;RES_DIR;OVERLAY_DIR;TEXTURES_DIR;OUTPUT_DIR"
|
|
"SOURCES;RUNTIME_LIBRARIES;FEATURES" ${ARGN})
|
|
if (ARG_UNPARSED_ARGUMENTS)
|
|
message(FATAL_ERROR "add_mod: unknown arguments: ${ARG_UNPARSED_ARGUMENTS}")
|
|
endif ()
|
|
if (NOT ARG_MOD_JSON)
|
|
message(FATAL_ERROR "add_mod: MOD_JSON is required")
|
|
endif ()
|
|
_mod_resolve_source_path(_mod_json "${ARG_MOD_JSON}")
|
|
if (NOT EXISTS "${_mod_json}")
|
|
message(FATAL_ERROR "add_mod: MOD_JSON does not exist: ${_mod_json}")
|
|
endif ()
|
|
|
|
set(_supported_features game webgpu)
|
|
set(_features "")
|
|
foreach (_feature IN LISTS ARG_FEATURES)
|
|
list(FIND _supported_features "${_feature}" _feature_index)
|
|
if (_feature_index EQUAL -1)
|
|
list(JOIN _supported_features ", " _supported_features_text)
|
|
message(FATAL_ERROR
|
|
"add_mod: unknown feature '${_feature}' (supported: ${_supported_features_text})")
|
|
endif ()
|
|
list(FIND _features "${_feature}" _duplicate_index)
|
|
if (NOT _duplicate_index EQUAL -1)
|
|
message(FATAL_ERROR "add_mod: duplicate feature '${_feature}'")
|
|
endif ()
|
|
list(APPEND _features "${_feature}")
|
|
endforeach ()
|
|
if (_features AND NOT ARG_SOURCES)
|
|
message(FATAL_ERROR "add_mod: FEATURES requires SOURCES")
|
|
endif ()
|
|
|
|
set(_has_lib FALSE)
|
|
set(_needs_host_link FALSE)
|
|
set(_lib_platform "")
|
|
set(_lib_name "")
|
|
if (ARG_SOURCES)
|
|
set(_has_lib TRUE)
|
|
add_library(${target_name} MODULE ${ARG_SOURCES})
|
|
_mod_lib_info(_lib_platform _lib_name)
|
|
set_target_properties(${target_name} PROPERTIES
|
|
PREFIX ""
|
|
C_VISIBILITY_PRESET hidden
|
|
CXX_VISIBILITY_PRESET hidden
|
|
VISIBILITY_INLINES_HIDDEN ON
|
|
WINDOWS_EXPORT_ALL_SYMBOLS OFF)
|
|
target_compile_features(${target_name} PRIVATE cxx_std_20)
|
|
target_link_libraries(${target_name} PRIVATE dusklight_mod_api)
|
|
foreach (_feature IN LISTS _features)
|
|
target_link_libraries(${target_name} PRIVATE dusklight_mod_feature_${_feature})
|
|
if (_feature STREQUAL "webgpu")
|
|
_mod_add_webgpu_headers(${target_name})
|
|
endif ()
|
|
if (_feature STREQUAL "game" OR _feature STREQUAL "webgpu")
|
|
set(_needs_host_link TRUE)
|
|
endif ()
|
|
endforeach ()
|
|
|
|
if (NOT TARGET dusklight)
|
|
# Apply global compile options for out-of-tree mod builds
|
|
if (CMAKE_SYSTEM_NAME STREQUAL Linux)
|
|
target_compile_options(${target_name} PRIVATE
|
|
-Wno-multichar -Wno-trigraphs -Wno-deprecated-declarations)
|
|
elseif (APPLE)
|
|
target_compile_options(${target_name} PRIVATE
|
|
-Wno-declaration-after-statement -Wno-non-pod-varargs)
|
|
elseif (MSVC)
|
|
target_compile_options(${target_name} PRIVATE
|
|
"$<$<COMPILE_LANGUAGE:C,CXX>:/bigobj>"
|
|
"$<$<COMPILE_LANGUAGE:C,CXX>:/utf-8>")
|
|
endif ()
|
|
# Use signed char on ARM to match the original game (and x86)
|
|
string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" _mod_arch)
|
|
if (_mod_arch MATCHES "^(arm|aarch64)" AND CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU")
|
|
target_compile_options(${target_name} PRIVATE -fsigned-char)
|
|
endif ()
|
|
endif ()
|
|
|
|
if (APPLE)
|
|
if (_needs_host_link)
|
|
if (TARGET dusklight)
|
|
set(_game_exe "$<TARGET_FILE:dusklight>")
|
|
add_dependencies(${target_name} dusklight)
|
|
elseif (DUSK_GAME_EXE)
|
|
_mod_resolve_source_path(_game_exe "${DUSK_GAME_EXE}")
|
|
else ()
|
|
_mod_download_link_stub(_game_exe)
|
|
endif ()
|
|
target_link_options(${target_name} PRIVATE
|
|
-Xlinker -bundle_loader -Xlinker "${_game_exe}")
|
|
set_property(TARGET ${target_name} APPEND PROPERTY LINK_DEPENDS "${_game_exe}")
|
|
endif ()
|
|
set_target_properties(${target_name} PROPERTIES
|
|
BUILD_RPATH "@loader_path"
|
|
INSTALL_RPATH "@loader_path")
|
|
elseif (ANDROID)
|
|
if (_needs_host_link)
|
|
if (TARGET dusklight)
|
|
target_link_libraries(${target_name} PRIVATE dusklight)
|
|
else ()
|
|
if (DUSK_GAME_EXE)
|
|
_mod_resolve_source_path(_game_lib "${DUSK_GAME_EXE}")
|
|
else ()
|
|
_mod_download_link_stub(_game_lib)
|
|
endif ()
|
|
target_link_libraries(${target_name} PRIVATE "${_game_lib}")
|
|
endif ()
|
|
endif ()
|
|
set_target_properties(${target_name} PROPERTIES
|
|
BUILD_RPATH "$ORIGIN"
|
|
INSTALL_RPATH "$ORIGIN")
|
|
elseif (UNIX)
|
|
if (_needs_host_link)
|
|
target_link_options(${target_name} PRIVATE -Wl,--allow-shlib-undefined)
|
|
endif ()
|
|
set_target_properties(${target_name} PROPERTIES
|
|
BUILD_RPATH "$ORIGIN"
|
|
INSTALL_RPATH "$ORIGIN")
|
|
elseif (WIN32)
|
|
# Mods link against the game's import library (sdk/windows-<arch>.lib, generated by
|
|
# setup_windows_exports); cl and clang-cl both consume it in MSVC mode. Function
|
|
# calls resolve through import thunks; game data is reachable only through
|
|
# __declspec(dllimport), i.e. DUSK_GAME_DATA-annotated declarations.
|
|
if (_needs_host_link)
|
|
if (TARGET dusklight)
|
|
if (NOT DUSK_GAME_IMPLIB)
|
|
message(FATAL_ERROR
|
|
"add_mod: DUSK_GAME_IMPLIB is not set (see setup_windows_exports)")
|
|
endif ()
|
|
set(_game_lib "${DUSK_GAME_IMPLIB}")
|
|
elseif (DUSK_GAME_EXE)
|
|
_mod_resolve_source_path(_game_lib "${DUSK_GAME_EXE}")
|
|
if (NOT _game_lib MATCHES "\\.lib$")
|
|
message(FATAL_ERROR
|
|
"add_mod: DUSK_GAME_EXE must be an import library on Windows "
|
|
"(sdk/windows-<arch>.lib)")
|
|
endif ()
|
|
else ()
|
|
_mod_download_link_stub(_game_lib)
|
|
endif ()
|
|
target_link_libraries(${target_name} PRIVATE "${_game_lib}")
|
|
endif ()
|
|
set_target_properties(${target_name} PROPERTIES MSVC_RUNTIME_LIBRARY "MultiThreadedDLL")
|
|
target_compile_definitions(${target_name} PRIVATE _ITERATOR_DEBUG_LEVEL=0)
|
|
endif ()
|
|
endif ()
|
|
if (ARG_RUNTIME_LIBRARIES AND NOT _has_lib)
|
|
message(FATAL_ERROR "add_mod: RUNTIME_LIBRARIES requires SOURCES")
|
|
endif ()
|
|
|
|
set(_output_dir "${DUSK_MODS_OUTPUT_DIR}")
|
|
if (ARG_OUTPUT_DIR)
|
|
set(_output_dir "${ARG_OUTPUT_DIR}")
|
|
endif ()
|
|
set(_stage "${CMAKE_CURRENT_BINARY_DIR}/${target_name}_stage")
|
|
set(_out "${_output_dir}/${target_name}.dusk")
|
|
|
|
set(_zip_args mod.json)
|
|
set(_package_deps "${_mod_json}")
|
|
set(_package_inputs "${_mod_json}")
|
|
set(_extra_cmds "")
|
|
set(_lib_copy_cmd "")
|
|
set(_target_depend "")
|
|
if (_has_lib)
|
|
list(APPEND _zip_args lib)
|
|
set(_lib_copy_cmd
|
|
COMMAND ${CMAKE_COMMAND} -E make_directory "${_stage}/lib/${_lib_platform}"
|
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
|
"$<TARGET_FILE:${target_name}>" "${_stage}/lib/${_lib_platform}/${_lib_name}")
|
|
set(_target_depend ${target_name})
|
|
endif ()
|
|
string(TOLOWER "${_lib_name}" _lib_name_key)
|
|
set(_runtime_lib_name_keys "${_lib_name_key}")
|
|
foreach (_runtime_lib IN LISTS ARG_RUNTIME_LIBRARIES)
|
|
_mod_resolve_source_path(_runtime_lib_path "${_runtime_lib}")
|
|
if (NOT EXISTS "${_runtime_lib_path}" OR IS_DIRECTORY "${_runtime_lib_path}")
|
|
message(FATAL_ERROR "add_mod: runtime library does not exist or is not a file: ${_runtime_lib_path}")
|
|
endif ()
|
|
get_filename_component(_runtime_lib_name "${_runtime_lib_path}" NAME)
|
|
string(TOLOWER "${_runtime_lib_name}" _runtime_lib_name_key)
|
|
list(FIND _runtime_lib_name_keys "${_runtime_lib_name_key}" _runtime_lib_name_index)
|
|
if (NOT _runtime_lib_name_index EQUAL -1)
|
|
message(FATAL_ERROR "add_mod: duplicate runtime library filename: ${_runtime_lib_name}")
|
|
endif ()
|
|
list(APPEND _runtime_lib_name_keys "${_runtime_lib_name_key}")
|
|
list(APPEND _package_deps "${_runtime_lib_path}")
|
|
list(APPEND _package_inputs "${_runtime_lib_path}")
|
|
list(APPEND _lib_copy_cmd COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
|
"${_runtime_lib_path}" "${_stage}/lib/${_lib_platform}/${_runtime_lib_name}")
|
|
endforeach ()
|
|
if (ARG_RES_DIR)
|
|
_mod_resolve_source_path(_res_dir "${ARG_RES_DIR}")
|
|
_mod_collect_assets(_res_deps "${_res_dir}")
|
|
list(APPEND _package_deps ${_res_deps})
|
|
list(APPEND _package_inputs "${_res_dir}" ${_res_deps})
|
|
list(APPEND _zip_args res)
|
|
list(APPEND _extra_cmds COMMAND ${CMAKE_COMMAND} -E copy_directory
|
|
"${_res_dir}" "${_stage}/res")
|
|
endif ()
|
|
if (ARG_OVERLAY_DIR)
|
|
_mod_resolve_source_path(_overlay_dir "${ARG_OVERLAY_DIR}")
|
|
_mod_collect_assets(_overlay_deps "${_overlay_dir}")
|
|
list(APPEND _package_deps ${_overlay_deps})
|
|
list(APPEND _package_inputs "${_overlay_dir}" ${_overlay_deps})
|
|
list(APPEND _zip_args overlay)
|
|
list(APPEND _extra_cmds COMMAND ${CMAKE_COMMAND} -E copy_directory
|
|
"${_overlay_dir}" "${_stage}/overlay")
|
|
endif ()
|
|
if (ARG_TEXTURES_DIR)
|
|
_mod_resolve_source_path(_textures_dir "${ARG_TEXTURES_DIR}")
|
|
_mod_collect_assets(_textures_deps "${_textures_dir}")
|
|
list(APPEND _package_deps ${_textures_deps})
|
|
list(APPEND _package_inputs "${_textures_dir}" ${_textures_deps})
|
|
list(APPEND _zip_args textures)
|
|
list(APPEND _extra_cmds COMMAND ${CMAKE_COMMAND} -E copy_directory
|
|
"${_textures_dir}" "${_stage}/textures")
|
|
endif ()
|
|
|
|
set(_bundle_cmds "")
|
|
if (ARG_BUNDLE AND TARGET dusklight)
|
|
file(READ "${_mod_json}" _mod_json_text)
|
|
string(JSON _mod_id GET "${_mod_json_text}" id)
|
|
set_property(GLOBAL APPEND PROPERTY DUSK_BUNDLED_MOD_TARGETS "${target_name}")
|
|
set_property(GLOBAL APPEND PROPERTY DUSK_BUNDLED_MOD_IDS "${_mod_id}")
|
|
set_property(GLOBAL APPEND PROPERTY DUSK_BUNDLED_MOD_STAGES "${_stage}")
|
|
set_property(GLOBAL APPEND PROPERTY DUSK_BUNDLED_MOD_PACKAGES "${_out}")
|
|
set_property(GLOBAL APPEND PROPERTY DUSK_BUNDLED_MOD_LIB_PLATFORMS "${_lib_platform}")
|
|
set_property(GLOBAL APPEND PROPERTY DUSK_BUNDLED_MOD_LIB_NAMES "${_lib_name}")
|
|
set(_bundle_cmds
|
|
COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/bundled_mods"
|
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_out}" "${CMAKE_BINARY_DIR}/bundled_mods/${target_name}.dusk")
|
|
endif ()
|
|
|
|
set(_package_target "${target_name}_package")
|
|
set(_package_inputs_file "${CMAKE_CURRENT_BINARY_DIR}/${target_name}_package_inputs.txt")
|
|
list(SORT _package_inputs)
|
|
set(_package_inputs_text "")
|
|
foreach (_package_input IN LISTS _package_inputs)
|
|
string(APPEND _package_inputs_text "${_package_input}\n")
|
|
endforeach ()
|
|
file(GENERATE OUTPUT "${_package_inputs_file}" CONTENT "${_package_inputs_text}")
|
|
add_custom_command(OUTPUT "${_out}"
|
|
COMMAND ${CMAKE_COMMAND} -E rm -rf "${_stage}"
|
|
COMMAND ${CMAKE_COMMAND} -E make_directory "${_stage}" "${_output_dir}"
|
|
${_lib_copy_cmd}
|
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_mod_json}" "${_stage}/mod.json"
|
|
${_extra_cmds}
|
|
COMMAND ${CMAKE_COMMAND} -E chdir "${_stage}" ${CMAKE_COMMAND} -E tar cvf "${_out}" --format=zip ${_zip_args}
|
|
${_bundle_cmds}
|
|
DEPENDS ${_target_depend} ${_package_deps} "${_package_inputs_file}"
|
|
COMMENT "Packaging ${target_name} -> ${_out}"
|
|
COMMAND_EXPAND_LISTS
|
|
VERBATIM
|
|
)
|
|
add_custom_target(${_package_target} ALL DEPENDS "${_out}")
|
|
if (TARGET dusklight_mods)
|
|
add_dependencies(dusklight_mods ${_package_target})
|
|
endif ()
|
|
endfunction()
|
|
|
|
# Install rules for BUNDLE mods.
|
|
# - Windows: the .dusk archives into <install>/mods (the loader extracts native libs to the
|
|
# user cache).
|
|
# - Linux: pre-extracted stage dirs into <install>/mods so native libs dlopen in place from
|
|
# read-only installs.
|
|
# - macOS: pre-extracted stage dirs into the installed app's Contents/Resources/mods, native
|
|
# libs ad-hoc signed in place, then the whole bundle re-signed.
|
|
# - iOS/tvOS: assets into <app>/mods/<id>, the mod library into Frameworks/<id>.so,
|
|
# and runtime libraries alongside it.
|
|
# - Android: nothing here; gradle packs ${CMAKE_BINARY_DIR}/bundled_mods into APK assets.
|
|
function(install_bundled_mods)
|
|
get_property(_targets GLOBAL PROPERTY DUSK_BUNDLED_MOD_TARGETS)
|
|
if (NOT _targets OR ANDROID)
|
|
return ()
|
|
endif ()
|
|
get_property(_ids GLOBAL PROPERTY DUSK_BUNDLED_MOD_IDS)
|
|
get_property(_stages GLOBAL PROPERTY DUSK_BUNDLED_MOD_STAGES)
|
|
get_property(_lib_platforms GLOBAL PROPERTY DUSK_BUNDLED_MOD_LIB_PLATFORMS)
|
|
get_property(_lib_names GLOBAL PROPERTY DUSK_BUNDLED_MOD_LIB_NAMES)
|
|
list(LENGTH _targets _count)
|
|
math(EXPR _last "${_count} - 1")
|
|
|
|
if (APPLE)
|
|
get_target_property(_app_name dusklight OUTPUT_NAME)
|
|
if (NOT _app_name)
|
|
set(_app_name dusklight)
|
|
endif ()
|
|
set(_bundle_dir "${CMAKE_INSTALL_PREFIX}/${_app_name}.app")
|
|
if (IOS OR TVOS)
|
|
foreach (_i RANGE ${_last})
|
|
list(GET _targets ${_i} _target)
|
|
list(GET _ids ${_i} _id)
|
|
list(GET _stages ${_i} _stage)
|
|
list(GET _lib_platforms ${_i} _lib_platform)
|
|
list(GET _lib_names ${_i} _lib_name)
|
|
install(DIRECTORY "${_stage}/" DESTINATION "${_bundle_dir}/mods/${_id}"
|
|
PATTERN "lib" EXCLUDE)
|
|
install(PROGRAMS "$<TARGET_FILE:${_target}>"
|
|
DESTINATION "${_bundle_dir}/Frameworks" RENAME "${_id}.so")
|
|
install(DIRECTORY "${_stage}/lib/${_lib_platform}/"
|
|
DESTINATION "${_bundle_dir}/Frameworks"
|
|
PATTERN "${_lib_name}" EXCLUDE)
|
|
endforeach ()
|
|
else ()
|
|
foreach (_i RANGE ${_last})
|
|
list(GET _ids ${_i} _id)
|
|
list(GET _stages ${_i} _stage)
|
|
list(GET _lib_platforms ${_i} _lib_platform)
|
|
list(GET _lib_names ${_i} _lib_name)
|
|
install(DIRECTORY "${_stage}/" DESTINATION "${_bundle_dir}/Contents/Resources/mods/${_id}")
|
|
install(CODE "
|
|
file(GLOB _mod_libs \"${_bundle_dir}/Contents/Resources/mods/${_id}/lib/${_lib_platform}/*\")
|
|
foreach (_mod_lib IN LISTS _mod_libs)
|
|
if (NOT IS_DIRECTORY \"\${_mod_lib}\")
|
|
execute_process(COMMAND /usr/bin/codesign --force --sign - \"\${_mod_lib}\" COMMAND_ERROR_IS_FATAL ANY)
|
|
endif ()
|
|
endforeach ()")
|
|
endforeach ()
|
|
if (TARGET crashpad_handler)
|
|
install(CODE "execute_process(COMMAND /usr/bin/codesign --force --sign - \"${_bundle_dir}/Contents/MacOS/$<TARGET_FILE_NAME:crashpad_handler>\" COMMAND_ERROR_IS_FATAL ANY)")
|
|
endif ()
|
|
install(CODE "execute_process(COMMAND /usr/bin/codesign --force --sign - --entitlements \"${DUSK_ENTITLEMENTS}\" \"${_bundle_dir}\" COMMAND_ERROR_IS_FATAL ANY)")
|
|
endif ()
|
|
return ()
|
|
endif ()
|
|
|
|
if (DUSK_PACKAGE_INSTALL)
|
|
set(_mods_dest "${CMAKE_INSTALL_DATAROOTDIR}/dusklight/mods")
|
|
else ()
|
|
set(_mods_dest "${CMAKE_INSTALL_PREFIX}/mods")
|
|
endif ()
|
|
if (WIN32)
|
|
foreach (_target IN LISTS _targets)
|
|
install(FILES "${CMAKE_BINARY_DIR}/bundled_mods/${_target}.dusk" DESTINATION "${_mods_dest}")
|
|
endforeach ()
|
|
else ()
|
|
foreach (_i RANGE ${_last})
|
|
list(GET _ids ${_i} _id)
|
|
list(GET _stages ${_i} _stage)
|
|
install(DIRECTORY "${_stage}/" DESTINATION "${_mods_dest}/${_id}")
|
|
endforeach ()
|
|
endif ()
|
|
endfunction()
|