Skip to content

Commit

Permalink
Implement projection caching (incomplete) (#322)
Browse files Browse the repository at this point in the history
Unfortunately we still need to clear the mvid field for this to kick in.
  • Loading branch information
tristanlabelle authored Oct 1, 2024
1 parent 7cd0007 commit cc91e8b
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 4 deletions.
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()

0 comments on commit cc91e8b

Please sign in to comment.