169 lines
6.7 KiB
CMake
169 lines
6.7 KiB
CMake
cmake_minimum_required(VERSION 3.20)
|
|
|
|
file(STRINGS "${LIST_FILE}" entries)
|
|
set(sources)
|
|
set(guard)
|
|
set(submodules)
|
|
set(includeDirectories)
|
|
set(reviewed)
|
|
foreach(entry IN LISTS entries)
|
|
string(FIND "${entry}" " " split)
|
|
string(SUBSTRING "${entry}" 0 ${split} section)
|
|
math(EXPR split "${split} + 1")
|
|
string(SUBSTRING "${entry}" ${split} -1 value)
|
|
if(section STREQUAL "sources")
|
|
list(APPEND sources "${value}")
|
|
elseif(section STREQUAL "guard")
|
|
list(APPEND guard "${value}")
|
|
elseif(section STREQUAL "submodules")
|
|
list(APPEND submodules "${value}")
|
|
elseif(section STREQUAL "includes")
|
|
list(APPEND includeDirectories "${value}")
|
|
elseif(section STREQUAL "reviewed")
|
|
list(APPEND reviewed "${value}")
|
|
endif()
|
|
endforeach()
|
|
list(SORT sources)
|
|
list(SORT guard)
|
|
get_filename_component(rootReal "${ROOT}" REALPATH)
|
|
get_filename_component(recompilerReal "${RECOMPILER_DIR}" REALPATH)
|
|
set(sourcesReal)
|
|
foreach(source IN LISTS sources)
|
|
get_filename_component(real "${source}" REALPATH)
|
|
list(APPEND sourcesReal "${real}")
|
|
endforeach()
|
|
|
|
set(failures)
|
|
set(manifest "${EXTRA}\n")
|
|
set(switches)
|
|
foreach(source IN LISTS sources)
|
|
if(NOT EXISTS "${source}")
|
|
continue()
|
|
endif()
|
|
file(SHA256 "${source}" digest)
|
|
file(RELATIVE_PATH relative "${ROOT}" "${source}")
|
|
string(APPEND manifest "${relative} ${digest}\n")
|
|
if(NOT source MATCHES "\\.(cpp|hpp|h)$")
|
|
continue()
|
|
endif()
|
|
file(STRINGS "${source}" lines REGEX "\"APS5_[A-Z0-9_]+\"")
|
|
foreach(line IN LISTS lines)
|
|
string(REGEX MATCHALL "\"APS5_[A-Z0-9_]+\"" names "${line}")
|
|
list(APPEND switches ${names})
|
|
endforeach()
|
|
string(FIND "${source}" "${RECOMPILER_DIR}/" inRecompiler)
|
|
if(NOT inRecompiler EQUAL 0)
|
|
continue()
|
|
endif()
|
|
get_filename_component(sourceDirectory "${source}" DIRECTORY)
|
|
file(STRINGS "${source}" lines REGEX "^[ \t]*#[ \t]*include[ \t]*\"[^\"]+\"")
|
|
foreach(line IN LISTS lines)
|
|
string(REGEX REPLACE "^[ \t]*#[ \t]*include[ \t]*\"([^\"]+)\".*$" "\\1" included "${line}")
|
|
set(resolved)
|
|
foreach(directory IN ITEMS "${sourceDirectory}" ${includeDirectories})
|
|
if(EXISTS "${directory}/${included}" AND NOT IS_DIRECTORY "${directory}/${included}")
|
|
get_filename_component(resolved "${directory}/${included}" REALPATH)
|
|
break()
|
|
endif()
|
|
endforeach()
|
|
file(RELATIVE_PATH relativeSource "${ROOT}" "${source}")
|
|
if(NOT resolved)
|
|
continue()
|
|
endif()
|
|
string(FIND "${resolved}" "${recompilerReal}/" resolvedInRecompiler)
|
|
string(FIND "${resolved}" "${rootReal}/3rdparty/" resolvedInThirdParty)
|
|
if(resolvedInRecompiler EQUAL 0 OR resolvedInThirdParty EQUAL 0 OR resolved IN_LIST sourcesReal)
|
|
continue()
|
|
endif()
|
|
file(RELATIVE_PATH relativeResolved "${rootReal}" "${resolved}")
|
|
list(APPEND failures "${relativeSource} includes ${relativeResolved}, which the shader disk cache key does not hash: add it to shaderCacheKeySources in core/shader/recompiler/CMakeLists.txt")
|
|
endforeach()
|
|
endforeach()
|
|
|
|
foreach(submodule IN LISTS submodules)
|
|
file(RELATIVE_PATH relative "${ROOT}" "${submodule}")
|
|
set(commit)
|
|
if(GIT)
|
|
execute_process(COMMAND "${GIT}" -C "${submodule}" rev-parse --show-toplevel HEAD
|
|
OUTPUT_VARIABLE output OUTPUT_STRIP_TRAILING_WHITESPACE RESULT_VARIABLE status ERROR_QUIET)
|
|
if(status EQUAL 0)
|
|
string(REPLACE "\n" ";" output "${output}")
|
|
list(GET output 0 topLevel)
|
|
list(GET output 1 head)
|
|
get_filename_component(topLevel "${topLevel}" REALPATH)
|
|
get_filename_component(submoduleReal "${submodule}" REALPATH)
|
|
if(topLevel STREQUAL submoduleReal)
|
|
set(commit "${head}")
|
|
endif()
|
|
endif()
|
|
endif()
|
|
if(NOT commit AND EXISTS "${submodule}/CMakeLists.txt")
|
|
file(SHA256 "${submodule}/CMakeLists.txt" digest)
|
|
set(commit "unversioned ${digest}")
|
|
endif()
|
|
string(APPEND manifest "submodule ${relative} ${commit}\n")
|
|
endforeach()
|
|
|
|
foreach(source IN LISTS guard)
|
|
if(NOT EXISTS "${source}")
|
|
continue()
|
|
endif()
|
|
file(RELATIVE_PATH relative "${ROOT}" "${source}")
|
|
file(STRINGS "${source}" lines REGEX "ShaderRecompiler|setenv|putenv")
|
|
foreach(line IN LISTS lines)
|
|
if(line MATCHES "using[ \t]+namespace[ \t]+ShaderRecompiler" OR line MATCHES "namespace[ \t]+[A-Za-z_][A-Za-z0-9_]*[ \t]*=[ \t]*(::)?ShaderRecompiler[ \t]*;")
|
|
list(APPEND failures "${relative} brings the ShaderRecompiler namespace in whole, which hides its calls from the shader disk cache key review: qualify them")
|
|
endif()
|
|
if(line MATCHES "(^|[^A-Za-z0-9_])(setenv|putenv|_putenv_s)[ \t]*\\(")
|
|
list(APPEND failures "${relative} sets an environment variable, which can change the recompiler's APS5_* switches behind the shader disk cache key")
|
|
endif()
|
|
string(REGEX MATCHALL "ShaderRecompiler::[A-Za-z_][A-Za-z0-9_]*(::[A-Za-z_][A-Za-z0-9_]*)*[ \t]*\\(" calls "${line}")
|
|
string(REGEX MATCHALL "using[ \t]+ShaderRecompiler::[A-Za-z_][A-Za-z0-9_]*(::[A-Za-z_][A-Za-z0-9_]*)*" declarations "${line}")
|
|
foreach(use IN LISTS calls declarations)
|
|
string(REGEX REPLACE "^(using[ \t]+)?ShaderRecompiler::([A-Za-z0-9_:]+).*$" "\\2" name "${use}")
|
|
if(NOT name IN_LIST reviewed)
|
|
list(APPEND failures "${relative} uses ShaderRecompiler::${name}, which has not been reviewed for the shader disk cache key: if it can change what a recompile produces other than through the RecompileRequest, key that input in ShaderDiskCache::BuildKey, then add the name to shaderCacheReviewedNames in core/shader/recompiler/CMakeLists.txt")
|
|
endif()
|
|
endforeach()
|
|
endforeach()
|
|
endforeach()
|
|
|
|
if(failures)
|
|
list(REMOVE_DUPLICATES failures)
|
|
list(JOIN failures "\n " failureText)
|
|
message(FATAL_ERROR "Shader disk cache key check failed:\n ${failureText}")
|
|
endif()
|
|
|
|
string(SHA256 version "${manifest}")
|
|
string(SUBSTRING "${version}" 0 16 version)
|
|
list(REMOVE_DUPLICATES switches)
|
|
list(SORT switches)
|
|
list(JOIN switches ",\n " switchList)
|
|
|
|
set(content "#ifndef CORE_SHADER_RECOMPILER_SHADERCACHEVERSION_HPP
|
|
#define CORE_SHADER_RECOMPILER_SHADERCACHEVERSION_HPP
|
|
|
|
#include <cstdint>
|
|
#include <string_view>
|
|
|
|
namespace ShaderRecompiler::ShaderDiskCache::Generated {
|
|
|
|
inline constexpr std::uint64_t SourceVersion = 0x${version}ull;
|
|
|
|
inline constexpr std::string_view RecompilerSwitches[] = {
|
|
${switchList}
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|
|
")
|
|
|
|
if(EXISTS "${OUTPUT}")
|
|
file(READ "${OUTPUT}" previous)
|
|
if(previous STREQUAL content)
|
|
return()
|
|
endif()
|
|
endif()
|
|
file(WRITE "${OUTPUT}" "${content}")
|