Skip to content

Add a way to build swift code as part of the executorch runtime frame… #11072

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

Merged
merged 2 commits into from
May 22, 2025
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
51 changes: 43 additions & 8 deletions extension/apple/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,29 @@

cmake_minimum_required(VERSION 3.19)

enable_language(Swift)

# Source root directory for executorch.
if(NOT EXECUTORCH_ROOT)
set(EXECUTORCH_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../..)
endif()

add_library(extension_apple)

file(GLOB EXPORTED_SOURCES
file(GLOB OBJC_SOURCES
ExecuTorch/Exported/*.m
ExecuTorch/Exported/*.mm
)

file(GLOB INTERNAL_SOURCES
ExecuTorch/Internal/*.m
ExecuTorch/Internal/*.mm
)

file(GLOB SWIFT_SOURCES
ExecuTorch/Exported/*.swift
)

target_sources(extension_apple PRIVATE
${EXPORTED_SOURCES}
${INTERNAL_SOURCES}
${OBJC_SOURCES}
${SWIFT_SOURCES}
)

target_include_directories(extension_apple
Expand All @@ -43,9 +46,41 @@ target_link_libraries(extension_apple
PRIVATE executorch ${FOUNDATION_FRAMEWORK}
)

target_compile_options(extension_apple PUBLIC ${_common_compile_options})
target_compile_options(extension_apple PRIVATE
set_source_files_properties(${OBJC_SOURCES} PROPERTIES COMPILE_FLAGS
"-fobjc-arc"
"-fno-exceptions"
"-fno-rtti"
)

set(MODULE_MAP_DIR ${CMAKE_CURRENT_BINARY_DIR}/module)
set(MODULE_MAP_FILE ${MODULE_MAP_DIR}/module.modulemap)

configure_file(
"${CMAKE_CURRENT_SOURCE_DIR}/ExecuTorch/Exported/ExecuTorch.h"
"${MODULE_MAP_DIR}/ExecuTorch.h"
COPYONLY
)

file(MAKE_DIRECTORY ${MODULE_MAP_DIR})
file(WRITE ${MODULE_MAP_FILE}
"module ExecuTorch {
umbrella header \"ExecuTorch.h\"
export *
}
")

set(SWIFT_CLANG_INTEROP_FLAGS "-Xcc -fmodule-map-file=${MODULE_MAP_FILE} -I ${MODULE_MAP_DIR}")

set_target_properties(extension_apple PROPERTIES
Swift_MODULE_NAME "ExecuTorch"
Swift_FLAGS "${SWIFT_CLANG_INTEROP_FLAGS}"
XCODE_ATTRIBUTE_SWIFT_MODULE_NAME "ExecuTorch"
XCODE_ATTRIBUTE_BUILD_LIBRARY_FOR_DISTRIBUTION YES
XCODE_ATTRIBUTE_SWIFT_ENABLE_TESTABILITY YES
XCODE_ATTRIBUTE_OTHER_SWIFT_FLAGS "${SWIFT_CLANG_INTEROP_FLAGS}"
)

add_custom_command(
TARGET extension_apple POST_BUILD
COMMAND ${CMAKE_COMMAND} -E rm -rf ${MODULE_MAP_DIR}
)
35 changes: 33 additions & 2 deletions scripts/create_frameworks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@ function usage() {
echo ""
echo "Usage: $0 --directory=<dir> --framework=<lib> [--output=<output>]"
echo " --directory: Directory containing the libs"
echo " --framework: Framework to create in the format 'target:lib1,lib2:headers'"
echo " --framework: Framework to create in the format 'target:lib1,lib2:headers:swiftmodule'"
echo " 'target' is the name of the target library."
echo " 'lib1,lib2' is a comma-separated list of input libraries."
echo " 'headers' is an optional path to a directory with headers."
echo " ':swiftmodule' is an optional module name to embed its .swiftmodule folder"
echo " --output: Optional output directory. Defaults to the current directory."
echo ""
echo "Example:"
echo "$0 --directory=ios-arm64 --directory=ios-arm64-simulator --framework=\"mylib:lib1.a,lib2.a:include\" --output=output/dir"
echo "$0 --directory=ios-arm64 --directory=ios-arm64-simulator --framework=\"mylib:lib1.a,lib2.a:include:MyModule\" --output=output/dir"
exit 1
}

Expand Down Expand Up @@ -58,6 +59,8 @@ create_xcframework() {
libraries_list=$(echo "$1" | cut -d: -f2 | tr ',' '\n')
local headers_directory
headers_directory=$(echo "$1" | cut -d: -f3)
local swift_module
swift_module=$(echo "$1" | cut -d: -f4)
local dir
local libraries=()
local merged_libs=()
Expand Down Expand Up @@ -117,8 +120,36 @@ create_xcframework() {

echo -e "\nCreating XCFramework ${xcframework}"

# Create the new .xcframework.
xcodebuild -create-xcframework "${libraries[@]}" -output "${xcframework}"

# Copy the .swiftmodule files into the .xcframework if applicable.
if [[ -n "$swift_module" ]]; then
echo -e "\nCopying Swift module ${swift_module}.swiftmodule into ${xcframework}"
for dir in "${directories[@]}"; do
local module_source_dir="${dir}/${swift_module}.swiftmodule"
if [ ! -d "$module_source_dir" ]; then
echo "Swiftmodule directory ${module_source_dir} does not exist"
exit 1
fi
local swiftmodule_file
swiftmodule_file=$(find "$module_source_dir" -maxdepth 1 -type f -name '*.swiftmodule' | head -n1)
if [[ -z "$swiftmodule_file" ]]; then
echo "No .swiftmodule file found in ${module_source_dir}"
exit 1
fi

local dir_suffix
dir_suffix=$(echo "$dir" | cut -d'/' -f1 | tr '[:upper:]' '[:lower:]' | sed 's/[\/\.~]/_/g')
for slice_path in "${xcframework}/${dir_suffix}-"*; do
if [ -d "${slice_path}/Headers" ]; then
echo " - Copying ${swiftmodule_file##*/} to ${slice_path}/Headers/${swift_module}.swiftmodule"
cp "${swiftmodule_file}" "${slice_path}/Headers/${swift_module}.swiftmodule"
fi
done
done
fi

echo -e "\nDeleting intermediate libraries:"
for merged_lib in "${merged_libs[@]}"; do
if [[ -f "${merged_lib}" ]]; then
Expand Down
Loading