Skip to content

Commit

Permalink
Build the entire project from the root CMakeLists.txt (#304)
Browse files Browse the repository at this point in the history
  • Loading branch information
tristanlabelle committed Sep 20, 2024
1 parent f8ece3d commit ae379aa
Show file tree
Hide file tree
Showing 15 changed files with 191 additions and 531 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/build-and-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ on:
workflow_dispatch:

jobs:
support-spm:
spm-support:
name: SPM - Support Module
runs-on: windows-2022
timeout-minutes: 10
Expand All @@ -27,7 +27,7 @@ jobs:
shell: pwsh
run: swift test --verbose --skip-build

generator-and-interoptests-spm:
spm-generator-and-interoptests:
name: SPM - Generator and InteropTests
runs-on: windows-2022
timeout-minutes: 15
Expand All @@ -46,7 +46,7 @@ jobs:
shell: pwsh
run: swift test --verbose --skip-build

- name: Build Test WinRT Component
- name: Build WinRTComponent
working-directory: InteropTests
shell: pwsh
run: '& .\BuildAndGenerate.ps1'
Expand Down
30 changes: 18 additions & 12 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,23 @@ project(SwiftWinRT LANGUAGES C Swift)

add_subdirectory(Support)

include(ExternalProject)
# InteropTests depends on SwiftWinRT.exe, so build it now
message(STATUS "Configuring Generator subproject...")
execute_process(
COMMAND ${CMAKE_COMMAND}
-S "${CMAKE_CURRENT_SOURCE_DIR}/Generator"
-B "${CMAKE_CURRENT_BINARY_DIR}/Generator"
-G "${CMAKE_GENERATOR}"
-D "CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
-D "CMAKE_C_COMPILER=${CMAKE_C_COMPILER}"
-D "CMAKE_Swift_COMPILER=${CMAKE_Swift_COMPILER}"
COMMAND_ERROR_IS_FATAL ANY)

ExternalProject_Add(Generator
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/Generator
BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/Generator
INSTALL_COMMAND "")
set(SWIFT_WINRT_EXE ${CMAKE_CURRENT_BINARY_DIR}/Generator/Sources/SwiftWinRT/SwiftWinRT.exe)
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")

ExternalProject_Add(InteropTests
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/InteropTests
BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/InteropTests
CMAKE_ARGS -DSWIFT_WINRT_EXE=${SWIFT_WINRT_EXE}
INSTALL_COMMAND ""
DEPENDS Generator)
# Now build InteropTests, which depends on SWIFT_WINRT_EXE
add_subdirectory(InteropTests)
2 changes: 1 addition & 1 deletion Generator/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ let package = Package(
.product(name: "DotNetMetadata", package: "swift-dotnetmetadata")
],
path: "Sources/SwiftWinRT",
exclude: [ "CMakeLists.txt" ],
exclude: [ "CMakeLists.txt", "Extensions/CMakeLists.txt" ],
resources: [
// Avoid the .swift extension or SPM will pick those up a source files.
.embedInCode("Extensions/WindowsFoundation_IAsyncAction_swift"),
Expand Down
16 changes: 3 additions & 13 deletions Generator/Sources/SwiftWinRT/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,18 +1,8 @@
add_subdirectory(Extensions)

file(GLOB_RECURSE SOURCES *.swift)
add_executable(SwiftWinRT ${SOURCES})

file(GLOB RESOURCES Extensions/*_swift)
set(PACKAGERESOURCES_SWIFT ${CMAKE_CURRENT_BINARY_DIR}/PackageResources.swift)
file(WRITE ${PACKAGERESOURCES_SWIFT} "enum PackageResources {\n")
foreach(RESOURCE ${RESOURCES})
get_filename_component(RESOURCE_NAME ${RESOURCE} NAME)
file(READ ${RESOURCE} RESOURCE_HEX HEX)
string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1," RESOURCE_HEX ${RESOURCE_HEX})
file(APPEND ${PACKAGERESOURCES_SWIFT} " static let ${RESOURCE_NAME}: [UInt8] = [ ${RESOURCE_HEX} ]\n")
endforeach()
file(APPEND ${PACKAGERESOURCES_SWIFT} "}\n")
target_sources(SwiftWinRT PRIVATE ${PACKAGERESOURCES_SWIFT})

target_sources(SwiftWinRT PRIVATE "${PACKAGERESOURCES_SWIFT_FILE}")
target_link_libraries(SwiftWinRT PRIVATE
ArgumentParser Collections DotNetMetadata DotNetMetadataFormat WindowsMetadata
CodeWriters ProjectionModel)
23 changes: 23 additions & 0 deletions Generator/Sources/SwiftWinRT/Extensions/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Build the resource embedding code
set(PACKAGERESOURCES_CODE "enum PackageResources {\n")
file(GLOB RESOURCES "*_swift")
foreach(RESOURCE ${RESOURCES})
get_filename_component(RESOURCE_NAME ${RESOURCE} NAME)
file(READ ${RESOURCE} RESOURCE_HEX HEX)
string(REGEX REPLACE "([0-9a-f][0-9a-f])" "0x\\1," RESOURCE_HEX ${RESOURCE_HEX})
string(APPEND PACKAGERESOURCES_CODE " static let ${RESOURCE_NAME}: [UInt8] = [ ${RESOURCE_HEX} ]\n")
endforeach()
string(APPEND PACKAGERESOURCES_CODE "}\n")

# Update the file if the code has changed
set(PACKAGERESOURCES_SWIFT_FILE "${CMAKE_CURRENT_BINARY_DIR}/PackageResources.swift")
set(PACKAGERESOURCES_OLD_CODE "")
if(EXISTS "${PACKAGERESOURCES_SWIFT_FILE}")
file(READ "${PACKAGERESOURCES_SWIFT_FILE}" PACKAGERESOURCES_OLD_CODE)
endif()
if(NOT "${PACKAGERESOURCES_CODE}" STREQUAL "${PACKAGERESOURCES_OLD_CODE}")
file(WRITE "${PACKAGERESOURCES_SWIFT_FILE}" "${PACKAGERESOURCES_CODE}")
endif()

# Return the path
set(PACKAGERESOURCES_SWIFT_FILE "${PACKAGERESOURCES_SWIFT_FILE}" PARENT_SCOPE)
8 changes: 6 additions & 2 deletions InteropTests/BuildAndGenerate.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@ if ($LASTEXITCODE -ne 0) { throw "Failed to build SwiftWinRT.exe" }
$SwiftWinRT = "$GeneratorProjectDir\.build\$SwiftConfiguration\SwiftWinRT.exe"

Write-Host -ForegroundColor Cyan "Building WinRTComponent.dll & winmd..."
$MSBuildConfiguration = if ($Release) { "Release" } else { "Debug" }
$WinRTComponentBinDir = & "$PSScriptRoot\WinRTComponent\Build.ps1" -Configuration $MSBuildConfiguration
$CMakePreset = if ($Release) { "release" } else { "debug" }
Push-Location "$PSScriptRoot\WinRTComponent"
& cmake.exe --preset $CMakePreset
& cmake.exe --build --preset $CMakePreset
Pop-Location
$WinRTComponentBinDir = "$PSScriptRoot\WinRTComponent\build\$CMakePreset"

Write-Host -ForegroundColor Cyan "Generating Swift projection for WinRT component..."
& "$PSScriptRoot\GenerateProjection.ps1" -SwiftWinRT $SwiftWinRT -WinMD "$WinRTComponentBinDir\WinRTComponent.winmd"
Expand Down
51 changes: 32 additions & 19 deletions InteropTests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,40 +1,53 @@
cmake_minimum_required(VERSION 3.21.0)

project(InteropTests LANGUAGES C Swift)
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")
endif()
cmake_path(ABSOLUTE_PATH SWIFT_WINRT_EXE NORMALIZE OUTPUT_VARIABLE SWIFT_WINRT_EXE)

# Build WinRTComponent.winmd/dll
message(STATUS "Building WinRTComponent...")
cmake_path(CONVERT "${CMAKE_CURRENT_SOURCE_DIR}/WinRTComponent/Build.ps1" TO_NATIVE_PATH_LIST SCRIPT_PATH_ARG)
set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS "${SCRIPT_PATH_ARG}")
cmake_path(CONVERT "${CMAKE_CURRENT_BINARY_DIR}/WinRTComponent" TO_NATIVE_PATH_LIST BINARY_DIR_BASE_ARG)
# 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 powershell.exe -File "${SCRIPT_PATH_ARG}"
-BinaryDirBase "${BINARY_DIR_BASE_ARG}"
COMMAND ${CMAKE_COMMAND}
--build "${CMAKE_CURRENT_BINARY_DIR}/WinRTComponent"
COMMAND_ERROR_IS_FATAL ANY)
set(WINRTCOMPONENT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/WinRTComponent/bin/WinRTComponent")
set(WINRTCOMPONENT_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/WinRTComponent")

# 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_ARG)
cmake_path(CONVERT "${SWIFT_WINRT_EXE}" TO_NATIVE_PATH_LIST SWIFT_WINRT_EXE_ARG)
cmake_path(CONVERT "${WINRTCOMPONENT_BINARY_DIR}/WinRTComponent.winmd" TO_NATIVE_PATH_LIST WINMD_ARG)
cmake_path(CONVERT "${CMAKE_CURRENT_BINARY_DIR}/Generated/Sources" TO_NATIVE_PATH_LIST OUTPUT_DIR_ARG)
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 "${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_ARG}"
-SwiftWinRT "${SWIFT_WINRT_EXE_ARG}"
-WinMD "${WINMD_ARG}"
-OutputDir "${OUTPUT_DIR_ARG}"
COMMAND powershell.exe -File "${SCRIPT_PATH_NATIVE}"
-SwiftWinRT "${SWIFT_WINRT_EXE_NATIVE}"
-WinMD "${WINMD_NATIVE}"
-OutputDir "${OUTPUT_DIR_NATIVE}"
COMMAND_ERROR_IS_FATAL ANY)

# Build the Swift projection
add_subdirectory(../Support ${CMAKE_CURRENT_BINARY_DIR}/Support)
# 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")
endif()

# Build the Swift projection
# TODO(https://github.com/tristanlabelle/swift-winrt/issues/302): Fix linking issues
# add_subdirectory(
# ${CMAKE_CURRENT_BINARY_DIR}/Generated/Sources
Expand Down
6 changes: 0 additions & 6 deletions InteropTests/WinRTComponent/.gitignore

This file was deleted.

40 changes: 0 additions & 40 deletions InteropTests/WinRTComponent/Build.ps1

This file was deleted.

50 changes: 50 additions & 0 deletions InteropTests/WinRTComponent/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
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 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")
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}"
-reference "${WINSDK_VERSION}"
-component "${CPPWINRT_GENERATED_DIR_NATIVE}" -overwrite -optimize
-output "${CPPWINRT_GENERATED_DIR_NATIVE}"
COMMAND_ERROR_IS_FATAL ANY)

# Build WinRTComponent.dll
file(GLOB SOURCES "*.cpp")
add_library(WinRTComponent SHARED
${SOURCES}
"${CPPWINRT_GENERATED_DIR}/module.g.cpp" # Other .g.cpp files are #included by our .cpp files
WinRTComponent.def)
target_include_directories(WinRTComponent PRIVATE
"${CMAKE_CURRENT_SOURCES_DIR}"
"${CPPWINRT_GENERATED_DIR}")
target_precompile_headers(WinRTComponent PRIVATE pch.h)
28 changes: 28 additions & 0 deletions InteropTests/WinRTComponent/CMakePresets.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"version": 3,
"cmakeMinimumRequired": {
"major": 3,
"minor": 21,
"patch": 0
},
"configurePresets": [
{
"name": "debug",
"displayName": "Debug",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build/debug",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"CMAKE_CXX_COMPILER": "cl",
"CMAKE_CXX_FLAGS": "/std:c++latest /W4 /EHsc"
}
}
],
"buildPresets": [
{
"name": "debug",
"displayName": "Debug",
"configurePreset": "debug"
}
]
}
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
// Includes all .idl files so we have a single <Midl Include="All.idl"> entry in the vcxproj.
// This speeds up the build by avoiding multiple midlrt calls followed by an mdmerge step.
#include "Arrays.idl"
#include "ByteBuffers.idl"
#include "Collections.idl"
#include "DateTimes.idl"
#include "Enums.idl"
#include "Errors.idl"
#include "Events.idl"
#include "ForCustomActivationFactoryResolution.idl"
#include "InspectableBoxing.idl"
#include "Int32Wrapper.idl"
#include "InterfaceCasting.idl"
#include "ManualAsyncOperation.idl"
#include "MinimalTypes.idl"
#include "MinimalUnsealedClasses.idl"
#include "NullValues.idl"
#include "Numbers.idl"
#include "ObjectReferencer.idl"
#include "OutputArgument.idl"
#include "OverloadedSum.idl"
#include "ReferenceBoxing.idl"
#include "ReturnArgument.idl"
#include "Strings.idl"
#include "Structs.idl"
#include "SwiftAttributes.idl"
#include "SwiftEnum.idl"
// Includes all .idl files so we have a single <Midl Include="All.idl"> entry in the vcxproj.
// This speeds up the build by avoiding multiple midlrt calls followed by an mdmerge step.
#include "Arrays.idl"
#include "ByteBuffers.idl"
#include "Collections.idl"
#include "DateTimes.idl"
#include "Enums.idl"
#include "Errors.idl"
#include "Events.idl"
#include "ForCustomActivationFactoryResolution.idl"
#include "InspectableBoxing.idl"
#include "Int32Wrapper.idl"
#include "InterfaceCasting.idl"
#include "ManualAsyncOperation.idl"
#include "MinimalTypes.idl"
#include "MinimalUnsealedClasses.idl"
#include "NullValues.idl"
#include "Numbers.idl"
#include "ObjectReferencer.idl"
#include "OutputArgument.idl"
#include "OverloadedSum.idl"
#include "ReferenceBoxing.idl"
#include "ReturnArgument.idl"
#include "Strings.idl"
#include "Structs.idl"
#include "SwiftAttributes.idl"
#include "SwiftEnum.idl"
#include "WeakReferencer.idl"
Loading

0 comments on commit ae379aa

Please sign in to comment.