build: dedupe third-party/system wiring, support all build types, pin deps
Centralize the engine include/link usage in an eve_engine_includes INTERFACE target and the per-platform system library list in cmake/system_libraries.cmake (no more duplicated lists or global include/link dirs). Accept RelWithDebInfo/MinSizeRel, apply the medialoader patch via ExternalProject PATCH_COMMAND instead of mutating the checkout at configure time, pin the third-party aggregate and Dawn to fixed commits, derive the SDK header list from the module manifest, and add deprecation notices for the third-party directory aliases. Also fix message typos and sync test-count docs.
This commit is contained in:
1 parent
9de7f9bed3
commit
ee956e356d
13 files changed
+446
-138
No files matched your search
@@ -73,10 +73,16 @@ jobs:
|
||||
- name: Check module dependency layering
|
||||
run: python3 scripts/module_depgraph.py --check
|
||||
|
||||
- name: Check declared module layers vs includes
|
||||
run: python3 scripts/module_depgraph.py --check-layers
|
||||
|
||||
- name: Report dependency graph
|
||||
if: always()
|
||||
run: python3 scripts/module_depgraph.py
|
||||
|
||||
- name: Check test source manifest
|
||||
run: python3 scripts/check_test_manifest.py
|
||||
|
||||
- name: Test release.py
|
||||
run: python3 -m unittest discover -s scripts/tests -p "test_*.py" -v
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ export XDG_RUNTIME_DIR=/tmp/xdg-runtime && mkdir -p "$XDG_RUNTIME_DIR" && chmod
|
||||
export ALSOFT_DRIVERS=null # OpenAL Soft null backend (no audio card)
|
||||
```
|
||||
|
||||
- Unit tests (full suite, ~1400 tests, a couple of minutes):
|
||||
- Unit tests (full suite, ~1500 per-case tests, a couple of minutes):
|
||||
`VK_ICD_FILENAMES=... ALSOFT_DRIVERS=... xvfb-run -a make test/linux-debug`
|
||||
- `make test/*` runs tests per case (process-isolated; this is the fast path on
|
||||
CI) and injects fast headless defaults for ClassicScenes
|
||||
|
||||
+80
-52
@@ -16,6 +16,14 @@ set(EVENGINE_PREBUILT_THIRD_PARTY "" CACHE PATH
|
||||
"Compatibility alias for EVENGINE_THIRD_PARTY_BINARY_DIR")
|
||||
set(EVENGINE_THIRD_PARTY_ROOT "" CACHE PATH
|
||||
"Deprecated compatibility alias for EVENGINE_THIRD_PARTY_BINARY_DIR")
|
||||
if(EVENGINE_PREBUILT_THIRD_PARTY)
|
||||
message(DEPRECATION
|
||||
"EVENGINE_PREBUILT_THIRD_PARTY is deprecated; use EVENGINE_THIRD_PARTY_BINARY_DIR")
|
||||
endif()
|
||||
if(EVENGINE_THIRD_PARTY_ROOT)
|
||||
message(DEPRECATION
|
||||
"EVENGINE_THIRD_PARTY_ROOT is deprecated; use EVENGINE_THIRD_PARTY_BINARY_DIR")
|
||||
endif()
|
||||
if(NOT EVENGINE_THIRD_PARTY_BINARY_DIR)
|
||||
if(EVENGINE_PREBUILT_THIRD_PARTY)
|
||||
set(EVENGINE_THIRD_PARTY_BINARY_DIR "${EVENGINE_PREBUILT_THIRD_PARTY}" CACHE PATH
|
||||
@@ -45,6 +53,11 @@ include(CTest)
|
||||
|
||||
# This is the main function of the build script
|
||||
function(main)
|
||||
# Central include/link-usage target for every engine module, platform
|
||||
# library and test runner. Replaces the old global include_directories() /
|
||||
# link_directories() sprawl: targets opt in by linking eve_engine_includes,
|
||||
# and the third-party install trees register their include/link dirs here.
|
||||
add_library(eve_engine_includes INTERFACE)
|
||||
get_available_build()
|
||||
load_third_party()
|
||||
load_webgpu_backend()
|
||||
@@ -140,6 +153,7 @@ function(main)
|
||||
# content from the result. See cmake/module_manifest.cmake.
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/module_manifest.cmake)
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/thirdparty_libs.cmake)
|
||||
include(${CMAKE_SOURCE_DIR}/cmake/system_libraries.cmake)
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Emscripten" AND NOT EVENGINE_PROFILE)
|
||||
# The browser runtime drops the modules whose third-party deps were cut.
|
||||
set(EVENGINE_PROFILE "web")
|
||||
@@ -164,6 +178,11 @@ function(main)
|
||||
# Platform CMake may set EVENGINE_PLATFORM_LIB; clear stale cache from other platforms.
|
||||
unset(EVENGINE_PLATFORM_LIB CACHE)
|
||||
add_subdirectory(platform/${BUILD_PLATFORM})
|
||||
# Platform libraries (android / ios / macosx / webgpu) also compile against
|
||||
# the shared engine include set.
|
||||
if(EVENGINE_PLATFORM_LIB AND TARGET ${EVENGINE_PLATFORM_LIB})
|
||||
target_link_libraries(${EVENGINE_PLATFORM_LIB} PUBLIC eve_engine_includes)
|
||||
endif()
|
||||
add_subdirectory(src/engine)
|
||||
add_subdirectory(src/modules)
|
||||
add_subdirectory(src/scripts)
|
||||
@@ -214,6 +233,9 @@ macro(create_module libname folder)
|
||||
else()
|
||||
add_library(${libname} OBJECT ${module_src})
|
||||
endif()
|
||||
# Opt the module into the shared engine include set (was global
|
||||
# include_directories before; see eve_engine_includes in main()).
|
||||
target_link_libraries(${libname} PUBLIC eve_engine_includes)
|
||||
|
||||
add_custom_target(check_sources_${folder}
|
||||
ALL
|
||||
@@ -235,7 +257,7 @@ endmacro()
|
||||
|
||||
# This function will set the include directories for the project
|
||||
function(set_include)
|
||||
include_directories(
|
||||
target_include_directories(eve_engine_includes INTERFACE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/engine
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/modules
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/scripts
|
||||
@@ -298,9 +320,10 @@ function(set_include)
|
||||
message(FATAL_ERROR "Android NDK libvulkan not found (need ANDROID_PLATFORM >= 24)")
|
||||
endif()
|
||||
if(Vulkan_INCLUDE_DIRS)
|
||||
include_directories(${Vulkan_INCLUDE_DIRS})
|
||||
target_include_directories(eve_engine_includes INTERFACE ${Vulkan_INCLUDE_DIRS})
|
||||
else()
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/third-party/vulkan)
|
||||
target_include_directories(eve_engine_includes INTERFACE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/third-party/vulkan)
|
||||
endif()
|
||||
set(EVENGINE_VULKAN_LIB ${ANDROID_VULKAN_LIB} CACHE INTERNAL "Vulkan link target")
|
||||
message(STATUS "Vulkan (Android): ${ANDROID_VULKAN_LIB}")
|
||||
@@ -360,16 +383,17 @@ function(set_include)
|
||||
set(EVENGINE_MOLTENVK_FRAMEWORK_DIR "${_eve_moltenvk_framework_dir}" CACHE INTERNAL "MoltenVK framework search path")
|
||||
set(EVENGINE_MOLTENVK_STATIC_LIB "${_eve_moltenvk_static_lib}" CACHE INTERNAL "MoltenVK static archive")
|
||||
if(Vulkan_INCLUDE_DIRS)
|
||||
include_directories(${Vulkan_INCLUDE_DIRS})
|
||||
target_include_directories(eve_engine_includes INTERFACE ${Vulkan_INCLUDE_DIRS})
|
||||
else()
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/third-party/vulkan)
|
||||
target_include_directories(eve_engine_includes INTERFACE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/third-party/vulkan)
|
||||
endif()
|
||||
# Placeholder when using -framework; static mode sets the .a below in engine CMake.
|
||||
set(EVENGINE_VULKAN_LIB "" CACHE INTERNAL "Vulkan link target")
|
||||
message(STATUS "Vulkan (iOS MoltenVK ${_eve_moltenvk_link_mode}): ${EVENGINE_MOLTENVK_XCFRAMEWORK}")
|
||||
elseif(Vulkan_FOUND AND Vulkan_INCLUDE_DIRS AND Vulkan_LIBRARIES)
|
||||
message(STATUS "Vulkan found: ${Vulkan_LIBRARY}")
|
||||
include_directories(${Vulkan_INCLUDE_DIRS})
|
||||
target_include_directories(eve_engine_includes INTERFACE ${Vulkan_INCLUDE_DIRS})
|
||||
set(EVENGINE_VULKAN_LIB Vulkan::Vulkan CACHE INTERNAL "Vulkan link target")
|
||||
elseif(APPLE)
|
||||
message(FATAL_ERROR
|
||||
@@ -401,16 +425,16 @@ macro(get_available_build)
|
||||
# Cross-compiling for Emscripten (web/WASM, browser WebGPU) must win over host detection.
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
|
||||
list(APPEND AVAILABLE_PLATFORM "webgpu")
|
||||
set(BUILD_PLATFORM "webgpu" CACHE STRING "The build platfrom (${AVAILABLE_PLATFORM})")
|
||||
set(BUILD_PLATFORM "webgpu" CACHE STRING "The build platform (${AVAILABLE_PLATFORM})")
|
||||
SET_PROPERTY(CACHE BUILD_PLATFORM PROPERTY STRINGS ${AVAILABLE_PLATFORM})
|
||||
# Cross-compiling for Android (NDK toolchain) must win over host Apple/Linux detection.
|
||||
elseif(ANDROID OR (CMAKE_SYSTEM_NAME STREQUAL "Android"))
|
||||
list(APPEND AVAILABLE_PLATFORM "android")
|
||||
set(BUILD_PLATFORM "android" CACHE STRING "The build platfrom (${AVAILABLE_PLATFORM})")
|
||||
set(BUILD_PLATFORM "android" CACHE STRING "The build platform (${AVAILABLE_PLATFORM})")
|
||||
SET_PROPERTY(CACHE BUILD_PLATFORM PROPERTY STRINGS ${AVAILABLE_PLATFORM})
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "iOS")
|
||||
list(APPEND AVAILABLE_PLATFORM "ios")
|
||||
set(BUILD_PLATFORM "ios" CACHE STRING "The build platfrom (${AVAILABLE_PLATFORM})")
|
||||
set(BUILD_PLATFORM "ios" CACHE STRING "The build platform (${AVAILABLE_PLATFORM})")
|
||||
SET_PROPERTY(CACHE BUILD_PLATFORM PROPERTY STRINGS ${AVAILABLE_PLATFORM})
|
||||
elseif(UNIX)
|
||||
if(APPLE)
|
||||
@@ -418,13 +442,13 @@ macro(get_available_build)
|
||||
list(APPEND AVAILABLE_PLATFORM "ios")
|
||||
list(APPEND AVAILABLE_PLATFORM "android")
|
||||
list(APPEND AVAILABLE_PLATFORM "webgpu")
|
||||
set(BUILD_PLATFORM "macosx" CACHE STRING "The build platfrom (${AVAILABLE_PLATFORM})")
|
||||
set(BUILD_PLATFORM "macosx" CACHE STRING "The build platform (${AVAILABLE_PLATFORM})")
|
||||
SET_PROPERTY(CACHE BUILD_PLATFORM PROPERTY STRINGS ${AVAILABLE_PLATFORM})
|
||||
else() # Linux
|
||||
list(APPEND AVAILABLE_PLATFORM "linux")
|
||||
list(APPEND AVAILABLE_PLATFORM "android")
|
||||
list(APPEND AVAILABLE_PLATFORM "webgpu")
|
||||
set(BUILD_PLATFORM "linux" CACHE STRING "The build platfrom (${AVAILABLE_PLATFORM})")
|
||||
set(BUILD_PLATFORM "linux" CACHE STRING "The build platform (${AVAILABLE_PLATFORM})")
|
||||
SET_PROPERTY(CACHE BUILD_PLATFORM PROPERTY STRINGS ${AVAILABLE_PLATFORM})
|
||||
endif()
|
||||
else()
|
||||
@@ -432,7 +456,7 @@ macro(get_available_build)
|
||||
list(APPEND AVAILABLE_PLATFORM "win32")
|
||||
list(APPEND AVAILABLE_PLATFORM "android")
|
||||
list(APPEND AVAILABLE_PLATFORM "webgpu")
|
||||
set(BUILD_PLATFORM "win32" CACHE STRING "The build platfrom (${AVAILABLE_PLATFORM})")
|
||||
set(BUILD_PLATFORM "win32" CACHE STRING "The build platform (${AVAILABLE_PLATFORM})")
|
||||
MESSAGE("Build Platform: ${BUILD_PLATFORM}")
|
||||
SET_PROPERTY(CACHE BUILD_PLATFORM PROPERTY STRINGS ${AVAILABLE_PLATFORM})
|
||||
endif()
|
||||
@@ -488,7 +512,7 @@ macro(get_available_build)
|
||||
CACHE INTERNAL "Exact basenames excluded from module source scan")
|
||||
endif()
|
||||
|
||||
message("Availabe: ${AVAILABLE_PLATFORM}")
|
||||
message("Available: ${AVAILABLE_PLATFORM}")
|
||||
|
||||
if("${BUILD_PLATFORM}" IN_LIST AVAILABLE_PLATFORM)
|
||||
message("Build Platform: ${BUILD_PLATFORM}")
|
||||
@@ -590,16 +614,18 @@ function(check_third_party_project name repo)
|
||||
"${_eve_tp_binary}")
|
||||
endif()
|
||||
add_custom_target(${name})
|
||||
include_directories("${_eve_tp_binary}/include")
|
||||
target_include_directories(eve_engine_includes INTERFACE "${_eve_tp_binary}/include")
|
||||
# SDL2 and FreeType install their public headers one level below include/.
|
||||
# Their sources use <SDL.h> and <ft2build.h>, so expose those roots too.
|
||||
if(IS_DIRECTORY "${_eve_tp_binary}/include/SDL2")
|
||||
include_directories("${_eve_tp_binary}/include/SDL2")
|
||||
target_include_directories(eve_engine_includes INTERFACE
|
||||
"${_eve_tp_binary}/include/SDL2")
|
||||
endif()
|
||||
if(IS_DIRECTORY "${_eve_tp_binary}/include/freetype2")
|
||||
include_directories("${_eve_tp_binary}/include/freetype2")
|
||||
target_include_directories(eve_engine_includes INTERFACE
|
||||
"${_eve_tp_binary}/include/freetype2")
|
||||
endif()
|
||||
link_directories("${_eve_tp_binary}/lib")
|
||||
target_link_directories(eve_engine_includes INTERFACE "${_eve_tp_binary}/lib")
|
||||
message(STATUS "third-party: using read-only prebuilt tree ${_eve_tp_binary}")
|
||||
return()
|
||||
endif()
|
||||
@@ -681,14 +707,23 @@ function(check_third_party_project name repo)
|
||||
# --config is required for multi-config generators (VS); ignored by Ninja.
|
||||
set(_eve_tp_build_cmd ${CMAKE_COMMAND} --build ${CMAKE_CURRENT_SOURCE_DIR}/build/${name}/${TP_BUILD_PATH}/ --target install --config ${_eve_tp_build_type} --parallel 8)
|
||||
|
||||
# Tracked patch applied at build time (never by mutating the checkout at
|
||||
# configure time). Paths in the patch are relative to the medialoader
|
||||
# submodule root. See cmake/patch_third_party.cmake.
|
||||
set(_eve_tp_patch_cmd ${CMAKE_COMMAND}
|
||||
-DPATCH=${CMAKE_SOURCE_DIR}/cmake/patches/medialoader-smooth-normals.patch
|
||||
-DPATCH_DIR=${CMAKE_CURRENT_SOURCE_DIR}/${name}/medialoader
|
||||
-P ${CMAKE_SOURCE_DIR}/cmake/patch_third_party.cmake)
|
||||
|
||||
if(_eve_tp_use_ninja)
|
||||
ExternalProject_Add(${name}
|
||||
GIT_REPOSITORY ${GIT_HTTPS_LINK}
|
||||
GIT_TAG origin/main
|
||||
GIT_TAG 566e4073d2ec1c723b581daa50334a4b05956091
|
||||
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/${name}
|
||||
BINARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/build/${name}/${TP_BUILD_PATH}
|
||||
CMAKE_GENERATOR "Ninja"
|
||||
CMAKE_ARGS ${_eve_tp_cmake_args}
|
||||
PATCH_COMMAND ${_eve_tp_patch_cmd}
|
||||
BUILD_COMMAND ${_eve_tp_build_cmd}
|
||||
BUILD_ALWAYS 0
|
||||
EXCLUDE_FROM_ALL 1
|
||||
@@ -696,29 +731,33 @@ function(check_third_party_project name repo)
|
||||
else()
|
||||
ExternalProject_Add(${name}
|
||||
GIT_REPOSITORY ${GIT_HTTPS_LINK}
|
||||
GIT_TAG origin/main
|
||||
GIT_TAG 566e4073d2ec1c723b581daa50334a4b05956091
|
||||
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/${name}
|
||||
BINARY_DIR ${CMAKE_CURRENT_SOURCE_DIR}/build/${name}/${TP_BUILD_PATH}
|
||||
CMAKE_ARGS ${_eve_tp_cmake_args}
|
||||
PATCH_COMMAND ${_eve_tp_patch_cmd}
|
||||
BUILD_COMMAND ${_eve_tp_build_cmd}
|
||||
BUILD_ALWAYS 0
|
||||
EXCLUDE_FROM_ALL 1
|
||||
)
|
||||
endif()
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/build/${name}-binary/${TP_BUILD_PATH}/include)
|
||||
link_directories(${CMAKE_CURRENT_SOURCE_DIR}/build/${name}-binary/${TP_BUILD_PATH}/lib)
|
||||
target_include_directories(eve_engine_includes INTERFACE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/build/${name}-binary/${TP_BUILD_PATH}/include)
|
||||
target_link_directories(eve_engine_includes INTERFACE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/build/${name}-binary/${TP_BUILD_PATH}/lib)
|
||||
endfunction()
|
||||
|
||||
# Load third party project from github
|
||||
function(load_third_party)
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Release")
|
||||
message("Build Type: Release")
|
||||
elseif(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
message("Build Type: Debug")
|
||||
# Debug gets its own third-party install tree (<plat>-debug); the other
|
||||
# supported single-config build types (Release, RelWithDebInfo, MinSizeRel)
|
||||
# share the release-style tree and the md library postfixes on Windows.
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(DEBUG_APPENDIX "-debug")
|
||||
else()
|
||||
message(FATAL_ERROR "Unsupported Build Type: ${CMAKE_BUILD_TYPE}")
|
||||
set(DEBUG_APPENDIX "")
|
||||
endif()
|
||||
message("Build Type: ${CMAKE_BUILD_TYPE} (third-party tree suffix '${DEBUG_APPENDIX}')")
|
||||
|
||||
set(TP_BUILD_PATH ${BUILD_PLATFORM}${DEBUG_APPENDIX})
|
||||
message("Third Party Build Path: ${TP_BUILD_PATH}")
|
||||
@@ -732,8 +771,8 @@ function(load_third_party)
|
||||
"EVENGINE_THIRD_PARTY_BINARY_DIR must contain include/ and lib/: ${_eve_prebuilt_tp}")
|
||||
endif()
|
||||
message(STATUS "third-party: using read-only prebuilt install ${_eve_prebuilt_tp}")
|
||||
include_directories("${_eve_prebuilt_tp}/include")
|
||||
link_directories("${_eve_prebuilt_tp}/lib")
|
||||
target_include_directories(eve_engine_includes INTERFACE "${_eve_prebuilt_tp}/include")
|
||||
target_link_directories(eve_engine_includes INTERFACE "${_eve_prebuilt_tp}/lib")
|
||||
set(EVENGINE_THIRD_PARTY_BINARY_ONLY ON CACHE INTERNAL
|
||||
"Use installed third-party prefix" FORCE)
|
||||
# Preserve the dependency target expected by create_module(), but give it no
|
||||
@@ -744,30 +783,17 @@ function(load_third_party)
|
||||
endif()
|
||||
|
||||
ensure_third_party_checkout()
|
||||
# EVEngine's database module uses POCO Data + SQLite. The third-party
|
||||
# aggregate already defaults ENABLE_DATA / ENABLE_DATA_SQLITE to ON (pinned
|
||||
# by GIT_TAG below), so no configure-time edits are needed for it.
|
||||
#
|
||||
# Normal generation for assets without authored normals: medialoader maps
|
||||
# generateNormalsIfMissing to aiProcess_GenNormals (per-face, flat shading).
|
||||
# Patch the cloned tree (idempotent, same pattern as the ENABLE_DATA edit
|
||||
# below) to request aiProcess_GenSmoothNormals, so sphere-like models shade
|
||||
# smoothly while hard edges (default smoothing angle 80 degrees) keep seams.
|
||||
set(_eve_ml_loader "${CMAKE_SOURCE_DIR}/third-party/medialoader/model/ModelLoader.cpp")
|
||||
if(EXISTS "${_eve_ml_loader}")
|
||||
file(READ "${_eve_ml_loader}" _eve_ml_loader_text)
|
||||
string(REPLACE "aiProcess_GenNormals" "aiProcess_GenSmoothNormals"
|
||||
_eve_ml_loader_text "${_eve_ml_loader_text}")
|
||||
file(WRITE "${_eve_ml_loader}" "${_eve_ml_loader_text}")
|
||||
endif()
|
||||
# EVEngine's database module uses POCO Data and its bundled SQLite connector.
|
||||
# The third-party aggregate disables these by default to reduce its footprint;
|
||||
# enable the two targets in the checked-out aggregate before configuring it.
|
||||
if(NOT EVENGINE_THIRD_PARTY_BINARY_DIR)
|
||||
set(_eve_tp_cmake "${CMAKE_CURRENT_SOURCE_DIR}/third-party/CMakeLists.txt")
|
||||
file(READ "${_eve_tp_cmake}" _eve_tp_contents)
|
||||
string(REPLACE "set(ENABLE_DATA OFF CACHE BOOL \"\" FORCE)"
|
||||
"set(ENABLE_DATA ON CACHE BOOL \"\" FORCE)" _eve_tp_contents "${_eve_tp_contents}")
|
||||
string(REPLACE "set(ENABLE_DATA_SQLITE OFF CACHE BOOL \"\" FORCE)"
|
||||
"set(ENABLE_DATA_SQLITE ON CACHE BOOL \"\" FORCE)" _eve_tp_contents "${_eve_tp_contents}")
|
||||
file(WRITE "${_eve_tp_cmake}" "${_eve_tp_contents}")
|
||||
endif()
|
||||
# A tracked patch (cmake/patches/medialoader-smooth-normals.patch) switches
|
||||
# it to aiProcess_GenSmoothNormals, so sphere-like models shade smoothly
|
||||
# while hard edges (default smoothing angle 80 degrees) keep seams. The
|
||||
# patch is applied by the third-party ExternalProject's PATCH_COMMAND at
|
||||
# build time — never by mutating the checkout during configure.
|
||||
check_third_party_project(third-party "https://github.com/EVEngine/third-party")
|
||||
|
||||
ADD_CUSTOM_TARGET(deps DEPENDS third-party)
|
||||
@@ -801,7 +827,9 @@ function(load_webgpu_backend)
|
||||
set(DAWN_ENABLE_OPENGLES OFF CACHE BOOL "" FORCE)
|
||||
set(DAWN_USE_XCODE OFF CACHE BOOL "" FORCE)
|
||||
|
||||
set(EVENGINE_DAWN_TAG "main" CACHE STRING
|
||||
# Pinned Dawn commit (2026-08-19 main HEAD) so native WebGPU builds stay
|
||||
# reproducible; override with -DEVENGINE_DAWN_TAG=<commit> if needed.
|
||||
set(EVENGINE_DAWN_TAG "c3845d0d962656a2ea03063bddc85dc1ef1a0baa" CACHE STRING
|
||||
"Dawn commit/tag to fetch for the native WebGPU backend (pin for reproducible builds)")
|
||||
FetchContent_Declare(dawn
|
||||
GIT_REPOSITORY https://github.com/google/dawn.git
|
||||
@@ -816,7 +844,7 @@ function(load_webgpu_backend)
|
||||
endif()
|
||||
# Dawn's webgpu.h / webgpu_cpp.h live under src/ in the checkout; expose
|
||||
# them to every module target (engine, eve_imgui, gpgpu/webgpu, ...).
|
||||
include_directories("${dawn_SOURCE_DIR}/src")
|
||||
target_include_directories(eve_engine_includes INTERFACE "${dawn_SOURCE_DIR}/src")
|
||||
set(EVENGINE_WEBGPU_LIB dawn::dawn CACHE INTERNAL "WebGPU link target")
|
||||
message(STATUS "WebGPU (native): Dawn ready, link target = ${EVENGINE_WEBGPU_LIB}")
|
||||
endfunction()
|
||||
|
||||
@@ -114,6 +114,7 @@ GAME ?=
|
||||
reinstall/third-party/android reinstall/third-party/android-debug \
|
||||
reinstall/third-party/ios reinstall/third-party/ios-debug \
|
||||
link-compile-commands download-classic-scenes download-skinned-character \
|
||||
check/test-manifest check/module-layers \
|
||||
docs
|
||||
|
||||
# Default: every debug target this machine can build (host + optional ios/android/wsl).
|
||||
@@ -132,6 +133,14 @@ show-targets:
|
||||
@echo "sdk -> sdk/$(PLATFORM) (Release) or sdk/$(PLATFORM)-debug"
|
||||
@echo "run -> run/$(PLATFORM)-debug (GAME=$(GAME), empty = embedded demo)"
|
||||
|
||||
# Verify every test/*.cpp on disk is registered in test/CMakeLists.txt.
|
||||
check/test-manifest:
|
||||
python3 scripts/check_test_manifest.py
|
||||
|
||||
# Verify module includes never climb above the declared manifest LAYER.
|
||||
check/module-layers:
|
||||
python3 scripts/module_depgraph.py --check-layers
|
||||
|
||||
# clangd: build/compile_commands.json -> host platform debug CDB
|
||||
link-compile-commands:
|
||||
@mkdir -p build
|
||||
@@ -513,7 +522,7 @@ docs:
|
||||
CTEST_FILTER = $(if $(FILTER),-R '^$(subst .,\.,$(FILTER))')
|
||||
|
||||
# Default: run tests per case (process-isolated; this is the fast path on CI —
|
||||
# main runs 1551 cases in ~2-11 min). "bundle/<file>" entries stay registered
|
||||
# main runs 1526 cases in ~2-11 min). "bundle/<file>" entries stay registered
|
||||
# by cmake/ZeroErrDiscoverTestsImpl.cmake as an opt-in: GPU/window tests were
|
||||
# ~70x slower when several shared one process on CI, so bundles are excluded
|
||||
# unless requested (FILTER=bundle/<file> or ctest -L bundle).
|
||||
|
||||
+13
-4
@@ -57,10 +57,19 @@ install(FILES "${CMAKE_BINARY_DIR}/src/engine/common/config.h"
|
||||
DESTINATION include/eve/common
|
||||
)
|
||||
|
||||
set(_eve_module_dirs
|
||||
animation audio data event filesystem graphics image ik joystick keyboard mouse
|
||||
model3d network particles plugins sound spatial timer touch ui window
|
||||
)
|
||||
# Module header dirs are derived from the module manifest (single source of
|
||||
# truth) so the SDK always ships every module's public headers. CORE modules
|
||||
# (common / cmdline / devtools) live under src/engine and are installed above.
|
||||
set(_eve_module_dirs "")
|
||||
foreach(_eve_mod IN LISTS EVE_ALL_MODULES)
|
||||
if(EVE_MODULE_${_eve_mod}_CORE)
|
||||
continue()
|
||||
endif()
|
||||
list(APPEND _eve_module_dirs "${_eve_mod}")
|
||||
endforeach()
|
||||
if(NOT _eve_module_dirs)
|
||||
message(WARNING "install_sdk.cmake: EVE_ALL_MODULES is empty; no module headers will be installed")
|
||||
endif()
|
||||
foreach(_eve_mod IN LISTS _eve_module_dirs)
|
||||
if(EXISTS "${CMAKE_SOURCE_DIR}/src/modules/${_eve_mod}")
|
||||
install(DIRECTORY "${CMAKE_SOURCE_DIR}/src/modules/${_eve_mod}/"
|
||||
|
||||
@@ -80,8 +80,9 @@ eve_declare_module(NAME spatial LAYER 0 SCRIPT Spatial SLOT spatial
|
||||
GROUP 2d 3d web)
|
||||
eve_declare_module(NAME ik LIB EVIK LAYER 0 SCRIPT IK
|
||||
GROUP 2d 3d web)
|
||||
eve_declare_module(NAME editor LAYER 0 SCRIPT Editor SLOT editor
|
||||
GROUP 3d web)
|
||||
eve_declare_module(NAME editor LAYER 6 SCRIPT Editor SLOT editor
|
||||
GROUP 3d web
|
||||
OPTIONAL_DEPS procgen)
|
||||
eve_declare_module(NAME plugins LAYER 0 SCRIPT Plugins
|
||||
GROUP 3d)
|
||||
eve_declare_module(NAME database LAYER 0 SCRIPT Database
|
||||
@@ -92,7 +93,7 @@ eve_declare_module(NAME inventory LAYER 0 SCRIPT Inventory)
|
||||
# THIRDPARTY poco is required so MSVC compiles those TUs with
|
||||
# POCO_NO_AUTOMATIC_LIBS; otherwise the obj records a link of
|
||||
# PocoFoundationd.lib instead of the *mdd archive the third-party build emits.
|
||||
eve_declare_module(NAME building LAYER 0 SCRIPT Building
|
||||
eve_declare_module(NAME building LAYER 4 SCRIPT Building
|
||||
DEPS grid data
|
||||
THIRDPARTY poco)
|
||||
|
||||
@@ -117,7 +118,7 @@ eve_declare_module(NAME joystick LAYER 1 SCRIPT Joystick
|
||||
DEPS event
|
||||
THIRDPARTY sdl2
|
||||
GROUP minimal 2d 3d web)
|
||||
eve_declare_module(NAME model3d LIB EVModel3D LAYER 1 SCRIPT Model3D SLOT model3d
|
||||
eve_declare_module(NAME model3d LIB EVModel3D LAYER 4 SCRIPT Model3D SLOT model3d
|
||||
DEPS filesystem
|
||||
THIRDPARTY medialoader_model assimp
|
||||
GROUP 3d)
|
||||
@@ -204,8 +205,8 @@ eve_declare_module(NAME weather LAYER 4 SCRIPT Weather SLOT weather
|
||||
eve_declare_module(NAME stylize LAYER 4 SCRIPT Stylize SLOT stylize
|
||||
DEPS graphics image
|
||||
GROUP 3d)
|
||||
eve_declare_module(NAME voxel LAYER 4 SCRIPT Voxel
|
||||
DEPS graphics
|
||||
eve_declare_module(NAME voxel LAYER 5 SCRIPT Voxel
|
||||
DEPS graphics procgen
|
||||
GROUP 3d)
|
||||
eve_declare_module(NAME spritestack LIB EVSpriteStack LAYER 4 SCRIPT SpriteStack SLOT spritestack
|
||||
DEPS graphics image model3d
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
# Idempotent git-apply wrapper used by ExternalProject PATCH_COMMAND.
|
||||
#
|
||||
# Usage:
|
||||
# cmake -DPATCH=<abs path to .patch>
|
||||
# -DPATCH_DIR=<git checkout root the patch paths are relative to>
|
||||
# -P cmake/patch_third_party.cmake
|
||||
#
|
||||
# The patch is applied with `git apply` inside PATCH_DIR. If it is already
|
||||
# applied (reverse-apply succeeds) the step is a no-op so rebuilds do not fail.
|
||||
# If the working tree drifted so the patch no longer applies, configure/build
|
||||
# fails loudly instead of silently compiling different third-party code.
|
||||
|
||||
if(NOT DEFINED PATCH OR NOT DEFINED PATCH_DIR)
|
||||
message(FATAL_ERROR "patch_third_party.cmake requires -DPATCH=... and -DPATCH_DIR=...")
|
||||
endif()
|
||||
|
||||
get_filename_component(PATCH_ABS "${PATCH}" ABSOLUTE)
|
||||
get_filename_component(PATCH_DIR_ABS "${PATCH_DIR}" ABSOLUTE)
|
||||
if(NOT EXISTS "${PATCH_ABS}")
|
||||
message(FATAL_ERROR "Third-party patch file not found: ${PATCH_ABS}")
|
||||
endif()
|
||||
if(NOT IS_DIRECTORY "${PATCH_DIR_ABS}")
|
||||
message(FATAL_ERROR "Third-party patch target dir not found: ${PATCH_DIR_ABS}")
|
||||
endif()
|
||||
|
||||
find_package(Git QUIET)
|
||||
if(NOT GIT_EXECUTABLE)
|
||||
message(FATAL_ERROR "git is required to apply third-party patches")
|
||||
endif()
|
||||
|
||||
# Already applied? `git apply --reverse --check` succeeds only then.
|
||||
execute_process(
|
||||
COMMAND "${GIT_EXECUTABLE}" apply --reverse --check "${PATCH_ABS}"
|
||||
WORKING_DIRECTORY "${PATCH_DIR_ABS}"
|
||||
RESULT_VARIABLE _eve_patch_reverse
|
||||
OUTPUT_QUIET ERROR_QUIET)
|
||||
if(_eve_patch_reverse EQUAL 0)
|
||||
message(STATUS "Third-party patch already applied: ${PATCH_ABS}")
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Apply cleanly, or fail loudly so a stale patch cannot silently bit-rot.
|
||||
execute_process(
|
||||
COMMAND "${GIT_EXECUTABLE}" apply --check "${PATCH_ABS}"
|
||||
WORKING_DIRECTORY "${PATCH_DIR_ABS}"
|
||||
RESULT_VARIABLE _eve_patch_check
|
||||
OUTPUT_QUIET ERROR_QUIET)
|
||||
if(NOT _eve_patch_check EQUAL 0)
|
||||
message(FATAL_ERROR
|
||||
"Third-party patch no longer applies cleanly: ${PATCH_ABS}\n"
|
||||
"The vendored source changed upstream; update or drop the patch.")
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
COMMAND "${GIT_EXECUTABLE}" apply "${PATCH_ABS}"
|
||||
WORKING_DIRECTORY "${PATCH_DIR_ABS}"
|
||||
RESULT_VARIABLE _eve_patch_result)
|
||||
if(NOT _eve_patch_result EQUAL 0)
|
||||
message(FATAL_ERROR "git apply failed for ${PATCH_ABS} (exit ${_eve_patch_result})")
|
||||
endif()
|
||||
message(STATUS "Applied third-party patch: ${PATCH_ABS}")
|
||||
@@ -0,0 +1,14 @@
|
||||
diff --git a/model/ModelLoader.cpp b/model/ModelLoader.cpp
|
||||
index beccd4e..604deb8 100644
|
||||
--- a/model/ModelLoader.cpp
|
||||
+++ b/model/ModelLoader.cpp
|
||||
@@ -17,7 +17,7 @@ unsigned int ModelLoader::flagsFrom(const LoadOptions &opt) const {
|
||||
unsigned int flags = 0;
|
||||
if (opt.triangulate)
|
||||
flags |= aiProcess_Triangulate;
|
||||
if (opt.generateNormalsIfMissing)
|
||||
- flags |= aiProcess_GenNormals;
|
||||
+ flags |= aiProcess_GenSmoothNormals;
|
||||
if (opt.joinIdenticalVertices)
|
||||
flags |= aiProcess_JoinIdenticalVertices;
|
||||
if (opt.flipUVs)
|
||||
@@ -0,0 +1,80 @@
|
||||
# Platform system libraries, appended to the list variable named by <out_var>.
|
||||
#
|
||||
# Shared by src/engine/CMakeLists.txt (host binary) and test/CMakeLists.txt
|
||||
# (unit-test runner) so the per-platform link lists cannot drift apart.
|
||||
function(eve_append_system_libraries out_var)
|
||||
if(WIN32)
|
||||
list(APPEND ${out_var} winmm version imm32 Setupapi ws2_32 iphlpapi shlwapi)
|
||||
elseif(ANDROID OR (CMAKE_SYSTEM_NAME STREQUAL "Android"))
|
||||
find_library(ANDROID_LOG_LIB log)
|
||||
find_library(ANDROID_LIB android)
|
||||
find_library(ANDROID_OPENSLES_LIB OpenSLES)
|
||||
list(APPEND ${out_var}
|
||||
${ANDROID_LOG_LIB}
|
||||
${ANDROID_LIB}
|
||||
${ANDROID_OPENSLES_LIB}
|
||||
dl
|
||||
m
|
||||
c++_shared
|
||||
)
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
|
||||
# Emscripten exposes pthread/dl/GL as virtual libraries; nothing to link.
|
||||
# Game-side threading is enabled through -sPROXY_TO_PTHREAD (platform/webgpu).
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "iOS" OR EVENGINE_IOS)
|
||||
list(APPEND ${out_var}
|
||||
"-framework UIKit"
|
||||
"-framework Foundation"
|
||||
"-framework CoreFoundation"
|
||||
"-framework Metal"
|
||||
"-framework QuartzCore"
|
||||
"-framework CoreGraphics"
|
||||
"-framework AudioToolbox"
|
||||
"-framework CoreAudio"
|
||||
"-framework AVFoundation"
|
||||
"-framework CoreMedia"
|
||||
"-framework GameController"
|
||||
"-framework CoreHaptics"
|
||||
"-framework CoreMotion"
|
||||
"-framework OpenGLES"
|
||||
"-framework CoreBluetooth"
|
||||
# Static MoltenVK references IOSurface APIs.
|
||||
"-framework IOSurface"
|
||||
iconv
|
||||
)
|
||||
elseif(APPLE)
|
||||
list(APPEND ${out_var}
|
||||
dl pthread iconv
|
||||
"-framework Cocoa"
|
||||
"-framework IOKit"
|
||||
"-framework ForceFeedback"
|
||||
"-framework Carbon"
|
||||
"-framework CoreVideo"
|
||||
"-framework Metal"
|
||||
"-framework QuartzCore"
|
||||
"-framework AudioToolbox"
|
||||
"-framework CoreAudio"
|
||||
"-framework GameController"
|
||||
"-framework CoreHaptics"
|
||||
"-framework AVFoundation"
|
||||
"-framework CoreMedia"
|
||||
"-framework CoreFoundation"
|
||||
"-framework Foundation"
|
||||
"-framework OpenGL"
|
||||
)
|
||||
elseif(UNIX)
|
||||
# Static SDL2 pulls Wayland/X11 extras; FreeType needs bz2/png.
|
||||
list(APPEND ${out_var}
|
||||
dl pthread m rt bz2 png
|
||||
X11 Xext Xcursor Xrandr Xxf86vm Xi Xss Xinerama
|
||||
wayland-client wayland-cursor wayland-egl xkbcommon
|
||||
asound
|
||||
)
|
||||
# OpenAL Soft may compile the sndio backend when libsndio-dev is present.
|
||||
# GitHub Actions runners typically lack libsndio, so only link when found.
|
||||
find_library(EVENGINE_SNDIO_LIBRARY sndio)
|
||||
if(EVENGINE_SNDIO_LIBRARY)
|
||||
list(APPEND ${out_var} sndio)
|
||||
endif()
|
||||
endif()
|
||||
set(${out_var} "${${out_var}}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
@@ -0,0 +1,77 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Verify every test/*.cpp on disk is registered in test/CMakeLists.txt.
|
||||
|
||||
The unit-test suite is listed explicitly in test/CMakeLists.txt (file(GLOB
|
||||
all_test_cpp ...) plus conditionals). A source file that lands in test/ but is
|
||||
missing from that list silently never compiles or runs, which is how
|
||||
test/hair.cpp and test/runtime.cpp rotted before this check existed.
|
||||
|
||||
Usage:
|
||||
python3 scripts/check_test_manifest.py # exit 1 on drift
|
||||
"""
|
||||
|
||||
import pathlib
|
||||
import re
|
||||
import sys
|
||||
|
||||
REPO = pathlib.Path(__file__).resolve().parent.parent
|
||||
TEST_DIR = REPO / "test"
|
||||
CMAKE_LIST = TEST_DIR / "CMakeLists.txt"
|
||||
|
||||
ENTRY_RE = re.compile(r"^\s+([\w.-]+\.cpp)\s*$")
|
||||
APPEND_RE = re.compile(r"list\(APPEND\s+all_test_cpp\s+([\w./-]+\.cpp)\)")
|
||||
|
||||
# Test sources appended conditionally inside test/CMakeLists.txt.
|
||||
CONDITIONAL = {
|
||||
"demo.cpp", # only when EVENGINE_BUILD_DEMO=ON
|
||||
}
|
||||
|
||||
|
||||
def listed_sources() -> set[str]:
|
||||
text = CMAKE_LIST.read_text(encoding="utf-8")
|
||||
listed = set()
|
||||
in_glob = False
|
||||
for line in text.splitlines():
|
||||
if "file(GLOB all_test_cpp" in line:
|
||||
in_glob = True
|
||||
continue
|
||||
if in_glob:
|
||||
if line.rstrip().endswith(")"):
|
||||
in_glob = False
|
||||
continue
|
||||
m = ENTRY_RE.match(line)
|
||||
if m:
|
||||
listed.add(m.group(1))
|
||||
m = APPEND_RE.search(line)
|
||||
if m:
|
||||
listed.add(pathlib.PurePosixPath(m.group(1)).name)
|
||||
return listed
|
||||
|
||||
|
||||
def main() -> int:
|
||||
if not CMAKE_LIST.exists():
|
||||
print(f"error: {CMAKE_LIST} not found", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
on_disk = {p.name for p in TEST_DIR.glob("*.cpp")}
|
||||
listed = listed_sources()
|
||||
missing = sorted((on_disk - listed) - CONDITIONAL)
|
||||
stale = sorted(listed - on_disk - CONDITIONAL)
|
||||
|
||||
if not missing and not stale:
|
||||
print(f"test manifest OK: {len(listed)} sources listed, {len(on_disk)} on disk")
|
||||
return 0
|
||||
|
||||
if missing:
|
||||
print("error: test source files missing from test/CMakeLists.txt:", file=sys.stderr)
|
||||
for name in missing:
|
||||
print(f" {name}", file=sys.stderr)
|
||||
if stale:
|
||||
print("error: entries in test/CMakeLists.txt with no source file:", file=sys.stderr)
|
||||
for name in stale:
|
||||
print(f" {name}", file=sys.stderr)
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -8,6 +8,11 @@ docs/dev/模块编排与裁剪架构.md for how the output is interpreted.
|
||||
python3 scripts/module_depgraph.py # graph + layers
|
||||
python3 scripts/module_depgraph.py --cycles # cycles only
|
||||
python3 scripts/module_depgraph.py --check # exit 1 on unlisted back-edge
|
||||
python3 scripts/module_depgraph.py --check-layers
|
||||
# exit 1 when an include edge
|
||||
# climbs above the LAYER the
|
||||
# module declares in the
|
||||
# module manifest
|
||||
|
||||
Only sub-path includes ("map/Map.h") count as a cross-module dependency;
|
||||
a bare <map> / <thread> / <filesystem> is a standard library header.
|
||||
@@ -21,6 +26,7 @@ from collections import defaultdict
|
||||
|
||||
REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
MODULES_DIR = os.path.join(REPO, "src", "modules")
|
||||
MANIFEST_FILE = os.path.join(REPO, "cmake", "module_manifest.cmake")
|
||||
|
||||
INCLUDE_RE = re.compile(r'^\s*#\s*include\s*[<"]([^">]+)[">]', re.M)
|
||||
SOURCE_EXT = (".cpp", ".cc", ".h", ".hpp")
|
||||
@@ -32,7 +38,6 @@ KNOWN_BACK_EDGES = {
|
||||
# window/Window.cpp, window/sdl/Window.cpp: the window owns the Graphics
|
||||
# pointer and decodes its own icon image.
|
||||
("window", "graphics"),
|
||||
("window", "image"),
|
||||
# scene/Scene.cpp: pickScreenAt and collectFrustumIdsAt take a
|
||||
# graphics::Camera3D and read its projection. Everything else about scene is
|
||||
# now renderer-agnostic (graphics registers its own link kinds), so these two
|
||||
@@ -40,6 +45,29 @@ KNOWN_BACK_EDGES = {
|
||||
("scene", "graphics"),
|
||||
}
|
||||
|
||||
# eve_declare_module(NAME <m> ... LAYER <n> ...) blocks in the module manifest.
|
||||
DECLARE_RE = re.compile(r"eve_declare_module\((.*?)\)", re.S)
|
||||
NAME_RE = re.compile(r"NAME\s+(\S+)")
|
||||
LAYER_RE = re.compile(r"LAYER\s+(-?\d+)")
|
||||
|
||||
|
||||
def declared_layers():
|
||||
"""Return {module: declared LAYER} parsed from cmake/module_manifest.cmake.
|
||||
|
||||
The manifest is the single source of truth for the *declared* module
|
||||
layers. The computed layers printed by the default report are derived from
|
||||
the include graph instead; this check exists to keep the two in step.
|
||||
"""
|
||||
with open(MANIFEST_FILE, encoding="utf-8") as handle:
|
||||
text = handle.read()
|
||||
result = {}
|
||||
for block in DECLARE_RE.findall(text):
|
||||
name = NAME_RE.search(block)
|
||||
layer = LAYER_RE.search(block)
|
||||
if name and layer:
|
||||
result[name.group(1)] = int(layer.group(1))
|
||||
return result
|
||||
|
||||
|
||||
def scan():
|
||||
"""Return (modules, edges, header_edges).
|
||||
@@ -112,12 +140,61 @@ def cycles(edges, ignore=frozenset()):
|
||||
return found
|
||||
|
||||
|
||||
def check_declared_layers(edges, header_edges):
|
||||
"""Exit 1 when an include edge climbs above the declared module LAYER.
|
||||
|
||||
The manifest declares each module's layer (cmake/module_manifest.cmake).
|
||||
A module may only include headers from modules declared at the same or a
|
||||
lower layer; an edge toward a *strictly higher* layer is a layering
|
||||
violation and is reported (KNOWN_BACK_EDGES whitelists accepted debt).
|
||||
Same-layer edges (e.g. window -> image) are allowed, matching the DEPS the
|
||||
manifest itself declares.
|
||||
"""
|
||||
layers_map = declared_layers()
|
||||
missing = sorted(m for m in set(edges) | {b for deps in edges.values() for b in deps}
|
||||
if m not in layers_map)
|
||||
if missing:
|
||||
print("warning: modules missing a LAYER declaration in the manifest: "
|
||||
+ ", ".join(missing), file=sys.stderr)
|
||||
|
||||
actual = {(a, b) for a, deps in edges.items() for b in deps}
|
||||
offenders = sorted(
|
||||
(a, b) for (a, b) in actual
|
||||
if a in layers_map and b in layers_map
|
||||
and layers_map[b] > layers_map[a]
|
||||
and (a, b) not in KNOWN_BACK_EDGES
|
||||
)
|
||||
stale = sorted(
|
||||
(a, b) for (a, b) in KNOWN_BACK_EDGES
|
||||
if (a, b) in actual
|
||||
and (a not in layers_map or b not in layers_map
|
||||
or layers_map[b] <= layers_map[a])
|
||||
)
|
||||
|
||||
for a, b in offenders:
|
||||
marker = "*" if (a, b) in header_edges else " "
|
||||
print(f"error: layer violation {a}(L{layers_map[a]}) -> {b}(L{layers_map[b]}){marker}",
|
||||
file=sys.stderr)
|
||||
for a, b in stale:
|
||||
print(f"note: {a} -> {b} no longer violates the declared layers; "
|
||||
"drop it from KNOWN_BACK_EDGES", file=sys.stderr)
|
||||
|
||||
if offenders:
|
||||
return 1
|
||||
print(f"ok: no declared-layer violations "
|
||||
f"({len(KNOWN_BACK_EDGES)} known back-edges, {len(stale)} now stale)")
|
||||
return 0
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__,
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||
parser.add_argument("--cycles", action="store_true", help="report dependency cycles only")
|
||||
parser.add_argument("--check", action="store_true",
|
||||
help="fail when a back-edge outside KNOWN_BACK_EDGES appears")
|
||||
parser.add_argument("--check-layers", action="store_true",
|
||||
help="fail when an include edge climbs above the module's "
|
||||
"declared manifest LAYER")
|
||||
args = parser.parse_args()
|
||||
|
||||
modules, edges, header_edges = scan()
|
||||
@@ -150,6 +227,9 @@ def main():
|
||||
print(f"ok: no new back-edges ({len(KNOWN_BACK_EDGES)} known, {len(stale)} now stale)")
|
||||
return 0
|
||||
|
||||
if args.check_layers:
|
||||
return check_declared_layers(edges, header_edges)
|
||||
|
||||
by_layer = defaultdict(list)
|
||||
for module in modules:
|
||||
by_layer[depth[module]].append(module)
|
||||
|
||||
+13
-73
@@ -40,6 +40,9 @@ endif()
|
||||
# symbolized stack trace on crash; it is a host-only tool, not a game module.
|
||||
if(WIN32)
|
||||
add_library(EVBacktrace INTERFACE)
|
||||
# backward.hpp lives in the third-party install; get its include dirs
|
||||
# through the shared include target instead of global include_directories.
|
||||
target_link_libraries(EVBacktrace INTERFACE eve_engine_includes)
|
||||
if(EVENGINE_THIRD_PARTY_BINARY_DIR)
|
||||
# Prebuilt-install mode: point at the install tree directly.
|
||||
target_include_directories(EVBacktrace INTERFACE ${EVENGINE_THIRD_PARTY_BINARY_DIR}/include)
|
||||
@@ -53,81 +56,18 @@ if(WIN32)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
set(SystemLibraries ${SystemLibraries} winmm version imm32 Setupapi ws2_32 iphlpapi shlwapi)
|
||||
elseif(ANDROID OR (CMAKE_SYSTEM_NAME STREQUAL "Android"))
|
||||
find_library(ANDROID_LOG_LIB log)
|
||||
find_library(ANDROID_LIB android)
|
||||
find_library(ANDROID_OPENSLES_LIB OpenSLES)
|
||||
set(SystemLibraries ${SystemLibraries}
|
||||
${ANDROID_LOG_LIB}
|
||||
${ANDROID_LIB}
|
||||
${ANDROID_OPENSLES_LIB}
|
||||
dl
|
||||
m
|
||||
c++_shared
|
||||
)
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Emscripten")
|
||||
# Emscripten exposes pthread/dl/GL as virtual libraries; nothing to link.
|
||||
# Game-side threading is enabled through -sPROXY_TO_PTHREAD (platform/webgpu).
|
||||
set(SystemLibraries ${SystemLibraries})
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "iOS" OR EVENGINE_IOS)
|
||||
set(SystemLibraries ${SystemLibraries}
|
||||
"-framework UIKit"
|
||||
"-framework Foundation"
|
||||
"-framework CoreFoundation"
|
||||
"-framework Metal"
|
||||
"-framework QuartzCore"
|
||||
"-framework CoreGraphics"
|
||||
"-framework AudioToolbox"
|
||||
"-framework CoreAudio"
|
||||
"-framework AVFoundation"
|
||||
"-framework CoreMedia"
|
||||
"-framework GameController"
|
||||
"-framework CoreHaptics"
|
||||
"-framework CoreMotion"
|
||||
"-framework OpenGLES"
|
||||
"-framework CoreBluetooth"
|
||||
# Static MoltenVK references IOSurface APIs.
|
||||
"-framework IOSurface"
|
||||
iconv
|
||||
)
|
||||
elseif(APPLE)
|
||||
set(SystemLibraries ${SystemLibraries}
|
||||
dl pthread iconv
|
||||
"-framework Cocoa"
|
||||
"-framework IOKit"
|
||||
"-framework ForceFeedback"
|
||||
"-framework Carbon"
|
||||
"-framework CoreVideo"
|
||||
"-framework Metal"
|
||||
"-framework QuartzCore"
|
||||
"-framework AudioToolbox"
|
||||
"-framework CoreAudio"
|
||||
"-framework GameController"
|
||||
"-framework CoreHaptics"
|
||||
"-framework AVFoundation"
|
||||
"-framework CoreMedia"
|
||||
"-framework CoreFoundation"
|
||||
"-framework Foundation"
|
||||
"-framework OpenGL"
|
||||
)
|
||||
elseif(UNIX)
|
||||
# Static SDL2 pulls Wayland/X11 extras; FreeType needs bz2/png.
|
||||
set(SystemLibraries ${SystemLibraries}
|
||||
dl pthread m rt bz2 png
|
||||
X11 Xext Xcursor Xrandr Xxf86vm Xi Xss Xinerama
|
||||
wayland-client wayland-cursor wayland-egl xkbcommon
|
||||
asound
|
||||
)
|
||||
# OpenAL Soft may compile the sndio backend when libsndio-dev is present.
|
||||
# GitHub Actions runners typically lack libsndio, so only link when found.
|
||||
find_library(EVENGINE_SNDIO_LIBRARY sndio)
|
||||
if(EVENGINE_SNDIO_LIBRARY)
|
||||
list(APPEND SystemLibraries sndio)
|
||||
endif()
|
||||
# Engine entry-point sources include common/config.h / cmdline/*.h directly;
|
||||
# link the shared include set explicitly (also propagates the third-party
|
||||
# link directories needed by the bare-name ${ThirdParty} list).
|
||||
if(TARGET ${EVENGINE_NATIVE_TARGET})
|
||||
# Plain signature: the target's other links use the plain form.
|
||||
target_link_libraries(${EVENGINE_NATIVE_TARGET} eve_engine_includes)
|
||||
endif()
|
||||
|
||||
# Platform system libraries, shared with the unit-test runner
|
||||
# (see cmake/system_libraries.cmake).
|
||||
eve_append_system_libraries(SystemLibraries)
|
||||
|
||||
# Third-party link list, derived from the module manifest: only the libraries
|
||||
# the enabled modules actually need, in the canonical order GNU ld requires.
|
||||
# See cmake/thirdparty_libs.cmake for the group -> link-name mapping.
|
||||
|
||||
@@ -225,6 +225,9 @@ if(_has_ui)
|
||||
target_compile_definitions(eve_imgui PUBLIC IMGUI_DISABLE_DEMO_WINDOWS)
|
||||
endif()
|
||||
|
||||
# eve_imgui may be INTERFACE (prebuilt mode) or STATIC; only the usage
|
||||
# requirements of the shared include set are needed either way.
|
||||
target_link_libraries(eve_imgui INTERFACE eve_engine_includes)
|
||||
target_link_libraries(EVUI PUBLIC eve_imgui)
|
||||
target_include_directories(EVUI PUBLIC ${CMAKE_SOURCE_DIR}/third-party/imgui)
|
||||
target_include_directories(EVUI BEFORE PUBLIC
|
||||
|
||||
Reference in new issue
Block a user