Skip to content

Commit

Permalink
Update build configurations and library loading for cross-platform su…
Browse files Browse the repository at this point in the history
…pport

This update enhances the libclang loading process in 'RuntimeHelper.java' to ensure better cross-platform compatibility. It also modifies the 'klang/build.gradle.kts' file to extract and copy libclang binaries when required during the build phase. Lastly, it introduces a new method in 'TypeRef.kt' to accommodate 'TypeImpl.QualifiedImpl' instances.
  • Loading branch information
Alexandre Mommers committed Dec 31, 2023
1 parent 56455c3 commit 9f47359
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 26 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,26 +26,17 @@
package org.openjdk.jextract.clang.libclang;
// Generated by jextract

import java.lang.foreign.Arena;
import java.lang.foreign.Linker;
import java.lang.foreign.FunctionDescriptor;
import java.lang.foreign.GroupLayout;
import java.lang.foreign.SymbolLookup;
import java.lang.foreign.MemoryLayout;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.SegmentAllocator;
import java.lang.foreign.ValueLayout;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.foreign.*;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Optional;
import java.util.stream.Stream;
import java.nio.file.StandardCopyOption;

import static java.lang.foreign.Linker.*;
import static java.lang.foreign.ValueLayout.*;

final class RuntimeHelper {
Expand All @@ -54,22 +45,37 @@ final class RuntimeHelper {
private static final ClassLoader LOADER = RuntimeHelper.class.getClassLoader();
private static final MethodHandles.Lookup MH_LOOKUP = MethodHandles.lookup();
private static final SymbolLookup SYMBOL_LOOKUP;
private static final SegmentAllocator THROWING_ALLOCATOR = (x, y) -> { throw new AssertionError("should not reach here"); };
private static final SegmentAllocator THROWING_ALLOCATOR = (x, y) -> {
throw new AssertionError("should not reach here");
};

final static SegmentAllocator CONSTANT_ALLOCATOR =
(size, align) -> Arena.ofAuto().allocate(size, align);

static {
var libraryFile = new File(getTemporaryDirectory() + inferLibraryFileName());
if (!libraryFile.exists()) {
var embeddedLibraryFile = findFileInClasspath(inferEmbededLibraryFileName());
try {
copyInputStreamToFile(embeddedLibraryFile, libraryFile.getAbsolutePath());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
libraryFile.deleteOnExit();

System.load(libraryFile.getAbsolutePath());
// Manual change to handle platform specific library name difference
String libName = System.getProperty("os.name").startsWith("Windows")? "libclang" : "clang";
System.loadLibrary(libName);
//String libName = System.getProperty("os.name").startsWith("Windows") ? "libclang" : "clang";
//System.loadLibrary(libName);

SymbolLookup loaderLookup = SymbolLookup.loaderLookup();
SYMBOL_LOOKUP = name -> loaderLookup.find(name).or(() -> LINKER.defaultLookup().find(name));
}

// Suppresses default constructor, ensuring non-instantiability.
private RuntimeHelper() {}
private RuntimeHelper() {
}

static <T> T requireNonNull(T obj, String symbolName) {
if (obj == null) {
Expand Down Expand Up @@ -111,7 +117,7 @@ static <Z> MemorySegment upcallStub(Class<Z> fi, Z z, FunctionDescriptor fdesc,
}

static MemorySegment asArray(MemorySegment addr, MemoryLayout layout, int numElements, Arena arena) {
return addr.reinterpret(numElements * layout.byteSize(), arena, null);
return addr.reinterpret(numElements * layout.byteSize(), arena, null);
}

// Internals only below this point
Expand Down Expand Up @@ -143,7 +149,7 @@ static MethodHandle make(MemorySegment symbol, FunctionDescriptor function) {
}
mtype = mtype.appendParameterTypes(Object[].class);
boolean needsAllocator = function.returnLayout().isPresent() &&
function.returnLayout().get() instanceof GroupLayout;
function.returnLayout().get() instanceof GroupLayout;
if (needsAllocator) {
mtype = mtype.insertParameterTypes(0, SegmentAllocator.class);
} else {
Expand All @@ -165,7 +171,7 @@ static Class<?> carrier(MemoryLayout layout, boolean ret) {
private Object invoke(SegmentAllocator allocator, Object[] args) throws Throwable {
// one trailing Object[]
int nNamedArgs = function.argumentLayouts().size();
assert(args.length == nNamedArgs + 1);
assert (args.length == nNamedArgs + 1);
// The last argument is the array of vararg collector
Object[] unnamedArgs = (Object[]) args[args.length - 1];

Expand All @@ -179,7 +185,7 @@ private Object invoke(SegmentAllocator allocator, Object[] args) throws Throwabl
}

assert pos == nNamedArgs;
for (Object o: unnamedArgs) {
for (Object o : unnamedArgs) {
argLayouts[pos] = variadicLayout(normalize(o.getClass()));
pos++;
}
Expand All @@ -190,7 +196,7 @@ private Object invoke(SegmentAllocator allocator, Object[] args) throws Throwabl
FunctionDescriptor.of(function.returnLayout().get(), argLayouts);
MethodHandle mh = LINKER.downcallHandle(symbol, f);
boolean needsAllocator = function.returnLayout().isPresent() &&
function.returnLayout().get() instanceof GroupLayout;
function.returnLayout().get() instanceof GroupLayout;
if (needsAllocator) {
mh = mh.bindTo(allocator);
}
Expand Down Expand Up @@ -259,4 +265,62 @@ private MemoryLayout variadicLayout(Class<?> c) {
}
}
}

private static String inferEmbededLibraryFileName() {
return STR."libclang-\{inferArchitecture()}.\{inferLibraryExtension()}";
}

private static String inferLibraryFileName() {
return STR."libclang.\{inferLibraryExtension()}";
}

private static String inferLibraryExtension() {
var osName = System.getProperty("os.name").toLowerCase();

if (osName.startsWith("windows")) {
return "dll";
} else if (osName.contains("nix") || osName.contains("nux")) {
return "so";
} else if (osName.contains("mac")) {
return "dylib";
}

throw new UnsupportedOperationException(STR."Unsupported operating system: \{osName}");
}

private static String inferArchitecture() {
var architecture = System.getProperty("os.arch").toLowerCase();

if (architecture.contains("amd64")
|| architecture.contains("x86_64")
|| architecture.contains("x86")
|| architecture.contains("i386")) {
return "x86_64";
} else if (architecture.contains("arm")) {
return "arm86";
}

throw new UnsupportedOperationException(STR."Unsupported architecture: \{architecture}");
}
private static InputStream findFileInClasspath(String fileName) {
// Get current classloader
ClassLoader classLoader = RuntimeHelper.class.getClassLoader();

// Find the resource
InputStream resourceStream = classLoader.getResourceAsStream(fileName);

if (resourceStream == null) {
throw new IllegalArgumentException(STR."File not found in classpath: \{fileName}");
}

return resourceStream;
}

private static void copyInputStreamToFile(InputStream source, String targetFilePath) throws IOException {
Files.copy(source, Path.of(targetFilePath), StandardCopyOption.REPLACE_EXISTING);
}

private static String getTemporaryDirectory() {
return System.getProperty("java.io.tmpdir");
}
}
4 changes: 2 additions & 2 deletions klang/klang/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ tasks.withType<Test>().configureEach {
"--enable-native-access=ALL-UNNAMED"
//, "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005"
)
systemProperties(
/*systemProperties(
"java.library.path" to inferPlatformClangPath()?.toFile()?.absolutePath
)
)*/
}

private fun inferPlatformClangPath(): Path? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,6 @@ internal fun Type.toTypeRef(): TypeRef = when (this) {
private fun Type.toTypeString(): String = when (this) {
is TypeImpl.DeclaredImpl -> tree().name()
is TypeImpl.PrimitiveImpl -> kind().typeName()
is TypeImpl.QualifiedImpl -> type().toTypeString()
else -> TODO("unsupported yet")
}

0 comments on commit 9f47359

Please sign in to comment.