diff --git a/DEVGUIDE.md b/DEVGUIDE.md
index e9ce1eec7..c7187ae21 100644
--- a/DEVGUIDE.md
+++ b/DEVGUIDE.md
@@ -45,6 +45,8 @@ Requirements:
Build with
dotnet build /p:SkipNative=true
+
+By default, this will build for your system's architecture (x64 vs arm64/M1). To override this, add `/p:TargetArchitecture=x64` or `/p:TargetArchitecture=arm64` to your build command.
## Packages
diff --git a/Directory.Build.props b/Directory.Build.props
index 40f3e1c77..2316b0353 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -7,8 +7,9 @@
Debug
Debug;Release
- x64
- x64
+ <_DefaultArchitecture>$([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString().ToLower())
+ AnyCPU
+ $(_DefaultArchitecture)
$(TargetArchitecture)
$(Platform).$(Configuration)
@@ -50,9 +51,12 @@
mac
linux
+ $(TargetOS)-$(TargetArchitecture)
+
win-x64
linux-x64
osx-x64
+ osx-arm64
-debug
@@ -125,13 +129,18 @@
+ pytorch
+ conda
+ osx-arm64
%252Bcpu
+ -py3.10_0
%252Bcu$(CudaVersionNoDot)
cpu
cu$(CudaVersionNoDot)
libtorch-win-shared-with-deps$(LibTorchDebug)
libtorch-shared-with-deps
libtorch-macos
+ pytorch
$(LibTorchArchiveCoreName)-$(LibTorchVersion)$(LibTorchCpuArchiveNameSuffix)
$(LibTorchArchiveCoreName)-$(LibTorchVersion)$(LibTorchCudaArchiveNameSuffix)
$(LibTorchArchiveCoreName)-$(LibTorchVersion)$(LibTorchCpuLocalNameSuffix)
diff --git a/Directory.Build.targets b/Directory.Build.targets
index d0bd1e93b..5d2ce4d53 100644
--- a/Directory.Build.targets
+++ b/Directory.Build.targets
@@ -1,7 +1,7 @@
-
+
-
+
@@ -62,7 +62,7 @@
-
+
@@ -78,6 +78,15 @@
+
+
+
+
+
+
+
+
+
@@ -124,5 +133,5 @@
-
+
\ No newline at end of file
diff --git a/README.md b/README.md
index debaa1c3c..65df44e8d 100644
--- a/README.md
+++ b/README.md
@@ -99,9 +99,11 @@ To use TorchSharp, you also need one of the LibTorch backend packages: https://w
* `libtorch-cpu-win-x64` (CPU, Windows)
-* `libtorch-cpu-osx-x64` (CPU, OSX)
+* `libtorch-cpu-osx-x64` (CPU, OSX-x64)
-* `libtorch-cpu` (CPU, references all three, larger download but simpler)
+* `libtorch-cpu-osx-arm64` (CPU, OSX-arm64)
+
+* `libtorch-cpu` (CPU, references all four, larger download but simpler)
* `libtorch-cuda-11.7-linux-x64` (CPU/CUDA 11.3, Linux)
diff --git a/azure-pipelines.yml b/azure-pipelines.yml
index e020d3063..b6d73e2cd 100644
--- a/azure-pipelines.yml
+++ b/azure-pipelines.yml
@@ -71,6 +71,15 @@ jobs:
pool:
vmImage: 'macos-11'
+- template: /build/ci/job-template.yml
+ parameters:
+ prepScript: echo "no prep needed"
+ name: MacOS_arm64
+ buildScript: dotnet build /p:SkipCuda=true /p:TargetArchitecture=arm64 -c
+ testScript: echo "Azure Pipelines does not support arm64 yet, can't run tests"
+ pool:
+ vmImage: 'macos-11'
+
################################################################################
# {Build} --> combine --> package to build native bits on multiple OS's
################################################################################
@@ -166,7 +175,7 @@ jobs:
artifact: WindowsAssets
# ################################################################################
-- job: MacOS_Native_Build_For_Packages
+- job: MacOS_x64_Native_Build_For_Packages
# ################################################################################
condition: and(ne(variables['system.pullrequest.isfork'], true), eq(variables['build.sourcebranchname'], 'main'))
variables:
@@ -182,7 +191,7 @@ jobs:
displayName: Download libtorch native binaries
- script: dotnet build -c $(BuildConfig) src/TorchSharp/TorchSharp.csproj /p:SkipCuda=true
- displayName: Build mac
+ displayName: Build mac-x64
- script: dotnet build -c $(BuildConfig) src/TorchVision/TorchVision.csproj /p:SkipCuda=true
displayName: Build TorchVision
@@ -191,7 +200,35 @@ jobs:
displayName: Build TorchAudio
- publish: $(Build.SourcesDirectory)/bin/obj/packprep/$(BuildConfig)
- artifact: MacAssets
+ artifact: MacAssets_x64
+
+ # ################################################################################
+- job: MacOS_arm64_Native_Build_For_Packages
+ # ################################################################################
+ condition: and(ne(variables['system.pullrequest.isfork'], true), eq(variables['build.sourcebranchname'], 'main'))
+ variables:
+ BuildConfig: Release
+ OfficialBuildId: $(BUILD.BUILDNUMBER)
+ DOTNET_CLI_TELEMETRY_OPTOUT: 1
+ DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
+ DOTNET_MULTILEVEL_LOOKUP: 0
+ pool:
+ vmImage: 'macos-11'
+ steps:
+ - script: dotnet build -c $(BuildConfig) src/Redist/libtorch-cpu/libtorch-cpu.proj /p:UpdateSHA=true /p:TargetOS=mac /p:TargetArchitecture=arm64 /t:Build /p:IncludeLibTorchCpuPackages=true
+ displayName: Download libtorch native binaries
+
+ - script: dotnet build -c $(BuildConfig) src/TorchSharp/TorchSharp.csproj /p:SkipCuda=true /p:TargetArchitecture=arm64
+ displayName: Build mac-arm64
+
+ - script: dotnet build -c $(BuildConfig) src/TorchVision/TorchVision.csproj /p:SkipCuda=true /p:TargetArchitecture=arm64
+ displayName: Build TorchVision
+
+ - script: dotnet build -c $(BuildConfig) src/TorchAudio/TorchAudio.csproj /p:SkipCuda=true /p:TargetArchitecture=arm64
+ displayName: Build TorchAudio
+
+ - publish: $(Build.SourcesDirectory)/bin/obj/packprep/$(BuildConfig)
+ artifact: MacAssets_arm64
################################################################################
@@ -201,7 +238,8 @@ jobs:
dependsOn:
- Linux_Native_Build_For_Packages
- Windows_Native_Build_For_Packages
- - MacOS_Native_Build_For_Packages
+ - MacOS_x64_Native_Build_For_Packages
+ - MacOS_arm64_Native_Build_For_Packages
variables:
BuildConfig: Release
OfficialBuildId: $(BUILD.BUILDNUMBER)
@@ -249,36 +287,67 @@ jobs:
- script: rmdir /s /q $(Pipeline.Workspace)\LinuxAssets
displayName: Free up space (LinuxAssets in workspace)
- # Download all bits contributing to the packages from the Mac build
+ # Download all bits contributing to the packages from the Mac x64 build
- download: current
- artifact: MacAssets
+ artifact: MacAssets_x64
- task: CopyFiles@2
- displayName: Copy mac native assets (TorchSharp) to correct folder where the bits contributing to the packages are assembled
+ displayName: Copy mac-x64 native assets (TorchSharp) to correct folder where the bits contributing to the packages are assembled
inputs:
- sourceFolder: $(Pipeline.Workspace)/MacAssets/TorchSharp
+ sourceFolder: $(Pipeline.Workspace)/MacAssets_x64/TorchSharp
targetFolder: $(Build.SourcesDirectory)/bin/obj/packprep/$(BuildConfig)/TorchSharp
- task: CopyFiles@2
- displayName: Copy mac native assets (TorchAudio) to correct folder where the bits contributing to the packages are assembled
+ displayName: Copy mac-x64 native assets (TorchAudio) to correct folder where the bits contributing to the packages are assembled
inputs:
- sourceFolder: $(Pipeline.Workspace)/MacAssets/TorchAudio
+ sourceFolder: $(Pipeline.Workspace)/MacAssets_x64/TorchAudio
targetFolder: $(Build.SourcesDirectory)/bin/obj/packprep/$(BuildConfig)/TorchAudio
- task: CopyFiles@2
- displayName: Copy mac native assets (TorchVision) to correct folder where the bits contributing to the packages are assembled
+ displayName: Copy mac-x64 native assets (TorchVision) to correct folder where the bits contributing to the packages are assembled
inputs:
- sourceFolder: $(Pipeline.Workspace)/MacAssets/TorchVision
+ sourceFolder: $(Pipeline.Workspace)/MacAssets_x64/TorchVision
targetFolder: $(Build.SourcesDirectory)/bin/obj/packprep/$(BuildConfig)/TorchVision
- task: CopyFiles@2
- displayName: Copy mac native assets (libtorch-cpu) to correct folder where the bits contributing to the packages are assembled
+ displayName: Copy mac-x64 native assets (libtorch-cpu) to correct folder where the bits contributing to the packages are assembled
inputs:
- sourceFolder: $(Pipeline.Workspace)/MacAssets/libtorch-cpu-osx-x64
+ sourceFolder: $(Pipeline.Workspace)/MacAssets_x64/libtorch-cpu-osx-x64
targetFolder: $(Build.SourcesDirectory)/bin/obj/packprep/$(BuildConfig)/libtorch-cpu-osx-x64
- - script: rmdir /s /q $(Pipeline.Workspace)\MacAssets
- displayName: Free up space (MacAssets in workspace)
+ - script: rmdir /s /q $(Pipeline.Workspace)\MacAssets_x64
+ displayName: Free up space (MacAssets_x64 in workspace)
+
+ # Download all bits contributing to the packages from the Mac arm64 build
+ - download: current
+ artifact: MacAssets_arm64
+
+ - task: CopyFiles@2
+ displayName: Copy mac-arm64 native assets (TorchSharp) to correct folder where the bits contributing to the packages are assembled
+ inputs:
+ sourceFolder: $(Pipeline.Workspace)/MacAssets_arm64/TorchSharp
+ targetFolder: $(Build.SourcesDirectory)/bin/obj/packprep/$(BuildConfig)/TorchSharp
+
+ - task: CopyFiles@2
+ displayName: Copy mac-arm64 native assets (TorchAudio) to correct folder where the bits contributing to the packages are assembled
+ inputs:
+ sourceFolder: $(Pipeline.Workspace)/MacAssets_arm64/TorchAudio
+ targetFolder: $(Build.SourcesDirectory)/bin/obj/packprep/$(BuildConfig)/TorchAudio
+
+ - task: CopyFiles@2
+ displayName: Copy mac-arm64 native assets (TorchVision) to correct folder where the bits contributing to the packages are assembled
+ inputs:
+ sourceFolder: $(Pipeline.Workspace)/MacAssets_arm64/TorchVision
+ targetFolder: $(Build.SourcesDirectory)/bin/obj/packprep/$(BuildConfig)/TorchVision
+
+ - task: CopyFiles@2
+ displayName: Copy mac-arm64 native assets (libtorch-cpu) to correct folder where the bits contributing to the packages are assembled
+ inputs:
+ sourceFolder: $(Pipeline.Workspace)/MacAssets_arm64/libtorch-cpu-osx-arm64
+ targetFolder: $(Build.SourcesDirectory)/bin/obj/packprep/$(BuildConfig)/libtorch-cpu-osx-arm64
+
+ - script: rmdir /s /q $(Pipeline.Workspace)\MacAssets_arm64
+ displayName: Free up space (MacAssets_arm64 in workspace)
- download: current
artifact: WindowsAssets
diff --git a/pkg/libtorch-cpu-osx-arm64/libtorch-cpu-osx-arm64.nupkgproj b/pkg/libtorch-cpu-osx-arm64/libtorch-cpu-osx-arm64.nupkgproj
new file mode 100644
index 000000000..d8ce731a6
--- /dev/null
+++ b/pkg/libtorch-cpu-osx-arm64/libtorch-cpu-osx-arm64.nupkgproj
@@ -0,0 +1,16 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pkg/libtorch-cpu/libtorch-cpu.nupkgproj b/pkg/libtorch-cpu/libtorch-cpu.nupkgproj
index 32a70e59b..f8d75cb83 100644
--- a/pkg/libtorch-cpu/libtorch-cpu.nupkgproj
+++ b/pkg/libtorch-cpu/libtorch-cpu.nupkgproj
@@ -7,6 +7,7 @@
+
diff --git a/src/Examples.Utils/Examples.Utils.csproj b/src/Examples.Utils/Examples.Utils.csproj
index 1f6d5a081..794a09947 100644
--- a/src/Examples.Utils/Examples.Utils.csproj
+++ b/src/Examples.Utils/Examples.Utils.csproj
@@ -9,10 +9,6 @@
net6.0
-
- x64
-
-
diff --git a/src/Examples/Examples.csproj b/src/Examples/Examples.csproj
index 4bac9a142..38853cad4 100644
--- a/src/Examples/Examples.csproj
+++ b/src/Examples/Examples.csproj
@@ -15,7 +15,6 @@
false
TorchSharp.Examples.Program
false
- x64
TorchSharp.Examples
diff --git a/src/Native/LibTorchSharp/CMakeLists.txt b/src/Native/LibTorchSharp/CMakeLists.txt
index d1f3b51a4..db3626b28 100644
--- a/src/Native/LibTorchSharp/CMakeLists.txt
+++ b/src/Native/LibTorchSharp/CMakeLists.txt
@@ -1,6 +1,6 @@
project(LibTorchSharp)
-if(APPLE)
+if(APPLE AND NOT LIBTORCH_ARCH STREQUAL "arm64")
include_directories("/usr/local/include" "/usr/local/opt/llvm/include")
link_directories("/usr/local/lib" "/usr/local/opt/llvm/lib")
endif()
@@ -56,6 +56,15 @@ if(NOT WIN32)
endif()
endif()
+# Enable cross compilation for arm64/x64 on macOS
+if(APPLE)
+ if(LIBTORCH_ARCH STREQUAL "arm64")
+ set(CMAKE_OSX_ARCHITECTURES "arm64")
+ else()
+ set(CMAKE_OSX_ARCHITECTURES "x86_64")
+ endif()
+endif()
+
# Add libTorch bindings
include_directories(${TORCH_INCLUDE_DIRS})
diff --git a/src/Native/LibTorchSharp/crc32c.c b/src/Native/LibTorchSharp/crc32c.c
index 6f34e23b3..f044397ff 100644
--- a/src/Native/LibTorchSharp/crc32c.c
+++ b/src/Native/LibTorchSharp/crc32c.c
@@ -30,12 +30,15 @@
// Per #2 in the copyright notice above:
//
// The definition of 'NONMINMAX' below was altered from the original.
+// cpuid.h and x86intrin.h are only included if we're on x86 or x64, fixing arm builds.
//#define NOMINMAX
#ifdef CRC32C_GCC
+#if defined(__x86_64__) || defined(__i386__)
#include
#include
+#endif
#else
#include
#endif
diff --git a/src/Native/build.sh b/src/Native/build.sh
index d04636db1..fdc14f190 100755
--- a/src/Native/build.sh
+++ b/src/Native/build.sh
@@ -59,7 +59,7 @@ while [ "$1" != "" ]; do
done
# Force the build to be release since libtorch is in release.
-__cmake_defines="-DCMAKE_BUILD_TYPE=${__configuration} ${__strip_argument} -DLIBTORCH_PATH=${__libtorchpath}"
+__cmake_defines="-DCMAKE_BUILD_TYPE=${__configuration} ${__strip_argument} -DLIBTORCH_PATH=${__libtorchpath} -DLIBTORCH_ARCH=${__build_arch}"
__IntermediatesDir="$__baseIntermediateOutputPath/$__build_arch.$__configuration/Native"
__BinDir="$__rootBinPath/$__build_arch.$__configuration/Native"
diff --git a/src/Redist/libtorch-cpu/libtorch-cpu.proj b/src/Redist/libtorch-cpu/libtorch-cpu.proj
index 74d269950..33c853b3e 100644
--- a/src/Redist/libtorch-cpu/libtorch-cpu.proj
+++ b/src/Redist/libtorch-cpu/libtorch-cpu.proj
@@ -8,8 +8,13 @@
$(LibTorchCpuLocalBase)
$(LibTorchCpuArchiveBase)
+ $(LibTorchArchiveSource)
.zip
https://download.pytorch.org/libtorch/cpu/$(ArchiveBaseName)$(ArchiveExtension)
+ .tar.bz2
+
+ https://conda.anaconda.org/pytorch/$(CondaArchivePlatformName)/$(ArchiveBaseName)$(ArchiveExtension)
+
$(MassiveDownloadRoot)$(MSBuildProjectName)\
$(ArchiveBaseName)$(ArchiveExtension)
$(DownloadedArchiveFolder)$(DownloadedArchiveFileName)
@@ -24,7 +29,7 @@
$(PackagePreparationPath)$(MSBuildProjectName)-$(TargetRuntimeID)
$(MainPackageFolder)\.copied.SkipTests.$(SkipTests).IncludeLibTorchCpuPackages.$(IncludeLibTorchCpuPackages)
-
+
@@ -38,7 +43,7 @@
-
+
@@ -52,6 +57,13 @@
+
+
+
+
+
+
+
@@ -105,12 +117,20 @@
+
+
+
+
diff --git a/src/Redist/libtorch-cpu/pytorch-1.13.0-py3.10_0.tar.bz2.sha b/src/Redist/libtorch-cpu/pytorch-1.13.0-py3.10_0.tar.bz2.sha
new file mode 100644
index 000000000..e2552c1d1
--- /dev/null
+++ b/src/Redist/libtorch-cpu/pytorch-1.13.0-py3.10_0.tar.bz2.sha
@@ -0,0 +1 @@
+3C22DC05D614895F583588E94ACCDB0922916D358CA9D6085376586EAB152519
diff --git a/src/TorchSharp/Torch.cs b/src/TorchSharp/Torch.cs
index eaafda124..de05b91f4 100644
--- a/src/TorchSharp/Torch.cs
+++ b/src/TorchSharp/Torch.cs
@@ -30,6 +30,7 @@ public static partial class torch
static string nativeRid =>
RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "win-x64" :
RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ? "linux-x64" :
+ RuntimeInformation.IsOSPlatform(OSPlatform.OSX) && RuntimeInformation.OSArchitecture == Architecture.Arm64 ? "osx-arm64" :
RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? "osx-x64" :
"any";
diff --git a/test/TorchSharpTest.WithCudaBinaries/TorchSharpTest.WithCudaBinaries.csproj b/test/TorchSharpTest.WithCudaBinaries/TorchSharpTest.WithCudaBinaries.csproj
index e097d0dc8..e6830d131 100644
--- a/test/TorchSharpTest.WithCudaBinaries/TorchSharpTest.WithCudaBinaries.csproj
+++ b/test/TorchSharpTest.WithCudaBinaries/TorchSharpTest.WithCudaBinaries.csproj
@@ -9,7 +9,6 @@
true
true
false
- x64
false
trx
$(OutputPath)
diff --git a/test/TorchSharpTest/TorchSharpTest.csproj b/test/TorchSharpTest/TorchSharpTest.csproj
index f1c1b54e7..2343302fe 100644
--- a/test/TorchSharpTest/TorchSharpTest.csproj
+++ b/test/TorchSharpTest/TorchSharpTest.csproj
@@ -9,7 +9,6 @@
net6.0
true
false
- x64
false
trx
$(OutputPath)