build: add ANYPS5_USE_SYSTEM_DEPS option

Resolve SDL2, freetype, Vulkan-Headers, SPIRV-Headers, glslang and
SPIRV-Tools from the system instead of the bundled submodules when the
option is ON. It is OFF by default, so the bundled build is unchanged.

Every package is required: a missing one, or Vulkan-Headers older than
1.4.310 (the agc driver uses VK_KHR_maintenance8), fails the configure
with an error and nothing falls back to the submodule. The system
packages are exposed under the same target names the bundled path uses,
so the rest of the CMake is untouched.

SDL2 is linked from the system as a shared library because the prx
libraries are shared objects and distribution static SDL2 is usually not
PIC. ffmpeg-core, libjpeg-turbo, stb, VulkanMemoryAllocator and LibAtrac9
stay bundled.
This commit is contained in:
husari.orozco 2026-10-06 11:13:31 -06:00 committed by Adrià Franch
parent 05c870cc05
commit 96ad950914
4 changed files with 136 additions and 24 deletions

View File

@ -25,7 +25,9 @@ endif()
option(ANYPS5_ENABLE_SPIRV_TOOLS "Enable SPIRV-Tools validation and optimization" OFF)
option(APS5_ENABLE_TIMING_LOG "Write frame timings asynchronously to frame-timing.log" OFF)
option(ANYPS5_USE_SYSTEM_DEPS "Resolve SDL2, freetype, Vulkan-Headers, SPIRV-Headers, glslang and SPIRV-Tools from the system instead of the bundled submodules" OFF)
add_compile_definitions(APS5_ENABLE_TIMING_LOG=$<BOOL:${APS5_ENABLE_TIMING_LOG}>)
include(cmake/SystemDeps.cmake)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
@ -82,10 +84,12 @@ set(SDL_HAPTIC OFF CACHE BOOL "" FORCE)
set(SDL_HIDAPI ON CACHE BOOL "" FORCE)
set(SDL_SENSOR OFF CACHE BOOL "" FORCE)
set(SDL_STATIC_PIC ON CACHE BOOL "" FORCE)
set(ANYPS5_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "")
add_subdirectory(3rdparty/SDL2)
set(CMAKE_EXE_LINKER_FLAGS "${ANYPS5_EXE_LINKER_FLAGS}")
if(NOT ANYPS5_USE_SYSTEM_DEPS)
set(ANYPS5_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "")
add_subdirectory(3rdparty/SDL2)
set(CMAKE_EXE_LINKER_FLAGS "${ANYPS5_EXE_LINKER_FLAGS}")
endif()
set(ARCHITECTURE x86_64)
add_subdirectory(3rdparty/ffmpeg-core)
if(MINGW)
@ -100,12 +104,14 @@ set(FT_DISABLE_PNG ON CACHE BOOL "" FORCE)
set(FT_DISABLE_HARFBUZZ ON CACHE BOOL "" FORCE)
set(FT_DISABLE_BROTLI ON CACHE BOOL "" FORCE)
set(SKIP_INSTALL_ALL ON CACHE BOOL "" FORCE)
add_subdirectory(3rdparty/freetype EXCLUDE_FROM_ALL)
set_target_properties(freetype PROPERTIES POSITION_INDEPENDENT_CODE ON)
if(WIN32)
get_target_property(freetypeSources freetype SOURCES)
list(FILTER freetypeSources EXCLUDE REGEX "ftver\\.rc$")
set_target_properties(freetype PROPERTIES SOURCES "${freetypeSources}")
if(NOT ANYPS5_USE_SYSTEM_DEPS)
add_subdirectory(3rdparty/freetype EXCLUDE_FROM_ALL)
set_target_properties(freetype PROPERTIES POSITION_INDEPENDENT_CODE ON)
if(WIN32)
get_target_property(freetypeSources freetype SOURCES)
list(FILTER freetypeSources EXCLUDE REGEX "ftver\\.rc$")
set_target_properties(freetype PROPERTIES SOURCES "${freetypeSources}")
endif()
endif()
add_subdirectory(core/shader/recompiler)

101
cmake/SystemDeps.cmake Normal file
View File

@ -0,0 +1,101 @@
# Resolves the third-party libraries from the system instead of the bundled
# submodules when ANYPS5_USE_SYSTEM_DEPS is ON. Every package is required: a
# missing one fails the configure and nothing falls back to the submodule.
#
# The system packages are exposed under the same target names the bundled
# submodules use (SDL2-static, freetype, glslang, SPIRV, glslang-standalone,
# SPIRV-Tools-opt, SPIRV-Tools-static) so the rest of the build does not need
# to know which path was taken.
if(NOT ANYPS5_USE_SYSTEM_DEPS)
return()
endif()
find_package(SDL2 CONFIG REQUIRED)
# The prx libraries are shared objects, so they need a position-independent
# SDL2. Distribution static builds are usually not PIC, so link the shared one.
if(NOT TARGET SDL2::SDL2)
message(FATAL_ERROR "ANYPS5_USE_SYSTEM_DEPS: SDL2 was found but does not provide SDL2::SDL2")
endif()
add_library(SDL2-static INTERFACE)
target_link_libraries(SDL2-static INTERFACE SDL2::SDL2)
find_package(Freetype REQUIRED)
if(NOT TARGET Freetype::Freetype)
message(FATAL_ERROR "ANYPS5_USE_SYSTEM_DEPS: freetype was found but does not provide Freetype::Freetype")
endif()
add_library(freetype INTERFACE)
target_link_libraries(freetype INTERFACE Freetype::Freetype)
find_package(VulkanHeaders CONFIG REQUIRED)
if(NOT TARGET Vulkan::Headers)
message(FATAL_ERROR "ANYPS5_USE_SYSTEM_DEPS: Vulkan-Headers was found but does not provide Vulkan::Headers")
endif()
get_target_property(ANYPS5_VULKAN_INCLUDE_DIRS Vulkan::Headers INTERFACE_INCLUDE_DIRECTORIES)
include(CheckCXXSourceCompiles)
set(CMAKE_REQUIRED_INCLUDES ${ANYPS5_VULKAN_INCLUDE_DIRS})
check_cxx_source_compiles("#include <vulkan/vulkan.h>\nint main() { VkPhysicalDeviceMaintenance8FeaturesKHR features{}; (void)features; return 0; }" ANYPS5_VULKAN_HAS_MAINTENANCE8)
unset(CMAKE_REQUIRED_INCLUDES)
if(NOT ANYPS5_VULKAN_HAS_MAINTENANCE8)
message(FATAL_ERROR "ANYPS5_USE_SYSTEM_DEPS: the system Vulkan-Headers do not provide VkPhysicalDeviceMaintenance8FeaturesKHR (VK_KHR_maintenance8), which the agc driver uses; install Vulkan-Headers 1.4.310 or newer")
endif()
find_package(SPIRV-Headers CONFIG REQUIRED)
if(NOT TARGET SPIRV-Headers::SPIRV-Headers)
message(FATAL_ERROR "ANYPS5_USE_SYSTEM_DEPS: SPIRV-Headers was found but does not provide SPIRV-Headers::SPIRV-Headers")
endif()
find_package(glslang CONFIG REQUIRED)
if(NOT TARGET glslang::glslang OR NOT TARGET glslang::SPIRV)
message(FATAL_ERROR "ANYPS5_USE_SYSTEM_DEPS: glslang was found but does not provide glslang::glslang and glslang::SPIRV")
endif()
add_library(glslang INTERFACE)
target_link_libraries(glslang INTERFACE glslang::glslang)
add_library(SPIRV INTERFACE)
target_link_libraries(SPIRV INTERFACE glslang::SPIRV)
# The bundled glslang has both <SPIRV/...> and <glslang/...> under one root; the
# system install keeps <glslang/...> under <prefix>/include and the rest,
# including <SPIRV/GlslangToSpv.h>, under <prefix>/include/glslang.
find_path(ANYPS5_GLSLANG_PUBLIC_INCLUDE_DIR NAMES glslang/Public/ShaderLang.h)
if(NOT ANYPS5_GLSLANG_PUBLIC_INCLUDE_DIR)
message(FATAL_ERROR "ANYPS5_USE_SYSTEM_DEPS: glslang/Public/ShaderLang.h was not found; the glslang headers are incomplete")
endif()
set(ANYPS5_GLSLANG_SPIRV_INCLUDE_DIR "${ANYPS5_GLSLANG_PUBLIC_INCLUDE_DIR}/glslang")
if(NOT EXISTS "${ANYPS5_GLSLANG_SPIRV_INCLUDE_DIR}/SPIRV/GlslangToSpv.h")
message(FATAL_ERROR "ANYPS5_USE_SYSTEM_DEPS: ${ANYPS5_GLSLANG_SPIRV_INCLUDE_DIR}/SPIRV/GlslangToSpv.h was not found")
endif()
find_program(ANYPS5_GLSLANG_STANDALONE_EXECUTABLE NAMES glslang glslangValidator)
if(NOT ANYPS5_GLSLANG_STANDALONE_EXECUTABLE)
message(FATAL_ERROR "ANYPS5_USE_SYSTEM_DEPS: the glslang compiler (glslang or glslangValidator) was not found; install the glslang tools package")
endif()
add_executable(glslang-standalone IMPORTED GLOBAL)
set_target_properties(glslang-standalone PROPERTIES IMPORTED_LOCATION "${ANYPS5_GLSLANG_STANDALONE_EXECUTABLE}")
if(ANYPS5_ENABLE_SPIRV_TOOLS)
find_package(SPIRV-Tools-opt CONFIG REQUIRED)
if(NOT TARGET SPIRV-Tools-opt OR NOT TARGET SPIRV-Tools-static)
message(FATAL_ERROR "ANYPS5_USE_SYSTEM_DEPS: SPIRV-Tools was found but does not provide SPIRV-Tools-opt and SPIRV-Tools-static")
endif()
endif()
set(_anyps5_system_include_targets
SDL2::SDL2
Freetype::Freetype
Vulkan::Headers
SPIRV-Headers::SPIRV-Headers
glslang::glslang
glslang::SPIRV
)
set(_anyps5_system_includes "")
foreach(_target IN LISTS _anyps5_system_include_targets)
if(TARGET ${_target})
get_target_property(_target_includes ${_target} INTERFACE_INCLUDE_DIRECTORIES)
if(_target_includes)
list(APPEND _anyps5_system_includes ${_target_includes})
endif()
endif()
endforeach()
list(APPEND _anyps5_system_includes ${ANYPS5_GLSLANG_SPIRV_INCLUDE_DIR} ${ANYPS5_GLSLANG_PUBLIC_INCLUDE_DIR})
include_directories(SYSTEM ${_anyps5_system_includes})

View File

@ -186,24 +186,26 @@ function(add_shader_recompiler target runtimeTarget)
list(REMOVE_ITEM shaderCacheGuardSources ${shaderCacheRecompilerSources})
find_package(Git QUIET)
set(shaderCacheSubmodules "${PROJECT_SOURCE_DIR}/3rdparty/SPIRV-Headers" "${PROJECT_SOURCE_DIR}/3rdparty/glslang")
if(ANYPS5_ENABLE_SPIRV_TOOLS)
list(APPEND shaderCacheSubmodules "${PROJECT_SOURCE_DIR}/3rdparty/SPIRV-Tools")
endif()
set(shaderCacheSubmoduleStamps)
foreach(submodule IN LISTS shaderCacheSubmodules)
list(APPEND shaderCacheSubmoduleStamps "${submodule}/CMakeLists.txt")
if(NOT GIT_FOUND)
continue()
if(NOT ANYPS5_USE_SYSTEM_DEPS)
set(shaderCacheSubmodules "${PROJECT_SOURCE_DIR}/3rdparty/SPIRV-Headers" "${PROJECT_SOURCE_DIR}/3rdparty/glslang")
if(ANYPS5_ENABLE_SPIRV_TOOLS)
list(APPEND shaderCacheSubmodules "${PROJECT_SOURCE_DIR}/3rdparty/SPIRV-Tools")
endif()
foreach(ref IN ITEMS HEAD refs/heads)
execute_process(COMMAND "${GIT_EXECUTABLE}" -C "${submodule}" rev-parse --path-format=absolute --git-path ${ref}
OUTPUT_VARIABLE stamp OUTPUT_STRIP_TRAILING_WHITESPACE RESULT_VARIABLE status ERROR_QUIET)
if(status EQUAL 0 AND EXISTS "${stamp}" AND NOT IS_DIRECTORY "${stamp}")
list(APPEND shaderCacheSubmoduleStamps "${stamp}")
foreach(submodule IN LISTS shaderCacheSubmodules)
list(APPEND shaderCacheSubmoduleStamps "${submodule}/CMakeLists.txt")
if(NOT GIT_FOUND)
continue()
endif()
foreach(ref IN ITEMS HEAD refs/heads)
execute_process(COMMAND "${GIT_EXECUTABLE}" -C "${submodule}" rev-parse --path-format=absolute --git-path ${ref}
OUTPUT_VARIABLE stamp OUTPUT_STRIP_TRAILING_WHITESPACE RESULT_VARIABLE status ERROR_QUIET)
if(status EQUAL 0 AND EXISTS "${stamp}" AND NOT IS_DIRECTORY "${stamp}")
list(APPEND shaderCacheSubmoduleStamps "${stamp}")
endif()
endforeach()
endforeach()
endforeach()
endif()
get_target_property(shaderCacheIncludeDirectories ${target} INCLUDE_DIRECTORIES)
string(TOUPPER "${CMAKE_BUILD_TYPE}" shaderCacheBuildType)

View File

@ -57,6 +57,7 @@ Project switches accept `ON` or `OFF`:
| `-DBUILD_TESTING=ON` | `OFF` | Build and register tests. |
| `-DANYPS5_RELINKER_ONLY=ON` | `OFF` | Build only the relinker and its tests, without third-party dependencies. |
| `-DANYPS5_ENABLE_SPIRV_TOOLS=ON` | `OFF` | Enable SPIR-V validation and optimization. |
| `-DANYPS5_USE_SYSTEM_DEPS=ON` | `OFF` | Resolve SDL2, freetype, Vulkan-Headers, SPIRV-Headers, glslang and SPIRV-Tools from the system instead of the submodules. |
| `-DAPS5_ENABLE_TIMING_LOG=ON` | `OFF` | Compile frame timing logging. |
| `-DAPS5_AGC_CREATE_LOG=OFF` | `ON` | Disable successful `sceAgcCreateShader` logging. |
| `-DAGC_BUILD_VISUAL_TEST=ON` | `OFF` | Build the standalone AGC SPIR-V visual test. |
@ -74,6 +75,8 @@ Build configuration parameters:
SDL and FreeType settings forced by the root `CMakeLists.txt` cannot be overridden with `-D`.
With `ANYPS5_USE_SYSTEM_DEPS=ON` those libraries come from the system (on Debian and Ubuntu: `libsdl2-dev`, `libfreetype-dev`, `libvulkan-dev`, `spirv-headers`, `glslang-dev`, `glslang-tools` and `spirv-tools`). A missing package, or Vulkan-Headers older than 1.4.310 (the agc driver uses `VK_KHR_maintenance8`), fails the configure with an error and never falls back to the submodule. The prx libraries are shared objects, so SDL2 is linked from the system as a shared library; the default build keeps its own static SDL2. `ffmpeg-core`, `libjpeg-turbo`, `stb`, `VulkanMemoryAllocator` and `LibAtrac9` always stay bundled and still need `git submodule update --init`.
## Write watch tests
The macOS write watch can be built and tested separately, without submodules or the prx libraries: