diff --git a/.ci/scripts/wheel/test_linux.py b/.ci/scripts/wheel/test_linux.py index 5e8db90c863..6f97f2c8203 100644 --- a/.ci/scripts/wheel/test_linux.py +++ b/.ci/scripts/wheel/test_linux.py @@ -14,6 +14,10 @@ test_base.ModelTest( model=Model.Mv3, backend=Backend.XnnpackQuantizationDelegation, - ) + ), + test_base.ModelTest( + model=Model.Mv3, + backend=Backend.CoreMlExportOnly, + ), ] ) diff --git a/.ci/scripts/wheel/test_macos.py b/.ci/scripts/wheel/test_macos.py index e0a5342186b..a2660016098 100644 --- a/.ci/scripts/wheel/test_macos.py +++ b/.ci/scripts/wheel/test_macos.py @@ -17,7 +17,7 @@ ), test_base.ModelTest( model=Model.Mv3, - backend=Backend.CoreMlTest, + backend=Backend.CoreMlExportAndTest, ), ] ) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d8798bafb9..573ba81aaaa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -565,8 +565,6 @@ if(EXECUTORCH_BUILD_PTHREADPOOL AND EXECUTORCH_BUILD_CPUINFO) endif() if(EXECUTORCH_BUILD_PYBIND) - add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/third-party/pybind11) - if(NOT EXECUTORCH_BUILD_EXTENSION_DATA_LOADER) add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/extension/data_loader) endif() @@ -602,7 +600,7 @@ if(EXECUTORCH_BUILD_PYBIND) list(APPEND _dep_libs portable_ops_lib) endif() - if(EXECUTORCH_BUILD_COREML) + if(EXECUTORCH_BUILD_COREML AND APPLE) list(APPEND _dep_libs coremldelegate) endif() @@ -701,7 +699,7 @@ if(EXECUTORCH_BUILD_EXECUTOR_RUNNER) list(APPEND _executor_runner_libs etdump flatccrt) endif() - if(EXECUTORCH_BUILD_COREML) + if(EXECUTORCH_BUILD_COREML AND APPLE) list(APPEND _executor_runner_libs coremldelegate) endif() diff --git a/backends/apple/coreml/CMakeLists.txt b/backends/apple/coreml/CMakeLists.txt index 720f22d97a0..8d7b89c5a8d 100644 --- a/backends/apple/coreml/CMakeLists.txt +++ b/backends/apple/coreml/CMakeLists.txt @@ -5,17 +5,11 @@ # This source code is licensed under the BSD-style license found in the # LICENSE file in the root directory of this source tree. -cmake_minimum_required(VERSION 3.19) - -project(executorch_coreml_backend) - -if(NOT CMAKE_CXX_STANDARD) - set(CMAKE_CXX_STANDARD 17) -endif() - -# Source root directory for executorch. -if(NOT EXECUTORCH_ROOT) - set(EXECUTORCH_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../..) +if(APPLE) + find_library(FOUNDATION_FRAMEWORK Foundation REQUIRED) + find_library(ACCELERATE_FRAMEWORK Accelerate REQUIRED) + find_library(COREML_FRAMEWORK CoreML REQUIRED) + find_library(SQLITE_LIBRARY sqlite3 REQUIRED) endif() if(EXECUTORCH_BUILD_DEVTOOLS) @@ -23,17 +17,6 @@ if(EXECUTORCH_BUILD_DEVTOOLS) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -frtti") endif() -option(COREML_BUILD_EXECUTOR_RUNNER "Build CoreML executor runner." OFF) - -# inmemoryfs sources -set(INMEMORYFS_SOURCES - runtime/inmemoryfs/inmemory_filesystem.cpp - runtime/inmemoryfs/inmemory_filesystem_utils.mm - runtime/inmemoryfs/memory_buffer.cpp - runtime/inmemoryfs/memory_stream.cpp - runtime/inmemoryfs/reversed_memory_stream.cpp -) - # kvstore sources set(KVSTORE_SOURCES runtime/kvstore/database.cpp runtime/kvstore/json_key_value_store.cpp @@ -61,9 +44,6 @@ set(DELEGATE_SOURCES runtime/delegate/serde_json.mm ) -# util sources -set(UTIL_SOURCES runtime/util/json_util.cpp runtime/util/objc_json_serde.mm) - # sdk sources set(SDK_SOURCES runtime/sdk/ETCoreMLModelAnalyzer.mm @@ -116,12 +96,19 @@ set(PROTOBUF_SOURCES runtime/sdk/format/WordTagger.pb.cc ) -find_library(FOUNDATION_FRAMEWORK Foundation) - # CoreML util + +set(UTIL_SOURCES runtime/util/json_util.cpp) +if(APPLE) + list(APPEND UTIL_SOURCES runtime/util/objc_json_serde.mm) +endif() + add_library(coreml_util ${UTIL_SOURCES}) target_include_directories(coreml_util PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/runtime/util) -target_link_libraries(coreml_util PRIVATE ${FOUNDATION_FRAMEWORK}) +if(APPLE) + target_link_libraries(coreml_util PRIVATE ${FOUNDATION_FRAMEWORK}) +endif() +target_compile_options(coreml_util PUBLIC -fPIC) install( TARGETS coreml_util @@ -131,9 +118,24 @@ install( ) # CoreML inmemoryfs + +set( + INMEMORYFS_SOURCES + runtime/inmemoryfs/inmemory_filesystem.cpp + runtime/inmemoryfs/memory_buffer.cpp + runtime/inmemoryfs/memory_stream.cpp + runtime/inmemoryfs/reversed_memory_stream.cpp +) +if(APPLE) + list(APPEND INMEMORYFS_SOURCES runtime/inmemoryfs/inmemory_filesystem_utils.mm) +endif() + add_library(coreml_inmemoryfs ${INMEMORYFS_SOURCES}) target_include_directories(coreml_inmemoryfs PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/runtime/inmemoryfs) -target_link_libraries(coreml_inmemoryfs PRIVATE coreml_util ${FOUNDATION_FRAMEWORK}) +if(APPLE) + target_link_libraries(coreml_inmemoryfs PRIVATE coreml_util ${FOUNDATION_FRAMEWORK}) +endif() +target_compile_options(coreml_inmemoryfs PUBLIC -fPIC) install( TARGETS coreml_inmemoryfs @@ -142,104 +144,101 @@ install( DESTINATION ${_common_include_directories} ) -# Define the delegate library -add_library(coremldelegate) -target_sources(coremldelegate PRIVATE ${KVSTORE_SOURCES} ${DELEGATE_SOURCES}) - -target_include_directories( - coremldelegate PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/runtime/include -) -target_include_directories( - coremldelegate PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/runtime/kvstore -) -target_include_directories( - coremldelegate PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/runtime/delegate -) -target_include_directories(coremldelegate PRIVATE ${EXECUTORCH_ROOT}/..) -target_include_directories(coremldelegate PRIVATE ${EXECUTORCH_ROOT}/runtime/core/portable_type/c10) -target_compile_definitions(coremldelegate PRIVATE C10_USING_CUSTOM_GENERATED_MACROS) +# executorchcoreml -if(EXECUTORCH_BUILD_DEVTOOLS) - target_sources(coremldelegate PRIVATE ${SDK_SOURCES} ${PROTOBUF_SOURCES}) - target_include_directories( - coremldelegate - PRIVATE - ${CMAKE_CURRENT_SOURCE_DIR}/runtime/sdk - ${CMAKE_CURRENT_SOURCE_DIR}/third-party/coremltools/deps/protobuf/src +if(EXECUTORCH_BUILD_PYBIND) + pybind11_add_module( + executorchcoreml + SHARED + runtime/inmemoryfs/inmemory_filesystem_py.cpp + runtime/inmemoryfs/inmemory_filesystem_utils.cpp ) - add_subdirectory( - ${CMAKE_CURRENT_SOURCE_DIR}/third-party/coremltools/deps/protobuf/cmake + target_link_libraries( + executorchcoreml + PRIVATE + coreml_util + coreml_inmemoryfs + nlohmann_json::nlohmann_json ) - - target_link_options_shared_lib(libprotobuf-lite) - target_link_libraries(coremldelegate PRIVATE libprotobuf-lite) + target_compile_options(executorchcoreml PUBLIC -fPIC) endif() -find_library(ACCELERATE_FRAMEWORK Accelerate) -find_library(COREML_FRAMEWORK CoreML) -find_library(SQLITE_LIBRARY sqlite3) - -target_link_libraries( - coremldelegate - PUBLIC coreml_util - coreml_inmemoryfs - PRIVATE executorch_core - ${ACCELERATE_FRAMEWORK} - ${COREML_FRAMEWORK} - ${FOUNDATION_FRAMEWORK} - ${SQLITE_LIBRARY} -) +# coremldelegate -target_link_options_shared_lib(coremldelegate) +if(APPLE) + add_library(coremldelegate) + target_sources(coremldelegate PRIVATE ${KVSTORE_SOURCES} ${DELEGATE_SOURCES}) -if(COREML_BUILD_EXECUTOR_RUNNER) - target_link_libraries( - coremldelegate PRIVATE portable_ops_lib portable_kernels + target_include_directories( + coremldelegate PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/runtime/include ) -endif() - -target_compile_options(coremldelegate PRIVATE "-fobjc-arc") -target_compile_options(coremldelegate PRIVATE "-fno-exceptions") - -if(EXECUTORCH_BUILD_DEVTOOLS) - target_compile_options( - executorch_core PUBLIC -DET_EVENT_TRACER_ENABLED + target_include_directories( + coremldelegate PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/runtime/kvstore ) - target_compile_options(coremldelegate PRIVATE "-frtti") - target_compile_options(libprotobuf-lite PRIVATE "-frtti") -else() - target_compile_options(coremldelegate PRIVATE "-fno-rtti") -endif() - -set(TARGET coremldelegate APPEND_STRING PROPERTY COMPILE_FLAGS - "-x objective-c++" -) - -set(TARGET coremldelegate APPEND_STRING PROPERTY COMPILE_FLAGS - "-Wno-null-character" -) + target_include_directories( + coremldelegate PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/runtime/delegate + ) + target_include_directories(coremldelegate PRIVATE ${PROJECT_SOURCE_DIR}/..) + target_include_directories(coremldelegate PRIVATE ${PROJECT_SOURCE_DIR}/runtime/core/portable_type/c10) + target_compile_definitions(coremldelegate PRIVATE C10_USING_CUSTOM_GENERATED_MACROS) + + if(EXECUTORCH_BUILD_DEVTOOLS) + target_sources(coremldelegate PRIVATE ${SDK_SOURCES} ${PROTOBUF_SOURCES}) + target_include_directories( + coremldelegate + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR}/runtime/sdk + ${CMAKE_CURRENT_SOURCE_DIR}/third-party/coremltools/deps/protobuf/src + ) + add_subdirectory( + ${CMAKE_CURRENT_SOURCE_DIR}/third-party/coremltools/deps/protobuf/cmake + ) + + target_link_options_shared_lib(libprotobuf-lite) + target_link_libraries(coremldelegate PRIVATE libprotobuf-lite) + endif() -set(TARGET coremldelegate APPEND_STRING PROPERTY COMPILE_FLAGS - "-Wno-receiver-expr" -) + target_link_libraries( + coremldelegate + PUBLIC coreml_util + coreml_inmemoryfs + PRIVATE executorch_core + ${ACCELERATE_FRAMEWORK} + ${COREML_FRAMEWORK} + ${FOUNDATION_FRAMEWORK} + ${SQLITE_LIBRARY} + ) -install( - TARGETS coremldelegate - DESTINATION lib - INCLUDES - DESTINATION ${_common_include_directories} -) + target_link_options_shared_lib(coremldelegate) -# We only care about building the pybinding when building for macOS wheels. -if(EXECUTORCH_BUILD_COREML AND EXECUTORCH_BUILD_PYBIND) - if(NOT TARGET pybind11::pybind11) - add_subdirectory(${EXECUTORCH_ROOT}/third-party/pybind11 ${CMAKE_CURRENT_BINARY_DIR}/pybind11) + if(EXECUTORCH_COREML_BUILD_EXECUTOR_RUNNER) + target_link_libraries( + coremldelegate PRIVATE portable_ops_lib portable_kernels + ) endif() - pybind11_add_module(executorchcoreml SHARED runtime/inmemoryfs/inmemory_filesystem_py.cpp) + target_compile_options( + coremldelegate + PRIVATE + -fobjc-arc + -fno-exceptions + -x objective-c++ + -Wno-null-character + -Wno-receiver-expr + ) - if(CMAKE_BUILD_TYPE STREQUAL "Debug" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo") - target_compile_options(executorchcoreml PRIVATE -g) + if(EXECUTORCH_BUILD_DEVTOOLS) + target_compile_options(executorch_core PUBLIC -DET_EVENT_TRACER_ENABLED) + target_compile_options(coremldelegate PRIVATE "-frtti") + target_compile_options(libprotobuf-lite PRIVATE "-frtti") + else() + target_compile_options(coremldelegate PRIVATE "-fno-rtti") endif() - target_link_libraries(executorchcoreml PRIVATE coreml_util coreml_inmemoryfs) + + install( + TARGETS coremldelegate + DESTINATION lib + INCLUDES + DESTINATION ${_common_include_directories} + ) endif() diff --git a/backends/apple/coreml/runtime/util/json_util.cpp b/backends/apple/coreml/runtime/util/json_util.cpp index a7592541a49..8caf0f37413 100644 --- a/backends/apple/coreml/runtime/util/json_util.cpp +++ b/backends/apple/coreml/runtime/util/json_util.cpp @@ -5,9 +5,16 @@ // Copyright © 2024 Apple Inc. All rights reserved. // // Please refer to the license found in the LICENSE file in the root directory of the source tree. +// +// Copyright (c) Meta Platforms, Inc. and affiliates. +// All rights reserved. +// +// This source code is licensed under the BSD-style license found in the +// LICENSE file in the root directory of this source tree.# #include "json_util.hpp" +#include #include #include diff --git a/examples/apple/coreml/scripts/build_executor_runner.sh b/examples/apple/coreml/scripts/build_executor_runner.sh index bdfbf24a0cf..00ee9821201 100755 --- a/examples/apple/coreml/scripts/build_executor_runner.sh +++ b/examples/apple/coreml/scripts/build_executor_runner.sh @@ -4,8 +4,15 @@ # # This source code is licensed under the BSD-style license found in the # LICENSE file in the root directory of this source tree. +# +# Copyright (c) Meta Platforms, Inc. and affiliates. +# All rights reserved. +# +# This source code is licensed under the BSD-style license found in the +# LICENSE file in the root directory of this source tree. -set -e + +set -eux MODE="Release" @@ -26,13 +33,8 @@ for arg in "$@"; do esac done -SCRIPT_DIR_PATH="$( - cd -- "$(dirname "$0")" >/dev/null 2>&1 - pwd -P -)" - -EXECUTORCH_ROOT_PATH=$(realpath "$SCRIPT_DIR_PATH/../../../../") +EXECUTORCH_ROOT_PATH=$(git rev-parse --show-toplevel) COREML_DIR_PATH="$EXECUTORCH_ROOT_PATH/backends/apple/coreml" EXAMPLES_COREML_DIR_PATH="$EXECUTORCH_ROOT_PATH/examples/apple/coreml" IOS_TOOLCHAIN_PATH="$EXECUTORCH_ROOT_PATH/third-party/ios-cmake/ios.toolchain.cmake" @@ -50,28 +52,26 @@ rm -rf "$CMAKE_BUILD_DIR_PATH" # Build executorch echo "ExecuTorch: Building executorch" -cmake "$EXECUTORCH_ROOT_PATH" -B"$CMAKE_BUILD_DIR_PATH" \ --DCMAKE_BUILD_TYPE="$MODE" \ --DCMAKE_TOOLCHAIN_FILE="$IOS_TOOLCHAIN_PATH" \ --DPLATFORM=MAC_UNIVERSAL \ --DDEPLOYMENT_TARGET=13.0 \ --DEXECUTORCH_BUILD_EXECUTOR_RUNNER=OFF \ --DEXECUTORCH_BUILD_XNNPACK=OFF \ --DEXECUTORCH_BUILD_DEVTOOLS=ON \ --DEXECUTORCH_BUILD_COREML=ON \ --Dprotobuf_BUILD_TESTS=OFF \ --Dprotobuf_BUILD_EXAMPLES=OFF \ --DCOREML_BUILD_EXECUTOR_RUNNER=ON \ --DCMAKE_MACOSX_BUNDLE=OFF - -cmake --build "$CMAKE_BUILD_DIR_PATH" -j9 -t coremldelegate -cmake --build "$CMAKE_BUILD_DIR_PATH" -j9 -t etdump -t flatccrt + +cmake -S $EXECUTORCH_ROOT_PATH \ + -B $CMAKE_BUILD_DIR_PATH \ + -DCMAKE_BUILD_TYPE="$MODE" \ + -DEXECUTORCH_BUILD_DEVTOOLS=ON \ + -Dprotobuf_BUILD_TESTS=OFF \ + --preset macos + +cmake --build $CMAKE_BUILD_DIR_PATH \ + -j$(sysctl -n hw.ncpu) \ + --config "$MODE" \ + --target coremldelegate \ + --target etdump \ + --target flatccrt # Copy CoreML delegate headers echo "ExecuTorch: Copying headers" echo $EXECUTORCH_INCLUDE_DIR_PATH rm -rf "$INCLUDE_DIR_PATH" -mkdir "$INCLUDE_DIR_PATH" +mkdir -p "$INCLUDE_DIR_PATH" #Copy ExecuTorch headers mkdir -p "$EXECUTORCH_INCLUDE_DIR_PATH" find extension \( -name "*.h" -o -name "*.hpp" \) -exec rsync -R '{}' "$EXECUTORCH_INCLUDE_DIR_PATH" \; @@ -82,7 +82,7 @@ cp -rf "$COREML_DIR_PATH/runtime/include/" "$INCLUDE_DIR_PATH" # Copy required libraries echo "ExecuTorch: Copying libraries" -mkdir "$LIBRARIES_DIR_PATH" +mkdir -p "$LIBRARIES_DIR_PATH" find "$CMAKE_BUILD_DIR_PATH/" -name 'libexecutorch.a' -exec cp -f "{}" "$LIBRARIES_DIR_PATH/libexecutorch.a" \; find "$CMAKE_BUILD_DIR_PATH/" -name 'libexecutorch_core.a' -exec cp -f "{}" "$LIBRARIES_DIR_PATH/libexecutorch_core.a" \; find "$CMAKE_BUILD_DIR_PATH/" -name 'libprotobuf-lite.a' -exec cp -f "{}" "$LIBRARIES_DIR_PATH/libprotobuf-lite.a" \; @@ -93,7 +93,7 @@ find "$CMAKE_BUILD_DIR_PATH/" -name 'libcoreml_inmemoryfs.a' -exec cp -f "{}" "$ find "$CMAKE_BUILD_DIR_PATH/" -name 'libcoremldelegate.a' -exec cp -f "{}" "$LIBRARIES_DIR_PATH/libcoremldelegate.a" \; find "$CMAKE_BUILD_DIR_PATH/" -name 'libportable_ops_lib.a' -exec cp -f "{}" "$LIBRARIES_DIR_PATH/libportable_ops_lib.a" \; find "$CMAKE_BUILD_DIR_PATH/" -name 'libportable_kernels.a' -exec cp -f "{}" "$LIBRARIES_DIR_PATH/libportable_kernels.a" \; -cp -f "$EXECUTORCH_ROOT_PATH/third-party/flatcc/lib/libflatccrt.a" "$LIBRARIES_DIR_PATH/libflatccrt.a" +cp -f "$CMAKE_BUILD_DIR_PATH/third-party/flatcc_external_project/lib/libflatccrt.a" "$LIBRARIES_DIR_PATH/libflatccrt.a" # Build the runner echo "ExecuTorch: Building runner" diff --git a/examples/models/__init__.py b/examples/models/__init__.py index 41ec5c3aac6..76469846608 100644 --- a/examples/models/__init__.py +++ b/examples/models/__init__.py @@ -44,7 +44,8 @@ def __str__(self) -> str: class Backend(str, Enum): XnnpackQuantizationDelegation = "xnnpack-quantization-delegation" - CoreMlTest = "coreml-test" + CoreMlExportOnly = "coreml" + CoreMlExportAndTest = "coreml-test" # AOT export + test with runner def __str__(self) -> str: return self.value diff --git a/pyproject.toml b/pyproject.toml index de1c2a84fbb..2b636fb00e3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -68,7 +68,7 @@ dependencies=[ "tabulate", "typing-extensions", # Keep this version in sync with: ./backends/apple/coreml/scripts/install_requirements.sh - "coremltools==8.3; platform_system == 'Darwin'", + "coremltools==8.3; platform_system == 'Darwin' or platform_system == 'Linux'", ] [project.urls] diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt index b4d4d875251..cae89792566 100644 --- a/third-party/CMakeLists.txt +++ b/third-party/CMakeLists.txt @@ -6,6 +6,10 @@ add_subdirectory(json) +if(EXECUTORCH_BUILD_PYBIND) + add_subdirectory(pybind11) +endif() + # MARK: - flatbuffers if(WIN32) diff --git a/tools/cmake/preset/default.cmake b/tools/cmake/preset/default.cmake index 51c228c479b..2d0c6302117 100644 --- a/tools/cmake/preset/default.cmake +++ b/tools/cmake/preset/default.cmake @@ -214,6 +214,11 @@ define_overridable_option( "Build the gflags library." BOOL ON ) +define_overridable_option( + EXECUTORCH_COREML_BUILD_EXECUTOR_RUNNER + "Build CoreML executor runner." + BOOL OFF +) if(EXECUTORCH_BUILD_ARM_BAREMETAL) set(_default_executorch_build_pthreadpool OFF) diff --git a/tools/cmake/preset/macos.cmake b/tools/cmake/preset/macos.cmake index 41e4fc3d86c..cef1f1877ee 100644 --- a/tools/cmake/preset/macos.cmake +++ b/tools/cmake/preset/macos.cmake @@ -9,3 +9,4 @@ include(${PROJECT_SOURCE_DIR}/tools/cmake/preset/pybind.cmake) include(${PROJECT_SOURCE_DIR}/tools/cmake/preset/llm.cmake) set_overridable_option(EXECUTORCH_BUILD_EXECUTOR_RUNNER ON) +set_overridable_option(EXECUTORCH_COREML_BUILD_EXECUTOR_RUNNER ON) diff --git a/tools/cmake/preset/pybind.cmake b/tools/cmake/preset/pybind.cmake index 7124a23a9c9..ad5adc3eef4 100644 --- a/tools/cmake/preset/pybind.cmake +++ b/tools/cmake/preset/pybind.cmake @@ -23,7 +23,7 @@ set_overridable_option(EXECUTORCH_BUILD_EXTENSION_FLAT_TENSOR ON) if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") set_overridable_option(EXECUTORCH_BUILD_COREML ON) elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") - # Linux-specific code here + set_overridable_option(EXECUTORCH_BUILD_COREML ON) elseif(CMAKE_SYSTEM_NAME STREQUAL "Windows" OR CMAKE_SYSTEM_NAME STREQUAL "WIN32") # Windows or other OS-specific code here else()