Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement projection caching (incomplete) #322

Merged
merged 1 commit into from
Oct 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions Generator/InteropTests/WinRTComponent/Clear-PEDateTimeStamp.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[CmdletBinding(PositionalBinding=$false)]
param(
[Parameter(Mandatory=$true)]
[string] $In,
[Parameter(Mandatory=$true)]
[string] $Out
)

$ErrorActionPreference = "Stop"

$PEBytes = [IO.File]::ReadAllBytes($In)
$MSDosSignature = [BitConverter]::ToUInt16($PEBytes, 0x0)
if ($MSDosSignature -ne 0x5A4D) { throw "Invalid MS-DOS signature" } # "MZ", little endian
$PEHeaderOffset = [BitConverter]::ToInt32($PEBytes, 0x3C)
$PESignature = [BitConverter]::ToInt32($PEBytes, $PEHeaderOffset)
if ($PESignature -ne 0x4550) { throw "Invalid PE signature" } # "PE\0\0", little endian
$PETimeDateStampOffset = $PEHeaderOffset + 0x8
[Array]::Clear($PEBytes, $PETimeDateStampOffset, 0x4)
[IO.File]::WriteAllBytes($Out, $PEBytes)
31 changes: 28 additions & 3 deletions Generator/InteropTests/WinRTComponent/GenerateProjection.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,39 @@ function(generate_projection)
message(FATAL_ERROR "PROJECTION_DIR argument is required")
endif()

string(REPLACE "\\" "" WINDOWS_SDK_VERSION "$ENV{WindowsSDKVersion}") # Remove trailing slash

# Determine the support package directory
execute_process(
COMMAND git.exe -C "${CMAKE_CURRENT_SOURCE_DIR}" rev-parse --path-format=absolute --show-toplevel
OUTPUT_VARIABLE REPO_ROOT
OUTPUT_VARIABLE SPM_SUPPORT_PACKAGE_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE
COMMAND_ERROR_IS_FATAL ANY)

# Skip if the inputs have not changed
file(SHA256 "${ARG_SWIFTWINRT_EXE}" SWIFTWINRT_EXE_HASH)
file(SHA256 "${ARG_WINRTCOMPONENT_WINMD}" WINRTCOMPONENT_WINMD_HASH)
file(SHA256 "${ARG_PROJECTION_JSON}" PROJECTION_JSON_HASH)
set(CACHE_KEY
"SwiftWinRT.exe: ${SWIFTWINRT_EXE_HASH}"
"WinRTComponent.winmd: ${WINRTCOMPONENT_WINMD_HASH}"
"Projection.json: ${PROJECTION_JSON_HASH}"
"Projection directory: ${ARG_PROJECTION_DIR}"
"Support package directory: ${SPM_SUPPORT_PACKAGE_DIR}"
"Windows SDK version: ${WINDOWS_SDK_VERSION}")
string(REPLACE ";" "\n" CACHE_KEY "${CACHE_KEY}")
if(EXISTS "${CMAKE_CURRENT_BINARY_DIR}/ProjectionCacheKey.txt")
file(READ "${CMAKE_CURRENT_BINARY_DIR}/ProjectionCacheKey.txt" PREVIOUS_CACHE_KEY)
if("${PREVIOUS_CACHE_KEY}" STREQUAL "${CACHE_KEY}")
message(STATUS "Skipping projection generation because the inputs have not changed")
return()
endif()
endif()

# Generate the projection
cmake_path(CONVERT "${ARG_PROJECTION_JSON}" TO_NATIVE_PATH_LIST PROJECTION_JSON_NATIVE)
string(REPLACE "\\" "" WINDOWS_SDK_VERSION "$ENV{WindowsSDKVersion}") # Remove trailing slash
cmake_path(CONVERT "${ARG_WINRTCOMPONENT_WINMD}" TO_NATIVE_PATH_LIST WINRTCOMPONENT_WINMD_NATIVE)
cmake_path(CONVERT "${REPO_ROOT}" TO_NATIVE_PATH_LIST SPM_SUPPORT_PACKAGE_DIR_NATIVE)
cmake_path(CONVERT "${SPM_SUPPORT_PACKAGE_DIR}" TO_NATIVE_PATH_LIST SPM_SUPPORT_PACKAGE_DIR_NATIVE)
cmake_path(CONVERT "${ARG_PROJECTION_DIR}" TO_NATIVE_PATH_LIST PROJECTION_DIR_NATIVE)
execute_process(
COMMAND "${ARG_SWIFTWINRT_EXE}"
Expand All @@ -44,6 +66,9 @@ function(generate_projection)
--out "${PROJECTION_DIR_NATIVE}"
--out-manifest "${PROJECTION_DIR_NATIVE}\\WinRTComponent.manifest"
COMMAND_ERROR_IS_FATAL ANY)

# Save the cache key
file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/ProjectionCacheKey.txt" "${CACHE_KEY}")
endfunction()

# Support running as a script
Expand Down
10 changes: 9 additions & 1 deletion Generator/InteropTests/WinRTComponent/GenerateWinMD.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,16 @@ function(generate_winrtcomponent_winmd)
/metadata_dir "${METADATA_DIR_NATIVE}"
/reference "${FOUNDATIONCONTRACT_WINMD_NATIVE}"
/reference "${UNIVERSALAPICONTRACT_WINMD_NATIVE}"
/winmd "${WINRTCOMPONENT_WINMD_NATIVE}"
/winmd "${WINRTCOMPONENT_WINMD_NATIVE}.timestamped"
/header "${WINRTCOMPONENT_H_NATIVE}"
"${WINRTCOMPONENT_IDL_NATIVE}"
COMMAND_ERROR_IS_FATAL ANY)

# Remove the timestamp from the generated WinRTComponent.winmd file for cachability
# TODO: We also need to zero the random "mvid" (module version id) field of the module metadata table :/
execute_process(
COMMAND powershell.exe -File "${CMAKE_CURRENT_SOURCE_DIR}/Clear-PEDateTimeStamp.ps1"
-In "${WINRTCOMPONENT_WINMD_NATIVE}.timestamped"
-Out "${WINRTCOMPONENT_WINMD_NATIVE}"
COMMAND_ERROR_IS_FATAL ANY)
endfunction()
Loading