Skip to content

Commit 18ed861

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 c2e96f8 commit 18ed861

File tree

5 files changed

+45
-32
lines changed

5 files changed

+45
-32
lines changed

Sources/CMakeLists.txt

+32
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,38 @@
1212
##
1313
##===----------------------------------------------------------------------===##
1414

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

Sources/FoundationEssentials/CMakeLists.txt

+1-23
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 ${SwiftFoundation_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

+10-9
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
if(NOT SWIFT_SYSTEM_NAME)
3033
if(CMAKE_SYSTEM_NAME STREQUAL Darwin)
3134
set(SWIFT_SYSTEM_NAME macosx)
@@ -49,13 +52,13 @@ else()
4952
message(STATUS "SwiftSyntax_DIR provided, using swift-syntax from ${SwiftSyntax_DIR}")
5053
endif()
5154

52-
if(NOT FoundationMacros_BuildLocalExecutable)
53-
add_library(FoundationMacros SHARED)
54-
target_compile_definitions(FoundationMacros PRIVATE FOUNDATION_MACROS_LIBRARY)
55-
else()
55+
if(SwiftFoundation_BUILD_EXECUTABLE_MACROS)
5656
add_executable(FoundationMacros)
5757
target_link_libraries(FoundationMacros PUBLIC
5858
SwiftSyntax::SwiftCompilerPlugin)
59+
else()
60+
add_library(FoundationMacros SHARED)
61+
target_compile_definitions(FoundationMacros PRIVATE FOUNDATION_MACROS_LIBRARY)
5962
endif()
6063

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

93-
if(NOT FoundationMacros_BuildLocalExecutable)
94-
install(TARGETS FoundationMacros
95-
LIBRARY DESTINATION lib/swift/host/plugins
96-
RUNTIME DESTINATION bin)
97-
endif()
96+
install(TARGETS FoundationMacros
97+
LIBRARY DESTINATION lib/swift/host/plugins
98+
RUNTIME DESTINATION bin)

cmake/modules/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
##
1313
##===----------------------------------------------------------------------===##
1414

15+
set(SWIFT_FOUNDATION_BUILD_MACROS_FILE ${CMAKE_CURRENT_BINARY_DIR}/FoundationBuildMacros.cmake)
1516
set(SWIFT_FOUNDATION_EXPORTS_FILE ${CMAKE_CURRENT_BINARY_DIR}/SwiftFoundationExports.cmake)
1617
set(SWIFT_FOUNDATION_ICU_EXPORTS_FILE ${SwiftFoundationICU_BINARY_DIR}/cmake/modules/SwiftFoundationICUExports.cmake)
1718
set(SWIFT_COLLECTIONS_EXPORTS_FILE ${SwiftCollections_BINARY_DIR}/cmake/modules/SwiftCollectionsExports.cmake)

cmake/modules/SwiftFoundationConfig.cmake.in

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
##===----------------------------------------------------------------------===##
1414

1515
if(NOT TARGET SwiftFoundation)
16+
include(@SWIFT_FOUNDATION_BUILD_MACROS_FILE@)
1617
include(@SWIFT_FOUNDATION_ICU_EXPORTS_FILE@)
1718
include(@SWIFT_COLLECTIONS_EXPORTS_FILE@)
1819
include(@SWIFT_FOUNDATION_EXPORTS_FILE@)

0 commit comments

Comments
 (0)