Skip to content

Commit 6b343b8

Browse files
committed
Update to pytorch-lite 2.1.0
- Use VoizeLibTorch-Lite to enable ios arm simulator support - Replace suparnatural FS with okio
1 parent 861a109 commit 6b343b8

File tree

14 files changed

+148
-130
lines changed

14 files changed

+148
-130
lines changed

.github/workflows/test.yml

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,22 @@ jobs:
2929
- run: xcrun simctl list devices iOS
3030
- run: python3 --version
3131
- run: pip3 install torch --extra-index-url https://download.pytorch.org/whl/cpu
32-
- run: ./gradlew iosSimulatorX64Test
32+
- run: ./gradlew iosInstrumentedSimulatorX64Test
33+
test-ios-simulator-arm64:
34+
runs-on: macos-latest
35+
steps:
36+
- uses: actions/checkout@v3
37+
- uses: actions/setup-java@v3
38+
with:
39+
distribution: 'temurin'
40+
java-version: '17'
41+
- uses: actions/setup-python@v2
42+
with:
43+
python-version: '3.9'
44+
- run: xcrun simctl list devices iOS
45+
- run: python3 --version
46+
- run: pip3 install torch --extra-index-url https://download.pytorch.org/whl/cpu
47+
- run: ./gradlew iosInstrumentedSimulatorArm64Test
3348
build:
3449
runs-on: macos-latest
3550
steps:
@@ -38,7 +53,7 @@ jobs:
3853
with:
3954
distribution: 'temurin'
4055
java-version: '17'
41-
- run: ./gradlew build -x iosX64Test
56+
- run: ./gradlew build -x iosX64Test -x iosSimulatorArm64Test
4257
build-libtorch-wrapper:
4358
runs-on: macos-latest
4459
defaults:

build.gradle.kts

Lines changed: 93 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,9 @@ kotlin {
2525
androidTarget {
2626
publishLibraryVariants("release")
2727
}
28-
28+
2929
ios()
30+
iosSimulatorArm64()
3031

3132
cocoapods {
3233
ios.deploymentTarget = "13.5"
@@ -52,13 +53,13 @@ kotlin {
5253
val commonTest by getting {
5354
dependencies {
5455
implementation(kotlin("test"))
55-
implementation("com.suparnatural.kotlin:fs:1.1.0")
56+
implementation("com.squareup.okio:okio:3.3.0")
5657
}
5758
}
5859
val androidMain by getting {
5960
dependencies {
6061
rootProject
61-
implementation("org.pytorch:pytorch_android_lite:1.13.1")
62+
implementation("org.pytorch:pytorch_android_lite:2.1.0")
6263
}
6364
}
6465
val androidUnitTest by getting {
@@ -72,90 +73,11 @@ kotlin {
7273
}
7374
}
7475

75-
tasks.named("linkDebugTestIosX64").configure {
76-
doFirst {
77-
val target = (kotlin.targets.getByName("iosX64") as KotlinNativeTarget)
78-
79-
target.binaries.all {
80-
val syntheticIOSProjectDir = project.file("build/cocoapods/synthetic/IOS")
81-
val libTorchPodDir = syntheticIOSProjectDir.resolve("Pods/LibTorch-Lite")
82-
val libTorchLibsDir = libTorchPodDir.resolve("install/lib")
83-
val podBuildDir = syntheticIOSProjectDir.resolve("build/Release-iphonesimulator")
84-
85-
linkerOpts(
86-
"-L${libTorchLibsDir.absolutePath}",
87-
"-lc10", "-ltorch", "-ltorch_cpu", "-lXNNPACK",
88-
"-lclog", "-lcpuinfo", "-leigen_blas", "-lpthreadpool", "-lpytorch_qnnpack",
89-
"-force_load", libTorchLibsDir.resolve("libtorch.a").absolutePath,
90-
"-force_load", libTorchLibsDir.resolve("libtorch_cpu.a").absolutePath,
91-
"-all_load",
92-
"-L${podBuildDir.resolve("PLMLibTorchWrapper").absolutePath}",
93-
"-lPLMLibTorchWrapper",
94-
"-framework", "Accelerate",
95-
)
96-
}
97-
}
98-
}
99-
100-
// inspired by: https://diamantidis.github.io/2019/08/25/kotlin-multiplatform-project-unit-tests-for-ios-and-android
101-
task("iosSimulatorX64Test") {
102-
val target = (kotlin.targets.getByName("iosX64") as KotlinNativeTarget)
103-
104-
dependsOn(target.binaries.getTest("DEBUG").linkTaskName)
105-
group = JavaBasePlugin.VERIFICATION_GROUP
106-
description = "Runs iOS tests on a simulator"
107-
108-
val deviceName = "iPhone 15 Pro"
109-
110-
doLast {
111-
println("Retrieving runtime for iOS simulator")
112-
val iOSRuntimesOutput = ByteArrayOutputStream()
113-
exec {
114-
commandLine("xcrun", "simctl", "list", "--json", "runtimes", "iOS")
115-
standardOutput = iOSRuntimesOutput
116-
}
117-
118-
val iOSRuntimesData = groovy.json.JsonSlurper().parseText(iOSRuntimesOutput.toString()) as Map<String, List<Map<String, Any>>>
119-
val runtimesIdentifiers = iOSRuntimesData["runtimes"]!!.map { it["identifier"]!! } as List<String>
120-
val latestRuntimeIdentifier = runtimesIdentifiers.maxOrNull()!!
121-
println("Latest iOS runtime: $latestRuntimeIdentifier")
76+
configureIosSimulatorLinkTask("linkDebugTestIosX64", "iosX64")
77+
configureIosSimulatorLinkTask("linkDebugTestIosSimulatorArm64", "iosSimulatorArm64")
12278

123-
println("Retrieving device for iOS simulator")
124-
val devicesOutput = ByteArrayOutputStream()
125-
exec {
126-
commandLine("xcrun", "simctl", "list", "--json", "devices")
127-
standardOutput = devicesOutput
128-
}
129-
val devicesData = groovy.json.JsonSlurper().parseText(devicesOutput.toString()) as Map<String, Map<String, List<Map<String, String>>>>
130-
val devices = devicesData["devices"]!!
131-
val device = devices[latestRuntimeIdentifier]!!.find { it["name"] == deviceName }
132-
val udid = device!!["udid"]
133-
println("Using device: $deviceName ($udid)")
134-
135-
exec {
136-
println("Building test model")
137-
commandLine("python3", "build_dummy_model.py")
138-
}
139-
140-
val simulatorFilesPath = "/Users/${System.getProperty("user.name")}/Library/Developer/CoreSimulator/Devices/$udid/data/Documents"
141-
142-
exec {
143-
println("Setting up iOS simulator documents directory")
144-
commandLine("mkdir", "-p", simulatorFilesPath)
145-
}
146-
147-
exec {
148-
println("Copying model to iOS simulator files ($simulatorFilesPath)")
149-
commandLine("cp", "dummy_module.ptl", simulatorFilesPath)
150-
}
151-
152-
exec {
153-
println("Running simulator tests")
154-
val binary = target.binaries.getTest("DEBUG").outputFile
155-
commandLine("xcrun", "simctl", "spawn", "--standalone", udid, binary.absolutePath)
156-
}
157-
}
158-
}
79+
createIosSimulatorTestTask("iosInstrumentedSimulatorX64Test", "iosX64")
80+
createIosSimulatorTestTask("iosInstrumentedSimulatorArm64Test", "iosSimulatorArm64")
15981

16082
android {
16183
namespace = "de.voize.pytorch_lite_multiplatform"
@@ -176,3 +98,88 @@ android {
17698
}
17799
}
178100
}
101+
102+
fun configureIosSimulatorLinkTask(taskName: String, targetName: String) {
103+
tasks.named(taskName).configure {
104+
doFirst {
105+
val target = (kotlin.targets.getByName(targetName) as KotlinNativeTarget)
106+
107+
target.binaries.all {
108+
val syntheticIOSProjectDir = project.file("build/cocoapods/synthetic/ios")
109+
val libTorchPodDir = syntheticIOSProjectDir.resolve("Pods/VoizeLibTorch-Lite")
110+
val frameworkLibsDir = libTorchPodDir.resolve("LibTorchLite.xcframework/ios-arm64_x86_64-simulator")
111+
val buildDir = syntheticIOSProjectDir.resolve("build/Release-iphonesimulator")
112+
113+
linkerOpts(
114+
"-L${frameworkLibsDir.absolutePath}",
115+
"-L${buildDir.resolve("PLMLibTorchWrapper").absolutePath}",
116+
"-lPLMLibTorchWrapper",
117+
"-framework", "Accelerate",
118+
"-ltorch_lite",
119+
"-all_load",
120+
)
121+
}
122+
}
123+
}
124+
}
125+
126+
// inspired by: https://diamantidis.github.io/2019/08/25/kotlin-multiplatform-project-unit-tests-for-ios-and-android
127+
fun createIosSimulatorTestTask(taskName: String, targetName: String) {
128+
task(taskName) {
129+
val target = (kotlin.targets.getByName(targetName) as KotlinNativeTarget)
130+
dependsOn(target.binaries.getTest("DEBUG").linkTaskName)
131+
group = JavaBasePlugin.VERIFICATION_GROUP
132+
description = "Runs iOS tests on a simulator for target $targetName"
133+
134+
val deviceName = "iPhone 15 Pro"
135+
136+
doLast {
137+
println("Retrieving runtime for iOS simulator")
138+
val iOSRuntimesOutput = ByteArrayOutputStream()
139+
exec {
140+
commandLine("xcrun", "simctl", "list", "--json", "runtimes", "iOS")
141+
standardOutput = iOSRuntimesOutput
142+
}
143+
144+
val iOSRuntimesData = groovy.json.JsonSlurper().parseText(iOSRuntimesOutput.toString()) as Map<String, List<Map<String, Any>>>
145+
val runtimesIdentifiers = iOSRuntimesData["runtimes"]!!.map { it["identifier"]!! } as List<String>
146+
val latestRuntimeIdentifier = runtimesIdentifiers.maxOrNull()!!
147+
println("Latest iOS runtime: $latestRuntimeIdentifier")
148+
149+
println("Retrieving device for iOS simulator")
150+
val devicesOutput = ByteArrayOutputStream()
151+
exec {
152+
commandLine("xcrun", "simctl", "list", "--json", "devices")
153+
standardOutput = devicesOutput
154+
}
155+
val devicesData = groovy.json.JsonSlurper().parseText(devicesOutput.toString()) as Map<String, Map<String, List<Map<String, String>>>>
156+
val devices = devicesData["devices"]!!
157+
val device = devices[latestRuntimeIdentifier]!!.find { it["name"] == deviceName }
158+
val udid = device!!["udid"]
159+
println("Using device: $deviceName ($udid)")
160+
161+
exec {
162+
println("Building test model")
163+
commandLine("python3", "build_dummy_model.py")
164+
}
165+
166+
val simulatorFilesPath = "/Users/${System.getProperty("user.name")}/Library/Developer/CoreSimulator/Devices/$udid/data/Documents"
167+
168+
exec {
169+
println("Setting up iOS simulator documents directory")
170+
commandLine("mkdir", "-p", simulatorFilesPath)
171+
}
172+
173+
exec {
174+
println("Copying model to iOS simulator files ($simulatorFilesPath)")
175+
commandLine("cp", "dummy_module.ptl", simulatorFilesPath)
176+
}
177+
178+
exec {
179+
println("Running simulator tests")
180+
val binary = target.binaries.getTest("DEBUG").outputFile
181+
commandLine("xcrun", "simctl", "spawn", "--standalone", udid, binary.absolutePath)
182+
}
183+
}
184+
}
185+
}

ios/LibTorchWrapper/LibTorchWrapper/IValueWrapper.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#import <LibTorch-Lite/LibTorch-Lite.h>
1+
#import <VoizeLibTorch-Lite/LibTorch-Lite.h>
22
#import <Foundation/Foundation.h>
33
#import "IValueWrapper.h"
44
#import "Tensor.h"

ios/LibTorchWrapper/LibTorchWrapper/Tensor.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#import <LibTorch-Lite/LibTorch-Lite.h>
1+
#import <VoizeLibTorch-Lite/LibTorch-Lite.h>
22
#import <Foundation/Foundation.h>
33
#import "Tensor.h"
44

ios/LibTorchWrapper/LibTorchWrapper/TorchModule.mm

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#import "TorchModule.h"
22
#import "Tensor.h"
33
#import "IValueWrapper.h"
4-
#import <LibTorch-Lite/LibTorch-Lite.h>
4+
#import <VoizeLibTorch-Lite/LibTorch-Lite.h>
55

66
@implementation TorchModule {
77
@protected

ios/LibTorchWrapper/PLMLibTorchWrapper.podspec

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,9 @@ Pod::Spec.new do |spec|
1414

1515
spec.source_files = "LibTorchWrapper/**/*.{h,m,mm}"
1616

17-
spec.dependency 'LibTorch-Lite', '1.13.0.1'
17+
spec.dependency 'VoizeLibTorch-Lite', '2.1.0'
1818
spec.frameworks = 'Accelerate'
1919

20-
spec.xcconfig = {
21-
'HEADER_SEARCH_PATHS' => '"${PODS_ROOT}/LibTorch-Lite/install/include/"',
22-
'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64',
23-
}
20+
spec.compiler_flags = '-std=c++17'
2421

2522
end

ios/LibTorchWrapper/Podfile

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,5 @@ target 'LibTorchWrapper' do
55
# Comment the next line if you don't want to use dynamic frameworks
66
use_frameworks!
77

8-
# Pods for LibTorchWrapper
9-
pod 'LibTorch-Lite', '1.13.0.1'
10-
8+
pod 'VoizeLibTorch-Lite', '2.1.0'
119
end

ios/LibTorchWrapper/Podfile.lock

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,16 @@
11
PODS:
2-
- LibTorch-Lite (1.13.0.1):
3-
- LibTorch-Lite/Core (= 1.13.0.1)
4-
- LibTorch-Lite/Core (1.13.0.1):
5-
- LibTorch-Lite/Torch
6-
- LibTorch-Lite/Torch (1.13.0.1)
2+
- VoizeLibTorch-Lite (2.1.0)
73

84
DEPENDENCIES:
9-
- LibTorch-Lite (= 1.13.0.1)
5+
- VoizeLibTorch-Lite (= 2.1.0)
106

117
SPEC REPOS:
128
trunk:
13-
- LibTorch-Lite
9+
- VoizeLibTorch-Lite
1410

1511
SPEC CHECKSUMS:
16-
LibTorch-Lite: dd01cdefa487b3b1d41f1c8a4495f5e41c79fd80
12+
VoizeLibTorch-Lite: 092115192956cd375d6eef9cac95f38c5df57908
1713

18-
PODFILE CHECKSUM: 56e1939633710f5b0fd08b1be9588e070b744861
14+
PODFILE CHECKSUM: 1dee2217ce79847faaa7b679557dea1e8cf93bed
1915

20-
COCOAPODS: 1.11.3
16+
COCOAPODS: 1.15.2

src/iosMain/kotlin/de/voize/pytorch_lite_multiplatform/IValue.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,4 +124,4 @@ actual class IValue internal constructor(val nativeIValue: IValueWrapper) {
124124
return IValue(IValueWrapper(dictLongKey = nativeIValues as Map<Any?, *>))
125125
}
126126
}
127-
}
127+
}

src/iosMain/kotlin/de/voize/pytorch_lite_multiplatform/PLMScope.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ actual fun <R> plmScoped(block: PLMScope.()->R): R {
99
val scope = PLMScope(this)
1010
scope.block()
1111
}
12-
}
12+
}

0 commit comments

Comments
 (0)