Skip to content

Commit 2ee745d

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 2ee745d

File tree

3 files changed

+41
-32
lines changed

3 files changed

+41
-32
lines changed

Sources/CMakeLists.txt

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

15+
add_library(FoundationBuildMacros INTERFACE)
16+
export(TARGETS FoundationBuildMacros FILE FoundationBuildMacros.cmake)
17+
if(SwiftFoudation_MACRO)
18+
message(STATUS "SwiftFoundation_MACRO provided, using macros in ${SwiftFoundation_MACRO}")
19+
target_compile_options(FoundationBuildMacros INTERFACE
20+
"SHELL:$<BUILD_INTERFACE:-plugin-path ${SwiftFoudation_MACRO}>")
21+
else()
22+
message(STATUS "NO SwiftFoundation_MACRO, building macros from scratch")
23+
include(ExternalProject)
24+
# The macros are required for building Swift-Foundation. Build them for the
25+
# build machine.
26+
ExternalProject_Add(FoundationMacros
27+
SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/FoundationMacros"
28+
INSTALL_DIR "${CMAKE_CURRENT_BINARY_DIR}/FoundationMacros"
29+
CMAKE_ARGS
30+
-DCMAKE_BUILD_TYPE=Release
31+
-DCMAKE_Swift_COMPILER=${CMAKE_Swift_COMPILER}
32+
-DCMAKE_INSTALL_PREFIX=<INSTALL_DIR>
33+
-DSwiftFoundation_BUILD_EXECUTABLE_MACROS=YES)
34+
ExternalProject_Get_Property(FoundationMacros INSTALL_DIR)
35+
add_dependencies(FoundationBuildMacros FoundationMacros)
36+
if(CMAKE_HOST_WIN32)
37+
set(_SwiftFoundation_HOST_EXECUTABLE_SUFFIX .exe)
38+
endif()
39+
40+
target_compile_options(FoundationBuildMacros INTERFACE
41+
"SHELL:$<BUILD_INTERFACE:$<$<COMPILE_LANGUAGE:Swift>:-load-plugin-executable ${INSTALL_DIR}/bin/FoundationMacros${_SwiftFoundation_HOST_EXECUTABLE_SUFFIX}#FoundationMacros>>")
42+
unset(_SwiftFoundation_HOST_EXECUTABLE_SUFFIX)
43+
endif()
44+
1545
add_subdirectory(_FoundationCShims)
1646
add_subdirectory(FoundationEssentials)
1747
add_subdirectory(FoundationInternationalization)

Sources/FoundationEssentials/CMakeLists.txt

Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -49,29 +49,6 @@ add_subdirectory(String)
4949
add_subdirectory(TimeZone)
5050
add_subdirectory(URL)
5151

52-
if(SwiftFoundation_MACRO)
53-
message(STATUS "SwiftFoundation_MACRO provided, using macros in ${SwiftFoundation_MACRO}")
54-
# A path to Foundation macros was provided, so we use that path
55-
target_compile_options(FoundationEssentials PRIVATE
56-
"SHELL:-plugin-path ${SwiftFoundation_MACRO}")
57-
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}>")
73-
endif()
74-
7552
if(CMAKE_SYSTEM_NAME STREQUAL Linux OR CMAKE_SYSTEM_NAME STREQUAL Android)
7653
target_compile_options(FoundationEssentials PRIVATE
7754
"SHELL:$<$<COMPILE_LANGUAGE:Swift>:-Xfrontend -Xcc -Xfrontend -D_GNU_SOURCE>")
@@ -88,6 +65,7 @@ target_compile_options(FoundationEssentials PRIVATE ${_SwiftFoundation_wasi_libc
8865
target_compile_options(FoundationEssentials PRIVATE -package-name "SwiftFoundation")
8966

9067
target_link_libraries(FoundationEssentials PUBLIC
68+
FoundationBuildMacros
9169
_FoundationCShims
9270
_FoundationCollections)
9371
target_link_libraries(FoundationEssentials PUBLIC ${_SwiftFoundation_wasi_libc_libraries})

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)