Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 46 additions & 18 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,6 @@ if (clang_versions.length == 0) {
" Make sure a ${llvm_home}/lib/clang/<VERSION> directory exists")
}
def clang_version = clang_versions[0]

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please clean up the spurious white space changes from the patch.

def buildDir = layout.buildDirectory.get()
def jextract_version = "23"
def jmods_dir = "$buildDir/jmods"
Expand Down Expand Up @@ -73,24 +72,32 @@ jar {
task copyLibClang(type: Sync) {
into("$buildDir/jmod_inputs")

// make sure we only pick up the "real" shared library file from LLVM installation
// (e.g. exclude symlinks on Linux)
def clang_path_include = (Os.isFamily(Os.FAMILY_UNIX) && !Os.isFamily(Os.FAMILY_MAC)) ?
"libclang.so.${clang_version}" : "*clang*"

from("${libclang_dir}") {
include(clang_path_include)
include("libLLVM.*")
exclude("clang.exe")
into("libs")
// make sure we drop shared library version name (Linux only)
rename("libclang.so.${clang_version}", "libclang.so")
}

from("$clang_include_dir") {
// make sure we only pick up the "real" shared library file from LLVM installation
// (e.g. exclude symlinks on Linux)
def isAix = Os.isName("AIX") || Os.isName("aix")
def isUnixNotMac = Os.isFamily(Os.FAMILY_UNIX) && !Os.isFamily(Os.FAMILY_MAC)
def clang_path_include =
isAix ? "libclang.a" :
isUnixNotMac ? "libclang.so.${clang_version}" :
"*clang*"
from("${libclang_dir}") {
include(clang_path_include)
include("libLLVM.*")
exclude("clang.exe")
into("libs")
// make sure we drop shared library version name (Linux only)
rename("libclang.so.*", "libclang.so")

}
from("${libclang_dir}") {
include("libclang.a")
into("$buildDir/test-libs")
}
Comment on lines +92 to +95
Copy link
Member

@JornVernee JornVernee Dec 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look right. This task is meant from creating the jmod inputs, not for setting up tests. This shouldn't be needed any way, since the tests are run on a runtime image that includes the library already.

from("$clang_include_dir") {
include("*.h")
into("conf/jextract")
}
}

}

task createJextractJmod(type: Exec) {
Expand Down Expand Up @@ -194,6 +201,8 @@ task createRuntimeImageForTest(type: Exec) {

task cmakeConfigure(type: Exec) {
executable = "cmake"
environment "CC", "/opt/IBM/xlC/13.1.3/bin/xlc"
environment "CXX", "/opt/IBM/xlC/13.1.3/bin/xlC"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leftover from testing I presume?

args = [
"-B", "$buildDir/testlib-build",
"-S", "$projectDir/test/test-support",
Expand All @@ -203,6 +212,7 @@ task cmakeConfigure(type: Exec) {
]
}


task cmakeBuild(type: Exec) {
dependsOn cmakeConfigure

Expand Down Expand Up @@ -238,7 +248,7 @@ void createJtregTask(String name, String jacocoAgent, String os_lib_dir) {
"-javacoption:--add-exports=org.openjdk.jextract/org.openjdk.jextract.json.parser=ALL-UNNAMED",
"-javaoption:--add-exports=org.openjdk.jextract/org.openjdk.jextract.json.parser=ALL-UNNAMED",
"-avm", "-conc:auto", "-verbose:summary,fail,error",
"-retain:fail,error",
"-retain:fail,error"
]

if (jacocoAgent != null) {
Expand All @@ -258,6 +268,24 @@ if (jacocoAgent != null) {
createJtregTask("jtregWithCoverage", jacocoAgent, os_lib_dir)
}


tasks.register("copyLibClangToTestLib", Copy) {
def srcFile = file("${project.buildDir}/jmod_inputs/libs/libclang.a")
def destDir = file("${project.buildDir}/test-lib/libs")
dependsOn(copyLibClang)
from(srcFile)
into(destDir)

doLast {
println "[DEBUG] Successfully copied libclang.a to test-lib/libs"
}
}

// Make jtreg depend on it
tasks.named("jtreg") {
dependsOn("copyLibClangToTestLib")
}

tasks.register("coverage", JavaExec) {
dependsOn jtregWithCoverage

Expand Down
7 changes: 6 additions & 1 deletion make/Build.gmk
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ endif

ifeq ($(PLATFORM_OS), macosx)
TAR_SUPPORTS_TRANSFORM := false
else ifeq ($(PLATFORM_OS), aix)
TAR_SUPPORTS_TRANSFORM := false
else
TAR_SUPPORTS_TRANSFORM := true
endif
Expand All @@ -29,6 +31,8 @@ JEXTRACT_JMOD_CONF_DIR := $(BUILD_DIR)/jextract_jmod_conf

ifeq ($(PLATFORM_OS), macosx)
BUNDLE_PLATFORM := macos-$(PLATFORM_CPU)
else ifeq ($(PLATFORM_OS), aix)
BUNDLE_PLATFORM := aix-$(PLATFORM_CPU)
else
BUNDLE_PLATFORM := $(PLATFORM)
endif
Expand All @@ -55,6 +59,8 @@ $(BUILD_CLASSES_DIR):

ifeq ($(PLATFORM_OS), linux)
LIBCLANG_COPY_PATH := "libclang.so.$(LIBCLANG_VERSION)"
else ifeq ($(PLATFORM_OS), aix)
LIBCLANG_COPY_PATH := "libclang.a"
else
LIBCLANG_COPY_PATH := "*clang.*"
endif
Expand All @@ -70,7 +76,6 @@ $(BUILD_MODULES_DIR): $(BUILD_CLASSES_DIR)
$(CP) "$(LIBCLANG_INCLUDE_DIR)/"*.h "$(JEXTRACT_JMOD_CONF_DIR)/jextract/"
[ ! -f $(JEXTRACT_JMOD_LIBS_DIR)/libclang.so.$(LIBCLANG_VERSION) ] || \
$(MV) "$(JEXTRACT_JMOD_LIBS_DIR)/libclang.so.$(LIBCLANG_VERSION)" "$(JEXTRACT_JMOD_LIBS_DIR)/libclang.so"

# create jextract jmod file
$(FIXPATH) $(PANAMA_JAVA_HOME)/bin/jmod \
create \
Expand Down
60 changes: 37 additions & 23 deletions make/Common.gmk
Original file line number Diff line number Diff line change
Expand Up @@ -68,39 +68,53 @@ endef

X :=
SPACE:=$(X) $(X)

UNAME_P := $(shell uname -p)
UNAME_M := $(shell uname -m)

# CPU detection
ifeq ($(UNAME_M),x86_64)
DEVKIT_VS_CPU_VAR_NAME := x86_64
PLATFORM_CPU := x64
else ifeq ($(UNAME_M),arm64)
DEVKIT_VS_CPU_VAR_NAME := aarch64
PLATFORM_CPU := aarch64
else ifeq ($(UNAME_M),aarch64)
DEVKIT_VS_CPU_VAR_NAME := aarch64
PLATFORM_CPU := aarch64
DEVKIT_VS_CPU_VAR_NAME := x86_64
PLATFORM_CPU := x64
else
$(error "Unknown CPU: $(UNAME_M)")
ifeq ($(UNAME_M),arm64)
DEVKIT_VS_CPU_VAR_NAME := aarch64
PLATFORM_CPU := aarch64
else
ifeq ($(UNAME_M),aarch64)
DEVKIT_VS_CPU_VAR_NAME := aarch64
PLATFORM_CPU := aarch64
else
ifeq ($(UNAME_P),powerpc)
DEVKIT_VS_CPU_VAR_NAME := ppc64
PLATFORM_CPU := ppc64
else
$(error "Unknown CPU: $(UNAME_M)")
endif
endif
endif
endif
Comment on lines 75 to 95
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please undo the format changes.


# OS detection
ifeq ($(OS),Windows_NT)
PLATFORM_OS := windows
FIXPATH := bash $(TOPDIR)/make/scripts/fixpath.sh exec
PLATFORM_OS := windows
FIXPATH := bash $(TOPDIR)/make/scripts/fixpath.sh exec
else
FIXPATH :=

UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S), Darwin)
PLATFORM_OS := macosx
else
ifeq ($(UNAME_S), Linux)
PLATFORM_OS := linux
FIXPATH :=
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Darwin)
PLATFORM_OS := macosx
else
$(error "Unknown OS: $(UNAME_S)")
ifeq ($(UNAME_S),Linux)
PLATFORM_OS := linux
else
ifeq ($(UNAME_S),AIX)
PLATFORM_OS := aix
else
$(error "Unknown OS: $(UNAME_S)")
endif
endif
endif
endif
endif

PLATFORM := $(PLATFORM_OS)-$(PLATFORM_CPU)

ECHO := echo
Expand Down
13 changes: 13 additions & 0 deletions make/NativeCompilation.gmk
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,19 @@ else
CFLAGS += --sysroot=$(SYSROOT)
endif
endif
ifeq ($(PLATFORM_OS), aix)
SHARED_LIB_SUFFIX := .a
CC_NAME := xlc
LINK_NAME := xlc

# xlc typically requires -q64 for 64-bit builds
CFLAGS += -q64 -bexpall -qhalt=e -qalign=power -sysroot=$(SYSROOT) -m64
LDFLAGS += -q64 -G -Wl,-bnoentry -Wl,-bexpall, -malign-power -m64
CPPFLAGS += -D_AIX

# AIX-specific export file handling can be added here if needed
endif

endif

CC := $(call FindTool,$(CC_NAME),$(TOOL_SEARCH_PATH))
Expand Down
34 changes: 27 additions & 7 deletions src/main/java/org/openjdk/jextract/clang/libclang/Index_h.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,10 @@
import java.util.*;
import java.util.function.*;
import java.util.stream.*;

import static java.lang.foreign.ValueLayout.*;
import java.util.StringTokenizer;
import static java.lang.foreign.MemoryLayout.PathElement.*;
import java.io.File;

public class Index_h {

Expand Down Expand Up @@ -80,15 +81,34 @@ static MemoryLayout align(MemoryLayout layout, long align) {
};
}

static SymbolLookup SYMBOL_LOOKUP;

static {
String libName = System.getProperty("os.name").startsWith("Windows") ? "libclang" : "clang";
System.loadLibrary(libName);
String osName = System.getProperty("os.name");
String libName = "";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This variable doesn't look like it needs to be hoisted.

if (osName.startsWith("AIX")) {
List<String> pathsToCheck = new ArrayList<>(Arrays.asList(
System.getProperty("java.library.path").split(File.pathSeparator)
));
// 2. Add alternate calculated paths
String currentDir = System.getProperty("user.dir"); // wherever JVM was launched
pathsToCheck.add(currentDir + "/build/jextract-jdk-test-image/lib");
pathsToCheck.add(currentDir + "/../../../jextract-jdk-test-image/lib"); // in case running from subdir
// 3. Try to find the library
for (String path : pathsToCheck) {
File f = new File(path, "libclang.a"); // AIX uses .a, Linux .so
if (f.exists() && !f.isDirectory()) {
libName = f.getAbsolutePath();
break;
}
}
SYMBOL_LOOKUP = SymbolLookup.libraryLookup(libName + "(libclang.so.14)", Arena.global());
Comment on lines +90 to +105
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pleas fix the indentation here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, hard-coding paths the the build directories in the production code seems fishy. It also shouldn't be needed. If the library is properly included in the runtime image, that's where it can be found, and I'm expecting the call to libraryLookup to succeed.

If it doesn't then there's something wrong with the runtime image. You might want to test grabbing the .jmod file from the build, and creating another runtime image with it, and then trying to access some of the jextract API classes in e.g. a jshell session, to see if the library can be loaded.

} else {
libName = osName.startsWith("Windows") ? "libclang" : "clang";
System.loadLibrary(libName);
SYMBOL_LOOKUP = SymbolLookup.loaderLookup().or(Linker.nativeLinker().defaultLookup());
}
}

static final SymbolLookup SYMBOL_LOOKUP = SymbolLookup.loaderLookup()
.or(Linker.nativeLinker().defaultLookup());

public static final ValueLayout.OfBoolean C_BOOL = ValueLayout.JAVA_BOOLEAN;
public static final ValueLayout.OfByte C_CHAR = ValueLayout.JAVA_BYTE;
public static final ValueLayout.OfShort C_SHORT = ValueLayout.JAVA_SHORT;
Expand Down
16 changes: 14 additions & 2 deletions test/test-support/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ cmake_minimum_required(VERSION 3.14)
project(TestSupportLibs)

option(TEST_SOURCE_ROOT "src directory with test files")

file(GLOB_RECURSE TEST_LIBS ${TEST_SOURCE_ROOT}/*lib*.c)

foreach(TEST_LIB ${TEST_LIBS})
Expand All @@ -11,13 +10,26 @@ foreach(TEST_LIB ${TEST_LIBS})
string(REGEX REPLACE ".*lib([A-Za-z0-9_]+)\.c(pp)?" "\\1" LIB_NAME ${TEST_LIB})
string(REGEX REPLACE "(.*)/lib[A-Za-z0-9_]+\.c(pp)?" "\\1" PARENT_DIR ${TEST_LIB})
message(STATUS "Lib name: ${LIB_NAME}")
if(${CMAKE_SYSTEM_NAME} MATCHES "AIX")
add_library(${LIB_NAME} SHARED ${TEST_LIB})
set_target_properties(${LIB_NAME} PROPERTIES
PREFIX "lib"
SUFFIX ".a"
COMPILE_FLAGS "-q64 -qhalt=e"
LINK_FLAGS "-q64 -G -Wl,-bnoentry,-bexpall"
)
else()
add_library(${LIB_NAME} SHARED ${TEST_LIB})
endif()

add_library(${LIB_NAME} SHARED ${TEST_LIB})
target_include_directories(${LIB_NAME}
PRIVATE
${PARENT_DIR}
)

# Link against libm to resolve sqrt() and other math symbols
target_link_libraries(${LIB_NAME} m)

Comment on lines +30 to +32
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not work on Windows:

LINK : fatal error LNK1181: cannot open input file 'm.lib'

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe you could use something like:

Suggested change
# Link against libm to resolve sqrt() and other math symbols
target_link_libraries(${LIB_NAME} m)
# Link against libm to resolve sqrt() and other math symbols
find_library(LIBM, m)
if(LIBM)
target_link_libraries(${LIB_NAME} ${LIBM})
endif()

install(
TARGETS
${LIB_NAME}
Expand Down