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

Extract GenerateWinMD.cmake to avoid recursive CMake invocation #307

Merged
merged 1 commit into from
Sep 21, 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
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ message(STATUS "Building Generator subproject...")
execute_process(
COMMAND ${CMAKE_COMMAND} --build "${CMAKE_CURRENT_BINARY_DIR}/Generator"
COMMAND_ERROR_IS_FATAL ANY)
set(SWIFT_WINRT_EXE "${CMAKE_CURRENT_BINARY_DIR}/Generator/Sources/SwiftWinRT/SwiftWinRT.exe")
set(SWIFTWINRT_EXE "${CMAKE_CURRENT_BINARY_DIR}/Generator/Sources/SwiftWinRT/SwiftWinRT.exe")

# Now build InteropTests, which depends on SWIFT_WINRT_EXE
# Now build InteropTests, which depends on SWIFTWINRT_EXE
add_subdirectory(InteropTests)
47 changes: 23 additions & 24 deletions InteropTests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,44 +4,43 @@ if(NOT DEFINED CMAKE_PROJECT_NAME)
project(InteropTests LANGUAGES C Swift)
endif()

if (NOT DEFINED SWIFT_WINRT_EXE)
message(FATAL_ERROR "SWIFT_WINRT_EXE must be defined")
if (NOT DEFINED SWIFTWINRT_EXE)
message(FATAL_ERROR "SWIFTWINRT_EXE must be defined")
endif()
cmake_path(ABSOLUTE_PATH SWIFT_WINRT_EXE NORMALIZE OUTPUT_VARIABLE SWIFT_WINRT_EXE)
cmake_path(ABSOLUTE_PATH SWIFTWINRT_EXE NORMALIZE OUTPUT_VARIABLE SWIFTWINRT_EXE)

# Generating projection sources will depend on WinRTComponent.winmd, so build it now
message(STATUS "Configuring WinRTComponent subproject...")
execute_process(
COMMAND ${CMAKE_COMMAND}
-S "${CMAKE_CURRENT_SOURCE_DIR}/WinRTComponent"
-B "${CMAKE_CURRENT_BINARY_DIR}/WinRTComponent"
-G "${CMAKE_GENERATOR}"
-D "CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
-D CMAKE_CXX_COMPILER=cl.exe
-D "CMAKE_CXX_FLAGS=/std:c++latest /W4 /EHsc"
COMMAND_ERROR_IS_FATAL ANY)

message(STATUS "Building WinRTComponent subproject...")
execute_process(
COMMAND ${CMAKE_COMMAND}
--build "${CMAKE_CURRENT_BINARY_DIR}/WinRTComponent"
COMMAND_ERROR_IS_FATAL ANY)
set(WINRTCOMPONENT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/WinRTComponent")
set(WINRTCOMPONENT_IDL "${CMAKE_CURRENT_SOURCE_DIR}/WinRTComponent/WinRTComponent.idl")
set(WINRTCOMPONENT_WINMD "${CMAKE_CURRENT_BINARY_DIR}/WinRTComponent.winmd")
include(WinRTComponent/GenerateWinMD.cmake)

# Generate Swift projection
message(STATUS "Generating Swift projection for WinRTComponent...")
cmake_path(CONVERT "${CMAKE_CURRENT_SOURCE_DIR}/GenerateProjection.ps1" TO_NATIVE_PATH_LIST SCRIPT_PATH_NATIVE)
cmake_path(CONVERT "${SWIFT_WINRT_EXE}" TO_NATIVE_PATH_LIST SWIFT_WINRT_EXE_NATIVE)
cmake_path(CONVERT "${WINRTCOMPONENT_BINARY_DIR}/WinRTComponent.winmd" TO_NATIVE_PATH_LIST WINMD_NATIVE)
cmake_path(CONVERT "${SWIFTWINRT_EXE}" TO_NATIVE_PATH_LIST SWIFTWINRT_EXE_NATIVE)
cmake_path(CONVERT "${WINRTCOMPONENT_WINMD}" TO_NATIVE_PATH_LIST WINRTCOMPONENT_WINMD_NATIVE)
cmake_path(CONVERT "${CMAKE_CURRENT_BINARY_DIR}/Generated/Sources" TO_NATIVE_PATH_LIST OUTPUT_DIR_NATIVE)
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${SCRIPT_PATH_ARG}")
execute_process(
COMMAND powershell.exe -File "${SCRIPT_PATH_NATIVE}"
-SwiftWinRT "${SWIFT_WINRT_EXE_NATIVE}"
-WinMD "${WINMD_NATIVE}"
-SwiftWinRT "${SWIFTWINRT_EXE_NATIVE}"
-WinMD "${WINRTCOMPONENT_WINMD_NATIVE}"
-OutputDir "${OUTPUT_DIR_NATIVE}"
COMMAND_ERROR_IS_FATAL ANY)

# Define WinRTComponent build (requires the cl.exe compiler)
include(ExternalProject)
message(STATUS "Building WinRTComponent...")
ExternalProject_Add(WinRTComponent
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/WinRTComponent"
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/WinRTComponent"
CMAKE_ARGS
-D "WINRTCOMPONENT_WINMD=${WINRTCOMPONENT_WINMD}"
-D "CMAKE_CXX_COMPILER=cl.exe"
-D "CMAKE_CXX_FLAGS=/std:c++latest /W4 /EHsc"
INSTALL_COMMAND ""
TEST_COMMAND "")

# Build the support module if not already the case (by root CMakeLists.txt)
if(NOT TARGET WindowsRuntime)
add_subdirectory(../Support "${CMAKE_CURRENT_BINARY_DIR}/Support")
Expand Down
38 changes: 13 additions & 25 deletions InteropTests/WinRTComponent/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,23 @@ cmake_minimum_required(VERSION 3.21.0)

project(WinRTComponent LANGUAGES CXX)

# Generate the WinMDs from the idl files
message(STATUS "Generating WinRTComponent.winmd...")
set(MIDLRT.EXE_PATH_NATIVE "$ENV{WindowsSdkVerBinPath}$ENV{VSCMD_ARG_HOST_ARCH}\\midlrt.exe")
cmake_path(CONVERT "$ENV{WindowsSdkDir}References\\$ENV{WindowsSDKVersion}" TO_CMAKE_PATH_LIST WINSDK_REFERENCES_DIR NORMALIZE)
set(FOUNDATIONCONTRACT_DIR "${WINSDK_REFERENCES_DIR}/Windows.Foundation.FoundationContract/4.0.0.0")
cmake_path(CONVERT "${FOUNDATIONCONTRACT_DIR}" TO_NATIVE_PATH_LIST METADATA_DIR_NATIVE)
cmake_path(CONVERT "${FOUNDATIONCONTRACT_DIR}/Windows.Foundation.FoundationContract.winmd" TO_NATIVE_PATH_LIST FOUNDATIONCONTRACT_WINMD_NATIVE)
cmake_path(CONVERT "${WINSDK_REFERENCES_DIR}/Windows.Foundation.UniversalApiContract/15.0.0.0/Windows.Foundation.UniversalApiContract.winmd" TO_NATIVE_PATH_LIST UNIVERSALAPICONTRACT_WINMD_NATIVE)
cmake_path(CONVERT "${CMAKE_CURRENT_BINARY_DIR}/WinRTComponent.winmd" TO_NATIVE_PATH_LIST WINRTCOMPONENT_WINMD_PATH_NATIVE)
cmake_path(CONVERT "${CMAKE_CURRENT_BINARY_DIR}/WinRTComponent.h" TO_NATIVE_PATH_LIST WINRTCOMPONENT_H_PATH_NATIVE)
cmake_path(CONVERT "${CMAKE_CURRENT_SOURCE_DIR}/WinRTComponent.idl" TO_NATIVE_PATH_LIST IDL_PATH_NATIVE)
execute_process(
COMMAND "${MIDLRT.EXE_PATH_NATIVE}"
/W1 /nologo /nomidl
/metadata_dir "${METADATA_DIR_NATIVE}"
/reference "${FOUNDATIONCONTRACT_WINMD_NATIVE}"
/reference "${UNIVERSALAPICONTRACT_WINMD_NATIVE}"
/winmd "${WINRTCOMPONENT_WINMD_PATH_NATIVE}"
/header "${WINRTCOMPONENT_H_PATH_NATIVE}"
"${IDL_PATH_NATIVE}"
COMMAND_ERROR_IS_FATAL ANY)
# Generate the WinRTComponent.winmd file if not previously done
if(NOT DEFINED WINRTCOMPONENT_WINMD)
set(WINRTCOMPONENT_IDL "${CMAKE_CURRENT_SOURCE_DIR}/WinRTComponent.idl")
set(WINRTCOMPONENT_WINMD "${CMAKE_CURRENT_BINARY_DIR}/WinRTComponent.winmd")
include(GenerateWinMD.cmake)
endif()

# Generate the C++/WinRT boilerplate
message(STATUS "Generating C++/WinRT boilerplate for WinRTComponent...")
set(CPPWINRT.EXE_PATH_NATIVE "$ENV{WindowsSdkVerBinPath}$ENV{VSCMD_ARG_HOST_ARCH}\\cppwinrt.exe")
set(CPPWINRT_EXE_NATIVE "$ENV{WindowsSdkVerBinPath}$ENV{VSCMD_ARG_HOST_ARCH}\\cppwinrt.exe")
cmake_path(CONVERT "${WINRTCOMPONENT_WINMD}" TO_NATIVE_PATH_LIST WINRTCOMPONENT_WINMD_NATIVE)
string(REPLACE "\\" "" WINSDK_VERSION "$ENV{WindowsSDKVersion}")
set(CPPWINRT_GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/CppWinRT")
cmake_path(CONVERT "${CPPWINRT_GENERATED_DIR}" TO_NATIVE_PATH_LIST CPPWINRT_GENERATED_DIR_NATIVE)
execute_process(
COMMAND "${CPPWINRT.EXE_PATH_NATIVE}"
-input "${WINRTCOMPONENT_WINMD_PATH_NATIVE}"
COMMAND "${CPPWINRT_EXE_NATIVE}"
-input "${WINRTCOMPONENT_WINMD_NATIVE}"
-reference "${WINSDK_VERSION}"
-component "${CPPWINRT_GENERATED_DIR_NATIVE}" -overwrite -optimize
-output "${CPPWINRT_GENERATED_DIR_NATIVE}"
Expand All @@ -47,4 +33,6 @@ add_library(WinRTComponent SHARED
target_include_directories(WinRTComponent PRIVATE
"${CMAKE_CURRENT_SOURCES_DIR}"
"${CPPWINRT_GENERATED_DIR}")
target_precompile_headers(WinRTComponent PRIVATE pch.h)
target_precompile_headers(WinRTComponent PRIVATE pch.h)

set(WINRTCOMPONENT_WINMD "${CMAKE_CURRENT_BINARY_DIR}/WinRTComponent.winmd" PARENT_SCOPE)
29 changes: 29 additions & 0 deletions InteropTests/WinRTComponent/GenerateWinMD.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Generates the WinRTComponent.winmd file from the WinRTComponent.idl file.
if(NOT DEFINED WINRTCOMPONENT_IDL)
message(FATAL_ERROR "WINRTCOMPONENT_IDL is not defined")
endif()

if(NOT DEFINED WINRTCOMPONENT_WINMD)
message(FATAL_ERROR "WINRTCOMPONENT_WINMD_PATH is not defined")
endif()

message(STATUS "Generating WinRTComponent.winmd...")
set(MIDLRT_EXE_NATIVE "$ENV{WindowsSdkVerBinPath}$ENV{VSCMD_ARG_HOST_ARCH}\\midlrt.exe")
cmake_path(CONVERT "$ENV{WindowsSdkDir}References\\$ENV{WindowsSDKVersion}" TO_CMAKE_PATH_LIST WINSDK_REFERENCES_DIR NORMALIZE)
set(FOUNDATIONCONTRACT_DIR "${WINSDK_REFERENCES_DIR}/Windows.Foundation.FoundationContract/4.0.0.0")
cmake_path(CONVERT "${FOUNDATIONCONTRACT_DIR}" TO_NATIVE_PATH_LIST METADATA_DIR_NATIVE)
cmake_path(CONVERT "${FOUNDATIONCONTRACT_DIR}/Windows.Foundation.FoundationContract.winmd" TO_NATIVE_PATH_LIST FOUNDATIONCONTRACT_WINMD_NATIVE)
cmake_path(CONVERT "${WINSDK_REFERENCES_DIR}/Windows.Foundation.UniversalApiContract/15.0.0.0/Windows.Foundation.UniversalApiContract.winmd" TO_NATIVE_PATH_LIST UNIVERSALAPICONTRACT_WINMD_NATIVE)
cmake_path(CONVERT "${WINRTCOMPONENT_WINMD}" TO_NATIVE_PATH_LIST WINRTCOMPONENT_WINMD_NATIVE)
string(REPLACE ".winmd" ".h" WINRTCOMPONENT_H_NATIVE "${WINRTCOMPONENT_WINMD_NATIVE}")
cmake_path(CONVERT "${WINRTCOMPONENT_IDL}" TO_NATIVE_PATH_LIST WINRTCOMPONENT_IDL_NATIVE)
execute_process(
COMMAND "${MIDLRT_EXE_NATIVE}"
/W1 /nologo /nomidl
/metadata_dir "${METADATA_DIR_NATIVE}"
/reference "${FOUNDATIONCONTRACT_WINMD_NATIVE}"
/reference "${UNIVERSALAPICONTRACT_WINMD_NATIVE}"
/winmd "${WINRTCOMPONENT_WINMD_NATIVE}"
/header "${WINRTCOMPONENT_H_NATIVE}"
"${WINRTCOMPONENT_IDL_NATIVE}"
COMMAND_ERROR_IS_FATAL ANY)
Loading