Skip to content

Commit 04df903

Browse files
committed
CMake: Fixing cross-compiling Swift-Foundation
The macros must build for the local machine running the build, not the machine that Swift-Foundation will run on, in order for the build to be able to use the macros. To do this, the macro build must use ExternalProject, which treats the child project as an entirely independent project. One cannot introspect into the external project since it is configured at build time, rather than at configure time. This is what allows the external project to build for another platform. The expectation is that the calling project will pull the built products of the ExternalProject from the install location. EPs have an internal implicit install prefix where they can install stuff to without dirtying the building machine or installed products, so we can make use of that. In order for that to work, the products must actually get installed though, so we have to install the FoundationMacros, even when built as an executable. To support that, I've exposed an option to tell the macro build to build the macros as an executable. On the library side, I've exposed the Foundation macros as an interface library that only exposes the `-load-plugin-path` option needed for picking up the macro. Linking against this interface library will load the plugin as desired. This results in a build that - can use macros, even when cross-compiling. - does not install the macros into the installed library, only to the build directory.
1 parent fd4788a commit 04df903

File tree

3 files changed

+36
-24
lines changed

3 files changed

+36
-24
lines changed

Sources/CMakeLists.txt

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,31 @@
1212
##
1313
##===----------------------------------------------------------------------===##
1414

15+
if(NOT SwiftFoudation_MACRO)
16+
include(ExternalProject)
17+
# The macros are required for building Swift-Foundation. Build them for the
18+
# build machine.
19+
ExternalProject_Add(FoundationMacros
20+
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/FoundationMacros"
21+
INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/FoundationMacros"
22+
CMAKE_ARGS
23+
-DCMAKE_BUILD_TYPE=Release
24+
-DCMAKE_Swift_COMPILER=${CMAKE_Swift_COMPILER}
25+
-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
26+
-DSwiftFoundation_BUILD_EXECUTABLE_MACROS=YES)
27+
28+
ExternalProject_Get_Property(FoundationMacros INSTALL_DIR)
29+
add_library(FoundationBuildMacros INTERFACE)
30+
add_dependencies(FoundationBuildMacros FoundationMacros)
31+
32+
if(CMAKE_HOST_WIN32)
33+
set(_SwiftFoundation_HOST_EXECUTABLE_SUFFIX .exe)
34+
endif()
35+
36+
target_compile_options(FoundationBuildMacros INTERFACE
37+
"$<$<COMPILE_LANGUAGE:Swift>:SHELL:-load-plugin-executable ${INSTALL_DIR}/bin/FoundationMacros${_SwiftFoundation_HOST_EXECUTABLE_SUFFIX}#FoundationMacros>")
38+
endif()
39+
1540
add_subdirectory(_FoundationCShims)
1641
add_subdirectory(FoundationEssentials)
1742
add_subdirectory(FoundationInternationalization)

Sources/FoundationEssentials/CMakeLists.txt

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -55,21 +55,7 @@ if(SwiftFoundation_MACRO)
5555
target_compile_options(FoundationEssentials PRIVATE
5656
"SHELL:-plugin-path ${SwiftFoundation_MACRO}")
5757
else()
58-
message(STATUS "SwiftFoundation_MACRO not provided, building Foundation macros locally for host")
59-
# No path to Foundation macros was provided, so we must build it ourselves
60-
set(FoundationMacros_BuildLocalExecutable YES)
61-
FetchContent_Declare(FoundationMacros
62-
SOURCE_DIR ${CMAKE_SOURCE_DIR}/Sources/FoundationMacros)
63-
FetchContent_MakeAvailable(FoundationMacros)
64-
add_dependencies(FoundationEssentials FoundationMacros)
65-
get_target_property(MacroDIR FoundationMacros RUNTIME_OUTPUT_DIRECTORY)
66-
if(CMAKE_SYSTEM_NAME STREQUAL Windows)
67-
set(MacroExecutable "${MacroDIR}/FoundationMacros.exe#FoundationMacros")
68-
else()
69-
set(MacroExecutable "${MacroDIR}/FoundationMacros#FoundationMacros")
70-
endif()
71-
target_compile_options(FoundationEssentials PUBLIC
72-
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-load-plugin-executable ${MacroExecutable}>")
58+
target_link_libraries(FoundationEssentials PRIVATE FoundationBuildMacros)
7359
endif()
7460

7561
if(CMAKE_SYSTEM_NAME STREQUAL Linux OR CMAKE_SYSTEM_NAME STREQUAL Android)

Sources/FoundationMacros/CMakeLists.txt

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ endif()
2626
project(FoundationMacros
2727
LANGUAGES Swift)
2828

29+
option(SwiftFoundation_BUILD_EXECUTABLE_MACROS
30+
"Build the FoundationMacros as an executable" NO)
31+
2932
# SwiftSyntax Dependency
3033
find_package(SwiftSyntax QUIET)
3134
if(NOT SwiftSyntax_FOUND)
@@ -41,13 +44,13 @@ else()
4144
message(STATUS "SwiftSyntax_DIR provided, using swift-syntax from ${SwiftSyntax_DIR}")
4245
endif()
4346

44-
if(NOT FoundationMacros_BuildLocalExecutable)
45-
add_library(FoundationMacros SHARED)
46-
target_compile_definitions(FoundationMacros PRIVATE FOUNDATION_MACROS_LIBRARY)
47-
else()
47+
if(SwiftFoundation_BUILD_EXECUTABLE_MACROS)
4848
add_executable(FoundationMacros)
4949
target_link_libraries(FoundationMacros PUBLIC
5050
SwiftSyntax::SwiftCompilerPlugin)
51+
else()
52+
add_library(FoundationMacros SHARED)
53+
target_compile_definitions(FoundationMacros PRIVATE FOUNDATION_MACROS_LIBRARY)
5154
endif()
5255

5356
# Parse the module as a library, even if it's an executable, because it uses an `@main` type to define its entry point.
@@ -82,8 +85,6 @@ set_target_properties(FoundationMacros PROPERTIES
8285
INSTALL_RPATH "$ORIGIN/../../../swift/${SWIFT_SYSTEM_NAME}:$ORIGIN/.."
8386
INSTALL_REMOVE_ENVIRONMENT_RPATH ON)
8487

85-
if(NOT FoundationMacros_BuildLocalExecutable)
86-
install(TARGETS FoundationMacros
87-
LIBRARY DESTINATION lib/swift/host/plugins
88-
RUNTIME DESTINATION bin)
89-
endif()
88+
install(TARGETS FoundationMacros
89+
LIBRARY DESTINATION lib/swift/host/plugins
90+
RUNTIME DESTINATION bin)

0 commit comments

Comments
 (0)