mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-25 18:05:12 -04:00
Compile generated common contract bodies through wrappers for Ninja
This commit is contained in:
@@ -102,6 +102,31 @@ function(psxrecomp_execution_profile target)
|
||||
VERBATIM)
|
||||
endfunction()
|
||||
|
||||
# A materialized game shard can also be a configure/hash input. Compile an
|
||||
# include wrapper so Ninja does not give the shard both a generation rule and
|
||||
# CMake's input-file phony rule. Keep hashing the original body.
|
||||
function(_psx_execution_compile_source target source output)
|
||||
get_filename_component(_absolute "${source}" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
get_source_file_property(_generated "${_absolute}" GENERATED)
|
||||
if(NOT _generated)
|
||||
set(${output} "${source}" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
string(SHA256 _path_hash "${_absolute}")
|
||||
get_filename_component(_ext "${_absolute}" LAST_EXT)
|
||||
set(_wrapper "${CMAKE_CURRENT_BINARY_DIR}/psx_execution/${target}/sources/${_path_hash}${_ext}")
|
||||
file(CONFIGURE OUTPUT "${_wrapper}" CONTENT "#include \"@_absolute@\"\n" @ONLY)
|
||||
foreach(_property LANGUAGE COMPILE_DEFINITIONS COMPILE_OPTIONS COMPILE_FLAGS
|
||||
INCLUDE_DIRECTORIES OBJECT_DEPENDS SKIP_PRECOMPILE_HEADERS
|
||||
SKIP_UNITY_BUILD_INCLUSION)
|
||||
get_source_file_property(_value "${_absolute}" "${_property}")
|
||||
if(NOT _value STREQUAL "NOTFOUND")
|
||||
set_source_files_properties("${_wrapper}" PROPERTIES "${_property}" "${_value}")
|
||||
endif()
|
||||
endforeach()
|
||||
set(${output} "${_wrapper}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Both source lists implement the same caller contract. Exclude these files
|
||||
# from common target sources; exactly one list is linked. CONTRACT_FILES names
|
||||
# adapter headers/recipes whose changes also affect the implementation identity.
|
||||
@@ -134,34 +159,29 @@ function(psxrecomp_add_implementation target)
|
||||
endif()
|
||||
list(APPEND _inputs "${_absolute}")
|
||||
endforeach()
|
||||
# CONTRACT_FILES can include common generated game bodies already added by
|
||||
# runtime.cmake, not only selected replacement bodies. Normalize those
|
||||
# existing source entries before declaring their configure dependency.
|
||||
get_target_property(_common_sources ${target} SOURCES)
|
||||
set(_common_compile_sources "")
|
||||
foreach(_source IN LISTS _common_sources)
|
||||
if(_source MATCHES "^\\$<")
|
||||
list(APPEND _common_compile_sources "${_source}")
|
||||
continue()
|
||||
endif()
|
||||
get_filename_component(_absolute "${_source}" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
if(_absolute IN_LIST _inputs)
|
||||
_psx_execution_compile_source(${target} "${_absolute}" _compiled)
|
||||
list(APPEND _common_compile_sources "${_compiled}")
|
||||
else()
|
||||
list(APPEND _common_compile_sources "${_source}")
|
||||
endif()
|
||||
endforeach()
|
||||
set_property(TARGET ${target} PROPERTY SOURCES "${_common_compile_sources}")
|
||||
set(_compile_sources "")
|
||||
foreach(_source IN LISTS _selected)
|
||||
get_filename_component(_absolute "${_source}" ABSOLUTE BASE_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
get_source_file_property(_generated "${_absolute}" GENERATED)
|
||||
if(_generated)
|
||||
# runtime.cmake marks game shards GENERATED, though they are
|
||||
# materialized before configure. Giving Ninja that file both as
|
||||
# a compiled generated source and a configure dependency creates
|
||||
# two output rules (an empty generation rule and a CMake phony).
|
||||
# Compile an include wrapper instead. The original remains the
|
||||
# sole maintained body and configure/hash input; #include keeps
|
||||
# its relative includes and __FILE__ behavior intact.
|
||||
string(SHA256 _path_hash "${_absolute}")
|
||||
get_filename_component(_ext "${_absolute}" LAST_EXT)
|
||||
set(_wrapper "${CMAKE_CURRENT_BINARY_DIR}/psx_execution/${target}/sources/${_path_hash}${_ext}")
|
||||
file(CONFIGURE OUTPUT "${_wrapper}" CONTENT "#include \"@_absolute@\"\n" @ONLY)
|
||||
foreach(_property LANGUAGE COMPILE_DEFINITIONS COMPILE_OPTIONS COMPILE_FLAGS
|
||||
INCLUDE_DIRECTORIES OBJECT_DEPENDS SKIP_PRECOMPILE_HEADERS
|
||||
SKIP_UNITY_BUILD_INCLUSION)
|
||||
get_source_file_property(_value "${_absolute}" "${_property}")
|
||||
if(NOT _value STREQUAL "NOTFOUND")
|
||||
set_source_files_properties("${_wrapper}" PROPERTIES "${_property}" "${_value}")
|
||||
endif()
|
||||
endforeach()
|
||||
list(APPEND _compile_sources "${_wrapper}")
|
||||
else()
|
||||
list(APPEND _compile_sources "${_absolute}")
|
||||
endif()
|
||||
_psx_execution_compile_source(${target} "${_source}" _compiled)
|
||||
list(APPEND _compile_sources "${_compiled}")
|
||||
endforeach()
|
||||
target_sources(${target} PRIVATE ${_compile_sources})
|
||||
set_property(TARGET ${target} APPEND PROPERTY PSX_IMPLEMENTATION_FAMILIES "${I_NAME}")
|
||||
|
||||
@@ -28,7 +28,9 @@ def main():
|
||||
#include "netplay_content_gate.h"
|
||||
#include <stdio.h>
|
||||
extern int operation(int);
|
||||
extern int common_game_body(void);
|
||||
int main(int argc, char** argv) {
|
||||
if (common_game_body() != 5) return 4;
|
||||
char no_mods[65], modded[65], upper[65];
|
||||
if (!psx_execution_content_identity("", no_mods) ||
|
||||
!psx_execution_content_identity("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", modded) ||
|
||||
@@ -49,6 +51,7 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
''')
|
||||
(source / "hle.c").write_text("int operation(int x) { return x * 3; }\n")
|
||||
(source / "common.c").write_text("#ifndef COMMON_SOURCE_FLAG\n#error common source property lost\n#endif\nint common_game_body(void) { return 5; }\n")
|
||||
(source / "local_step.h").write_text("#define LOCAL_STEP 3\n")
|
||||
(source / "lle.c").write_text('#include "local_step.h"\n#ifndef LLE_SOURCE_FLAG\n#error source compile property lost\n#endif\nint operation(int x) { int s=0; while(x--) s+=LOCAL_STEP; return s; }\n')
|
||||
(source / "contract.h").write_text("/* caller contract revision 1 */\n")
|
||||
@@ -60,14 +63,16 @@ include("{root.as_posix()}/cmake/psx_execution_profile.cmake")
|
||||
# automatic configure/hash inputs without creating duplicate Ninja rules.
|
||||
set_source_files_properties("${{CMAKE_CURRENT_SOURCE_DIR}}/lle.c" PROPERTIES
|
||||
GENERATED TRUE COMPILE_DEFINITIONS LLE_SOURCE_FLAG=1)
|
||||
add_executable(fixture main.c "{root.as_posix()}/runtime/src/psx_sha256.c")
|
||||
set_source_files_properties("${{CMAKE_CURRENT_SOURCE_DIR}}/common.c" PROPERTIES
|
||||
GENERATED TRUE COMPILE_DEFINITIONS COMMON_SOURCE_FLAG=1)
|
||||
add_executable(fixture main.c common.c "{root.as_posix()}/runtime/src/psx_sha256.c")
|
||||
target_include_directories(fixture PRIVATE "{root.as_posix()}/runtime/include")
|
||||
add_executable(fixture-pgxp main.c "{root.as_posix()}/runtime/src/psx_sha256.c")
|
||||
add_executable(fixture-pgxp main.c common.c "{root.as_posix()}/runtime/src/psx_sha256.c")
|
||||
target_include_directories(fixture-pgxp PRIVATE "{root.as_posix()}/runtime/include")
|
||||
psxrecomp_execution_profile(fixture CONTRACT_FILES shared.h)
|
||||
psxrecomp_execution_profile(fixture-pgxp CONTRACT_FILES shared.h)
|
||||
psxrecomp_add_implementation(fixture NAME triple CONTRACT integer-v1
|
||||
HLE_SOURCES hle.c LLE_SOURCES lle.c CONTRACT_FILES contract.h)
|
||||
HLE_SOURCES hle.c LLE_SOURCES lle.c CONTRACT_FILES contract.h common.c)
|
||||
''')
|
||||
|
||||
def configure(profile, name=None, ok=True):
|
||||
@@ -125,6 +130,13 @@ psxrecomp_add_implementation(fixture NAME triple CONTRACT integer-v1
|
||||
assert changed_contract["identity"] != changed["identity"]
|
||||
(source / "shared.h").write_text("/* shared service revision 2 */\n")
|
||||
assert build_run(enhanced_build)["identity"] != changed_contract["identity"]
|
||||
# Common generated bodies are compiled in both profiles and hashed as
|
||||
# caller contracts. Their edits must also reconfigure automatically.
|
||||
common_before = build_run(enhanced_build)
|
||||
reference_before = build_run(Path(temp) / "REFERENCE")
|
||||
(source / "common.c").write_text("int common_game_body(void) { return 2 + 3; }\n")
|
||||
assert build_run(enhanced_build)["identity"] != common_before["identity"]
|
||||
assert build_run(Path(temp) / "REFERENCE")["identity"] != reference_before["identity"]
|
||||
# Private HLE input is not required to build the maintained reference.
|
||||
(source / "hle.c").unlink()
|
||||
build_run(configure("REFERENCE", "reference-no-private"))
|
||||
|
||||
Reference in New Issue
Block a user