Support Apple silicon
Trying to load the dylib on Apple silicon gives this error:
Exception in thread "main" java.lang.UnsatisfiedLinkError: /private/var/folders/1b/331lr8s90xxcdx51x0pbwc7w0000gn/T/libjava-tree-sitter.dylib: dlopen(/private/var/folders/1b/331lr8s90xxcdx51x0pbwc7w0000gn/T/libjava-tree-sitter.dylib, 0x0001): tried: '/private/var/folders/1b/331lr8s90xxcdx51x0pbwc7w0000gn/T/libjava-tree-sitter.dylib' (mach-o file, but is an incompatible architecture (have 'x86_64', need 'arm64')), '/System/Volumes/Preboot/Cryptexes/OS/private/var/folders/1b/331lr8s90xxcdx51x0pbwc7w0000gn/T/libjava-tree-sitter.dylib' (no such file), '/private/var/folders/1b/331lr8s90xxcdx51x0pbwc7w0000gn/T/libjava-tree-sitter.dylib' (mach-o file, but is an incompatible architecture (have 'x86_64', need 'arm64'))
at java.base/jdk.internal.loader.NativeLibraries.load(Native Method)
at java.base/jdk.internal.loader.NativeLibraries$NativeLibraryImpl.open(NativeLibraries.java:388)
at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:232)
at java.base/jdk.internal.loader.NativeLibraries.loadLibrary(NativeLibraries.java:174)
at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2389)
at java.base/java.lang.Runtime.load0(Runtime.java:755)
at java.base/java.lang.System.load(System.java:1953)
at ch.usi.si.seart.treesitter.LibraryLoader.load(LibraryLoader.java:73)
at org.example.Main.<clinit>(Main.java:11)
Important part being (mach-o file, but is an incompatible architecture (have 'x86_64', need 'arm64'))
This is revealed with lipo:
$ lipo -archs libjava-tree-sitter.dylib
x86_64
It should be possible to create a universal binary using something like this method: https://developer.apple.com/documentation/apple-silicon/building-a-universal-macos-binary#Update-the-Architecture-List-of-Custom-Makefiles
Hi @ivangreene
Thank you for the report. Unfortunately, this is a long-standing issue that we are very much aware of. The original developers wrote the build script used for this project. The file is quite messy and will most likely be rewritten from scratch soon. The way it works is it builds for only one specified OS and architecture at a time. At the same time, when we build for release we do it locally on one of our machines, before publishing to Maven Central. Since we use only one machine with specific specs, we can only reliably compile for the x86_64 architecture. We plan to address this by migrating our build, test and release to GitHub actions, which will allow us to support a wider range of architectures.
Currently, the only way to work around the issue is to compile the JAR yourself locally and include it in your project. Since you are running this on MacOS you would need to modify the build-shared-object-library-macos execution to include the appropriate architecture parameter:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.1</version>
<executions>
<!-- OMITTED FOR BREVITY -->
<execution>
<id>build-shared-object-library-macos</id>
<phase>compile</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>python3</executable>
<workingDirectory>${project.basedir}</workingDirectory>
<arguments>
<argument>build.py</argument>
+ <argument>-a</argument>
+ <argument>aarch64</argument>
<argument>-o</argument>
<argument>${project.build.outputDirectory}/libjava-tree-sitter</argument>
</arguments>
</configuration>
</execution>
<!-- OMITTED FOR BREVITY -->
</executions>
</plugin>
Since you are compiling locally for just MacOS, you can also skip the Linux compilation entirely:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>3.1.1</version>
<!-- OMITTED FOR BREVITY -->
<execution>
<id>build-shared-object-library-linux</id>
<phase>compile</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
+ <skip>true</skip>
<!-- OMITTED FOR BREVITY -->
</configuration>
</execution>
</executions>
</plugin>
I'll keep the issue open for the moment, but it might be superseded by a more general one in the future.
Thanks, looking forward to a build with both architectures in the future. As a note, the build works as-is locally because the build.py determines the host's architecture, so didn't need to add the argument in the pom