diff --git a/cmake/GameABIConfig.cmake b/cmake/GameABIConfig.cmake index 8b95dcaf67..0b965aa082 100644 --- a/cmake/GameABIConfig.cmake +++ b/cmake/GameABIConfig.cmake @@ -47,6 +47,15 @@ target_link_libraries(dusklight_mod_feature_game INTERFACE dusklight_mod_api dusklight_game_abi_headers) target_compile_definitions(dusklight_mod_feature_game INTERFACE DUSK_MOD_FEATURE_GAME=1) +# Game headers assume global.h comes first in the translation unit (it defines DUSK_GAME_DATA +# and friends); force-include it so mods don't depend on include order. +if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC") + target_compile_options(dusklight_mod_feature_game INTERFACE + "$<$:/FIglobal.h>") +else () + target_compile_options(dusklight_mod_feature_game INTERFACE + "$<$:SHELL:-include global.h>") +endif () target_sources(dusklight_mod_feature_game INTERFACE ${_game_root}/sdk/src/game_feature.cpp) diff --git a/cmake/ModSDK.cmake b/cmake/ModSDK.cmake index 87125e12fd..0371a7d61b 100644 --- a/cmake/ModSDK.cmake +++ b/cmake/ModSDK.cmake @@ -2,6 +2,8 @@ # [RUNTIME_LIBRARIES ...] [RES_DIR ] [OVERLAY_DIR ] # [TEXTURES_DIR ] [OUTPUT_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}") @@ -29,6 +31,34 @@ function(_mod_lib_info out_platform_var out_name_var) 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}") @@ -150,8 +180,7 @@ function(add_mod target_name) elseif (DUSK_GAME_EXE) _mod_resolve_source_path(_game_exe "${DUSK_GAME_EXE}") else () - message(FATAL_ERROR - "add_mod: FEATURES ${_features} requires DUSK_GAME_EXE (game executable)") + _mod_download_link_stub(_game_exe) endif () target_link_options(${target_name} PRIVATE -Xlinker -bundle_loader -Xlinker "${_game_exe}") @@ -164,12 +193,13 @@ function(add_mod target_name) if (_needs_host_link) if (TARGET dusklight) target_link_libraries(${target_name} PRIVATE dusklight) - elseif (DUSK_GAME_EXE) - _mod_resolve_source_path(_game_lib "${DUSK_GAME_EXE}") - target_link_libraries(${target_name} PRIVATE "${_game_lib}") else () - message(FATAL_ERROR - "add_mod: FEATURES ${_features} requires DUSK_GAME_EXE (libmain.so or stub)") + 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 @@ -202,8 +232,7 @@ function(add_mod target_name) "(sdk/windows-.lib)") endif () else () - message(FATAL_ERROR - "add_mod: FEATURES ${_features} requires DUSK_GAME_EXE (import library)") + _mod_download_link_stub(_game_lib) endif () target_link_libraries(${target_name} PRIVATE "${_game_lib}") endif () diff --git a/sdk/CMakeLists.txt b/sdk/CMakeLists.txt index 2f25c28efe..cd80781eb6 100644 --- a/sdk/CMakeLists.txt +++ b/sdk/CMakeLists.txt @@ -7,7 +7,8 @@ # add_subdirectory(/sdk dusk-sdk EXCLUDE_FROM_ALL) # add_mod(my_mod FEATURES game webgpu SOURCES ... MOD_JSON mod.json) # -# TODO: auto-download link targets from tag +# On platforms where mods link against the game binary (Windows/Apple/Android), a +# version-independent link stub is downloaded automatically unless DUSK_GAME_EXE is set. cmake_minimum_required(VERSION 3.25)