From eff969202d592d4b8d30b76d8d9fc24262569dd5 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Fri, 10 Jul 2026 13:36:38 +0200 Subject: [PATCH 1/3] Add src_gen folders to generated pom.xml files --- .../pom.xml | 24 +++++++++ .../pom.xml | 24 +++++++++ .../com.oracle.graal.python.pegparser/pom.xml | 24 +++++++++ .../com.oracle.graal.python.processor/pom.xml | 24 +++++++++ .../com.oracle.graal.python.resources/pom.xml | 24 +++++++++ .../com.oracle.graal.python.shell/pom.xml | 24 +++++++++ graalpython/com.oracle.graal.python/pom.xml | 20 +++++++ mx.graalpython/mx_pominit.py | 52 ++++++++++++++++--- pom.xml | 6 +++ 9 files changed, 216 insertions(+), 6 deletions(-) diff --git a/graalpython/com.oracle.graal.python.annotations/pom.xml b/graalpython/com.oracle.graal.python.annotations/pom.xml index 09392ac931..c8aa8af9e0 100644 --- a/graalpython/com.oracle.graal.python.annotations/pom.xml +++ b/graalpython/com.oracle.graal.python.annotations/pom.xml @@ -53,4 +53,28 @@ SOFTWARE. com.oracle.graal.python.annotations jar + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add-mx-generated-sources + generate-sources + + add-source + + + + ../../mxbuild/graalpython/com.oracle.graal.python.annotations/src_gen + + + + + + + diff --git a/graalpython/com.oracle.graal.python.bouncycastle/pom.xml b/graalpython/com.oracle.graal.python.bouncycastle/pom.xml index 5db5641801..3ae5fa6978 100644 --- a/graalpython/com.oracle.graal.python.bouncycastle/pom.xml +++ b/graalpython/com.oracle.graal.python.bouncycastle/pom.xml @@ -76,4 +76,28 @@ SOFTWARE. bcutil-jdk18on + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add-mx-generated-sources + generate-sources + + add-source + + + + ../../mxbuild/graalpython/com.oracle.graal.python.bouncycastle/src_gen + + + + + + + diff --git a/graalpython/com.oracle.graal.python.pegparser/pom.xml b/graalpython/com.oracle.graal.python.pegparser/pom.xml index a6dbf87d88..018c72982d 100644 --- a/graalpython/com.oracle.graal.python.pegparser/pom.xml +++ b/graalpython/com.oracle.graal.python.pegparser/pom.xml @@ -60,4 +60,28 @@ SOFTWARE. icu4j + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add-mx-generated-sources + generate-sources + + add-source + + + + ../../mxbuild/graalpython/com.oracle.graal.python.pegparser/src_gen + + + + + + + diff --git a/graalpython/com.oracle.graal.python.processor/pom.xml b/graalpython/com.oracle.graal.python.processor/pom.xml index 061e5e11bd..9712c166b7 100644 --- a/graalpython/com.oracle.graal.python.processor/pom.xml +++ b/graalpython/com.oracle.graal.python.processor/pom.xml @@ -60,4 +60,28 @@ SOFTWARE. com.oracle.graal.python.annotations + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add-mx-generated-sources + generate-sources + + add-source + + + + ../../mxbuild/graalpython/com.oracle.graal.python.processor/src_gen + + + + + + + diff --git a/graalpython/com.oracle.graal.python.resources/pom.xml b/graalpython/com.oracle.graal.python.resources/pom.xml index ce411c3713..08e461967f 100644 --- a/graalpython/com.oracle.graal.python.resources/pom.xml +++ b/graalpython/com.oracle.graal.python.resources/pom.xml @@ -66,4 +66,28 @@ SOFTWARE. true + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add-mx-generated-sources + generate-sources + + add-source + + + + ../../mxbuild/graalpython/com.oracle.graal.python.resources/src_gen + + + + + + + diff --git a/graalpython/com.oracle.graal.python.shell/pom.xml b/graalpython/com.oracle.graal.python.shell/pom.xml index c086fee5f2..2482b656a6 100644 --- a/graalpython/com.oracle.graal.python.shell/pom.xml +++ b/graalpython/com.oracle.graal.python.shell/pom.xml @@ -72,4 +72,28 @@ SOFTWARE. maven-downloader + + + + + + org.codehaus.mojo + build-helper-maven-plugin + + + add-mx-generated-sources + generate-sources + + add-source + + + + ../../mxbuild/graalpython/com.oracle.graal.python.shell/src_gen + + + + + + + diff --git a/graalpython/com.oracle.graal.python/pom.xml b/graalpython/com.oracle.graal.python/pom.xml index fd0f6790ba..4b3598c2b3 100644 --- a/graalpython/com.oracle.graal.python/pom.xml +++ b/graalpython/com.oracle.graal.python/pom.xml @@ -103,6 +103,26 @@ SOFTWARE. + + + org.codehaus.mojo + build-helper-maven-plugin + + + add-mx-generated-sources + generate-sources + + add-source + + + + ../../mxbuild/graalpython/com.oracle.graal.python/src_gen + + + + + + org.apache.maven.plugins maven-compiler-plugin diff --git a/mx.graalpython/mx_pominit.py b/mx.graalpython/mx_pominit.py index 30270bd52d..516397da88 100644 --- a/mx.graalpython/mx_pominit.py +++ b/mx.graalpython/mx_pominit.py @@ -228,6 +228,12 @@ def common_source_dir(projects: dict) -> str: return source_dir[0] +def additional_source_dirs(project) -> list[str]: + if not hasattr(project, "source_gen_dir"): + return [] + return [project.source_gen_dir(relative=True)] + + def expand_processor(processor: str) -> list[str]: return ANNOTATION_PROCESSOR_ALIASES.get(processor, [processor]) @@ -329,6 +335,7 @@ def root_pom(suite: dict, projects: dict, graalvm_version: str) -> str: {java_version} true 3.14.1 + 3.6.1 3.6.1 {graalvm_version} @@ -360,6 +367,11 @@ def root_pom(suite: dict, projects: dict, graalvm_version: str) -> str: ${{maven.compiler.target}} + + org.codehaus.mojo + build-helper-maven-plugin + ${{build-helper-maven-plugin.version}} + org.apache.maven.plugins maven-enforcer-plugin @@ -389,6 +401,7 @@ def root_pom(suite: dict, projects: dict, graalvm_version: str) -> str: def leaf_pom(project_name: str, project, suite: dict) -> str: deps = project_dependencies(project, suite) + extra_source_dirs = additional_source_dirs(project) deps_xml = "" if deps: dep_entries = "\n".join(dependency_xml(dep, indent=" ") for dep in deps) @@ -398,12 +411,30 @@ def leaf_pom(project_name: str, project, suite: dict) -> str: {dep_entries} ''' - build_xml = "" + plugins = [] + if extra_source_dirs: + sources_xml = "\n".join(f" {source_dir}" for source_dir in extra_source_dirs) + plugins.append(f''' + + org.codehaus.mojo + build-helper-maven-plugin + + + add-mx-generated-sources + generate-sources + + add-source + + + +{sources_xml} + + + + + ''') if getattr(project, "jniHeaders", None): - build_xml = ''' - - - + plugins.append(''' org.apache.maven.plugins maven-compiler-plugin @@ -415,7 +446,16 @@ def leaf_pom(project_name: str, project, suite: dict) -> str: ${project.build.directory}/jni_gen - + ''') + + build_xml = "" + if plugins: + plugins_xml = "\n".join(plugins) + build_xml = f''' + + + +{plugins_xml} ''' diff --git a/pom.xml b/pom.xml index 7a41ea2c56..a927d6a203 100644 --- a/pom.xml +++ b/pom.xml @@ -65,6 +65,7 @@ SOFTWARE. 17 true 3.14.1 + 3.6.1 3.6.1 25.1.3 @@ -200,6 +201,11 @@ SOFTWARE. ${maven.compiler.target} + + org.codehaus.mojo + build-helper-maven-plugin + ${build-helper-maven-plugin.version} + org.apache.maven.plugins maven-enforcer-plugin From 1bc5dc71bebf851794becbfef0001e54aa5f3254 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Mon, 13 Jul 2026 15:40:14 +0200 Subject: [PATCH 2/3] Read platform-specific soext&multiarch from platform-specific resource --- .../com.oracle.graal.python.resources/pom.xml | 8 ++ ...ntime.platform.GraalPyPlatformInfoProvider | 1 + .../GraalPyPlatformInfoProviderImpl.java | 100 ++++++++++++++++++ .../python/resources/PythonResource.java | 46 ++------ .../oracle/graal/python/PythonLanguage.java | 36 +++++-- .../builtins/modules/SysModuleBuiltins.java | 2 +- .../graal/python/runtime/PythonContext.java | 8 +- .../platform/GraalPyPlatformInfoProvider.java | 67 ++++++++++++ graalpython/graalpy-versions/CMakeLists.txt | 5 +- mx.graalpython/suite.py | 17 ++- pom.xml | 20 ++-- 11 files changed, 241 insertions(+), 69 deletions(-) create mode 100644 graalpython/com.oracle.graal.python.resources/src/META-INF/services/com.oracle.graal.python.runtime.platform.GraalPyPlatformInfoProvider create mode 100644 graalpython/com.oracle.graal.python.resources/src/com/oracle/graal/python/resources/GraalPyPlatformInfoProviderImpl.java create mode 100644 graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/platform/GraalPyPlatformInfoProvider.java diff --git a/graalpython/com.oracle.graal.python.resources/pom.xml b/graalpython/com.oracle.graal.python.resources/pom.xml index 08e461967f..fd91192705 100644 --- a/graalpython/com.oracle.graal.python.resources/pom.xml +++ b/graalpython/com.oracle.graal.python.resources/pom.xml @@ -55,6 +55,14 @@ SOFTWARE. jar + + ${project.groupId} + com.oracle.graal.python + + + org.graalvm.sdk + nativeimage + org.graalvm.truffle truffle-api diff --git a/graalpython/com.oracle.graal.python.resources/src/META-INF/services/com.oracle.graal.python.runtime.platform.GraalPyPlatformInfoProvider b/graalpython/com.oracle.graal.python.resources/src/META-INF/services/com.oracle.graal.python.runtime.platform.GraalPyPlatformInfoProvider new file mode 100644 index 0000000000..4e1d06192e --- /dev/null +++ b/graalpython/com.oracle.graal.python.resources/src/META-INF/services/com.oracle.graal.python.runtime.platform.GraalPyPlatformInfoProvider @@ -0,0 +1 @@ +com.oracle.graal.python.resources.GraalPyPlatformInfoProviderImpl diff --git a/graalpython/com.oracle.graal.python.resources/src/com/oracle/graal/python/resources/GraalPyPlatformInfoProviderImpl.java b/graalpython/com.oracle.graal.python.resources/src/com/oracle/graal/python/resources/GraalPyPlatformInfoProviderImpl.java new file mode 100644 index 0000000000..1805b8e644 --- /dev/null +++ b/graalpython/com.oracle.graal.python.resources/src/com/oracle/graal/python/resources/GraalPyPlatformInfoProviderImpl.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.oracle.graal.python.resources; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.StandardCharsets; +import java.util.List; + +import com.oracle.graal.python.runtime.platform.GraalPyPlatformInfoProvider; +import com.oracle.truffle.api.InternalResource.CPUArchitecture; +import com.oracle.truffle.api.InternalResource.OS; + +public final class GraalPyPlatformInfoProviderImpl implements GraalPyPlatformInfoProvider { + /** + * The version generated at build time is stored in an ASCII-compatible way. At build time, we + * added the ordinal value of some base character (in this case {@code '!'}) to ensure that we + * have a printable character. + */ + private static final int VERSION_BASE = '!'; + + private static final class VersionsInfoHolder { + private static final VersionsInfo INFO = readVersionsInfo(OS.getCurrent(), CPUArchitecture.getCurrent()); + } + + @Override + public PlatformInfo getPlatformInfo() { + return getVersionsInfo().platformInfo(); + } + + static VersionsInfo getVersionsInfo() { + return VersionsInfoHolder.INFO; + } + + static VersionsInfo readVersionsInfo(OS os, CPUArchitecture cpuArchitecture) { + String resource = "/META-INF/resources/" + os + "/" + cpuArchitecture + "/graalpy_versions"; + try (InputStream stream = GraalPyPlatformInfoProviderImpl.class.getResourceAsStream(resource)) { + if (stream == null) { + throw new IllegalStateException("Missing GraalPy platform metadata resource: " + resource); + } + List lines = new BufferedReader(new InputStreamReader(stream, StandardCharsets.US_ASCII)).lines().toList(); + if (lines.size() < 4 || lines.get(0).length() < 7) { + throw new IllegalStateException("Malformed GraalPy platform metadata resource: " + resource); + } + String versions = lines.get(0); + return new VersionsInfo( + versions.charAt(0) - VERSION_BASE, + versions.charAt(1) - VERSION_BASE, + versions.charAt(3) - VERSION_BASE, + versions.charAt(4) - VERSION_BASE, + lines.get(1).strip(), + new PlatformInfo(lines.get(2).strip(), lines.get(3).strip())); + } catch (IOException e) { + throw new IllegalStateException("Cannot read GraalPy platform metadata resource: " + resource, e); + } + } + + record VersionsInfo(int pythonMajor, int pythonMinor, int graalVMajor, int graalVMinor, String pythonAbiFlags, PlatformInfo platformInfo) { + } +} diff --git a/graalpython/com.oracle.graal.python.resources/src/com/oracle/graal/python/resources/PythonResource.java b/graalpython/com.oracle.graal.python.resources/src/com/oracle/graal/python/resources/PythonResource.java index cb769e9925..8d14da26c3 100644 --- a/graalpython/com.oracle.graal.python.resources/src/com/oracle/graal/python/resources/PythonResource.java +++ b/graalpython/com.oracle.graal.python.resources/src/com/oracle/graal/python/resources/PythonResource.java @@ -42,8 +42,6 @@ import java.io.File; import java.io.IOException; -import java.io.InputStream; -import java.nio.charset.StandardCharsets; import java.nio.file.InvalidPathException; import java.nio.file.Path; import java.util.ArrayList; @@ -63,40 +61,6 @@ */ @InternalResource.Id(value = "python-home", componentId = "python", optional = true) public final class PythonResource implements InternalResource { - private static final int PYTHON_MAJOR; - private static final int PYTHON_MINOR; - private static final int GRAALVM_MAJOR; - private static final int GRAALVM_MINOR; - private static final String PYTHON_ABIFLAGS; - - /** - * The version generated at build time is stored in an ASCII-compatible way. Add build time, we - * added the ordinal value of some base character (in this case {@code '!'}) to ensure that we - * have a printable character. - */ - private static final int VERSION_BASE = '!'; - - static { - // See static ctor of PythonLanguage - try (InputStream is = PythonResource.class.getResourceAsStream("/graalpy_versions")) { - PYTHON_MAJOR = is.read() - VERSION_BASE; - PYTHON_MINOR = is.read() - VERSION_BASE; - is.read(); // skip python micro version - GRAALVM_MAJOR = is.read() - VERSION_BASE; - GRAALVM_MINOR = is.read() - VERSION_BASE; - is.read(); // skip GraalVM micro version - is.read(); // skip release level - int ch; - while ((ch = is.read()) != '\n' && ch != -1) { - // skip ABI version - } - String[] abiParts = ch == -1 ? new String[0] : new String(is.readAllBytes(), StandardCharsets.US_ASCII).split("\\R", 4); - PYTHON_ABIFLAGS = abiParts.length > 0 ? abiParts[0].strip() : ""; - } catch (IOException e) { - throw new RuntimeException(e); - } - } - private static final Path BASE_PATH = Path.of("META-INF", "resources"); private static final String LIBGRAALPY = "libgraalpy"; private static final String LIBPYTHON = "libpython"; @@ -110,6 +74,7 @@ public final class PythonResource implements InternalResource { private static final Path LIBPYTHON_SHA256 = Path.of(LIBPYTHON + ".sha256"); private static final Path INCLUDE_SHA256 = Path.of("include.sha256"); private static final Path NI_SHA256 = Path.of("ni.sha256"); + private static final Path VERSIONS_SHA256 = Path.of("versions.sha256"); private static final Path NATIVE_SHA256 = Path.of("native.sha256"); @Override @@ -117,17 +82,19 @@ public void unpackFiles(Env env, Path targetDirectory) throws IOException { OS os = env.getOS(); CPUArchitecture cpuArchitecture = env.getCPUArchitecture(); Path osArch = Path.of(os.toString()).resolve(cpuArchitecture.toString()); + GraalPyPlatformInfoProviderImpl.VersionsInfo versionsInfo = GraalPyPlatformInfoProviderImpl.getVersionsInfo(); ResourcesFilter filter = new ResourcesFilter(); if (os.equals(OS.WINDOWS)) { env.unpackResourceFiles(BASE_PATH.resolve(LIBPYTHON_FILES), targetDirectory.resolve("Lib"), BASE_PATH.resolve(LIBPYTHON), filter); env.unpackResourceFiles(BASE_PATH.resolve(LIBGRAALPY_FILES), targetDirectory.resolve("lib-graalpython"), BASE_PATH.resolve(LIBGRAALPY), filter); env.unpackResourceFiles(BASE_PATH.resolve(INCLUDE_FILES), targetDirectory.resolve("Include"), BASE_PATH.resolve(INCLUDE), filter); } else { - String pythonMajMin = "python" + PYTHON_MAJOR + "." + PYTHON_MINOR; + String pythonMajMin = "python" + versionsInfo.pythonMajor() + "." + versionsInfo.pythonMinor(); env.unpackResourceFiles(BASE_PATH.resolve(LIBPYTHON_FILES), targetDirectory.resolve("lib").resolve(pythonMajMin), BASE_PATH.resolve(LIBPYTHON), filter); - env.unpackResourceFiles(BASE_PATH.resolve(LIBGRAALPY_FILES), targetDirectory.resolve("lib").resolve("graalpy" + GRAALVM_MAJOR + "." + GRAALVM_MINOR), BASE_PATH.resolve(LIBGRAALPY), + env.unpackResourceFiles(BASE_PATH.resolve(LIBGRAALPY_FILES), + targetDirectory.resolve("lib").resolve("graalpy" + versionsInfo.graalVMajor() + "." + versionsInfo.graalVMinor()), BASE_PATH.resolve(LIBGRAALPY), filter); - env.unpackResourceFiles(BASE_PATH.resolve(INCLUDE_FILES), targetDirectory.resolve("include").resolve(pythonMajMin + PYTHON_ABIFLAGS), BASE_PATH.resolve(INCLUDE), filter); + env.unpackResourceFiles(BASE_PATH.resolve(INCLUDE_FILES), targetDirectory.resolve("include").resolve(pythonMajMin + versionsInfo.pythonAbiFlags()), BASE_PATH.resolve(INCLUDE), filter); } // ni files are in the same place on all platforms env.unpackResourceFiles(BASE_PATH.resolve(NI_FILES), targetDirectory, BASE_PATH, filter); @@ -242,6 +209,7 @@ public String versionHash(Env env) { CPUArchitecture cpuArchitecture = env.getCPUArchitecture(); if (!os.equals(OS.UNSUPPORTED) && !cpuArchitecture.equals(CPUArchitecture.UNSUPPORTED)) { al = new ArrayList<>(al); + al.add(Path.of(os.toString()).resolve(cpuArchitecture.toString()).resolve(VERSIONS_SHA256)); al.add(Path.of(os.toString()).resolve(cpuArchitecture.toString()).resolve(NATIVE_SHA256)); } for (var s : al) { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java index 929e713df5..947138e0be 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java @@ -43,6 +43,7 @@ import java.util.EnumSet; import java.util.List; import java.util.Map; +import java.util.ServiceLoader; import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; @@ -105,6 +106,8 @@ import com.oracle.graal.python.runtime.PythonSourceOptions; import com.oracle.graal.python.runtime.exception.PException; import com.oracle.graal.python.runtime.object.PFactory; +import com.oracle.graal.python.runtime.platform.GraalPyPlatformInfoProvider; +import com.oracle.graal.python.runtime.platform.GraalPyPlatformInfoProvider.PlatformInfo; import com.oracle.graal.python.util.Function; import com.oracle.graal.python.util.PythonUtils; import com.oracle.graal.python.util.Supplier; @@ -197,9 +200,8 @@ public final class PythonLanguage extends TruffleLanguage { /** See {@code mx_graalpython.py:abi_version} */ public static final String GRAALPY_ABI_VERSION; public static final String GRAALPY_ABIFLAGS; - public static final String GRAALPY_SOABI; - public static final String GRAALPY_EXT_SUFFIX; - public static final String GRAALPY_MULTIARCH; + private static final String BUILD_PLATFORM_GRAALPY_EXT_SUFFIX; + private static final String BUILD_PLATFORM_GRAALPY_MULTIARCH; /* Magic number used to mark pyc files */ public static final int MAGIC_NUMBER = 21000 + BytecodeDSLCompiler.BYTECODE_VERSION * 10; @@ -252,13 +254,34 @@ public final class PythonLanguage extends TruffleLanguage { String[] abiParts = new String(is.readAllBytes(), StandardCharsets.US_ASCII).split("\\R", 5); GRAALPY_ABI_VERSION = abiParts[0].strip(); GRAALPY_ABIFLAGS = abiParts.length > 1 ? abiParts[1].strip() : ""; - GRAALPY_SOABI = abiParts.length > 2 ? abiParts[2].strip() : ""; - GRAALPY_EXT_SUFFIX = abiParts.length > 3 ? abiParts[3].strip() : ""; - GRAALPY_MULTIARCH = abiParts.length > 4 ? abiParts[4].strip() : ""; + BUILD_PLATFORM_GRAALPY_EXT_SUFFIX = abiParts.length > 2 ? abiParts[2].strip() : ""; + BUILD_PLATFORM_GRAALPY_MULTIARCH = abiParts.length > 3 ? abiParts[3].strip() : ""; } catch (IOException e) { throw new RuntimeException(e); } + if (ImageInfo.inImageBuildtimeCode()) { + PLATFORM_INFO = getPlatformInfo(); + } } + + private static PlatformInfo PLATFORM_INFO; + + @TruffleBoundary + public static PlatformInfo getPlatformInfo() { + if (PLATFORM_INFO == null) { + if (ImageInfo.inImageRuntimeCode()) { + throw new IllegalStateException("GraalPy platform metadata must be initialized while building a native image"); + } + ModuleLayer layer = PythonLanguage.class.getModule().getLayer(); + ServiceLoader providers = layer != null + ? ServiceLoader.load(layer, GraalPyPlatformInfoProvider.class) + : ServiceLoader.load(GraalPyPlatformInfoProvider.class, PythonLanguage.class.getClassLoader()); + PLATFORM_INFO = providers.findFirst().map(GraalPyPlatformInfoProvider::getPlatformInfo).orElseGet( + () -> new PlatformInfo(BUILD_PLATFORM_GRAALPY_EXT_SUFFIX, BUILD_PLATFORM_GRAALPY_MULTIARCH)); + } + return PLATFORM_INFO; + } + public static final int RELEASE_SERIAL = 0; public static final int VERSION_HEX = MAJOR << 24 | MINOR << 16 | @@ -427,6 +450,7 @@ protected boolean patchContext(PythonContext context, Env newEnv) { @Override protected PythonContext createContext(Env env) { + getPlatformInfo(); final PythonContext context = new PythonContext(this, env); Object[] engineOptionsUnroll = this.engineOptionsStorage; diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SysModuleBuiltins.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SysModuleBuiltins.java index 95ede68a5e..64ddbec4c2 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SysModuleBuiltins.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SysModuleBuiltins.java @@ -562,7 +562,7 @@ public void initialize(Python3Core core) { if (os == PLATFORM_DARWIN) { addBuiltinConstant("_framework", FRAMEWORK); } - final TruffleString gmultiarch = toTruffleStringUncached(PythonLanguage.GRAALPY_MULTIARCH); + final TruffleString gmultiarch = PythonLanguage.getPlatformInfo().multiarch(); addBuiltinConstant("__gmultiarch", gmultiarch); // Initialized later in postInitialize diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java index 5e017690b3..805db631f1 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java @@ -784,8 +784,6 @@ public enum CApiState { @CompilationFinal private boolean nativeAccessAllowed; @CompilationFinal private NativeContext nativeContext; - private TruffleString extensionSuffix; - private static final class GlobalInterpreterLock extends ReentrantLock { private static final long serialVersionUID = 1L; @@ -2508,12 +2506,8 @@ public boolean isFinalizing() { return finalizing; } - @TruffleBoundary public TruffleString getExtensionSuffix() { - if (extensionSuffix == null) { - extensionSuffix = toTruffleStringUncached(PythonLanguage.GRAALPY_EXT_SUFFIX); - } - return extensionSuffix; + return PythonLanguage.getPlatformInfo().extensionSuffix(); } public Thread getMainThread() { diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/platform/GraalPyPlatformInfoProvider.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/platform/GraalPyPlatformInfoProvider.java new file mode 100644 index 0000000000..10018ce433 --- /dev/null +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/platform/GraalPyPlatformInfoProvider.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package com.oracle.graal.python.runtime.platform; + +import static com.oracle.graal.python.util.PythonUtils.toTruffleStringUncached; + +import com.oracle.truffle.api.strings.TruffleString; + +public interface GraalPyPlatformInfoProvider { + public static final class PlatformInfo { + private final TruffleString extensionSuffix; + private final TruffleString multiarch; + + public PlatformInfo(String extensionSuffix, String multiarch) { + this.extensionSuffix = toTruffleStringUncached(extensionSuffix); + this.multiarch = toTruffleStringUncached(multiarch); + } + + public TruffleString extensionSuffix() { + return extensionSuffix; + } + + public TruffleString multiarch() { + return multiarch; + } + } + + PlatformInfo getPlatformInfo(); +} diff --git a/graalpython/graalpy-versions/CMakeLists.txt b/graalpython/graalpy-versions/CMakeLists.txt index 1664e2baad..f797f86164 100644 --- a/graalpython/graalpy-versions/CMakeLists.txt +++ b/graalpython/graalpy-versions/CMakeLists.txt @@ -41,11 +41,8 @@ endif() if (NOT DEFINED GRAALPY_MULTIARCH) message(FATAL_ERROR "GRAALPY_MULTIARCH needs to be set") endif() -if (NOT DEFINED GRAALPY_SOABI) - message(FATAL_ERROR "GRAALPY_SOABI needs to be set") -endif() # Generates file 'graalpy_versions' with the given content. # The file will be created if it does not exist and will only be updated if the # content changes. -file(GENERATE OUTPUT "graalpy_versions" CONTENT "${GRAALPY_VER}\n${GRAALPY_ABIFLAGS}\n${GRAALPY_SOABI}\n${GRAALPY_EXT_SUFFIX}\n${GRAALPY_MULTIARCH}\n") +file(GENERATE OUTPUT "graalpy_versions" CONTENT "${GRAALPY_VER}\n${GRAALPY_ABIFLAGS}\n${GRAALPY_EXT_SUFFIX}\n${GRAALPY_MULTIARCH}\n") diff --git a/mx.graalpython/suite.py b/mx.graalpython/suite.py index db2cf41f2c..8f091ab91a 100644 --- a/mx.graalpython/suite.py +++ b/mx.graalpython/suite.py @@ -363,6 +363,7 @@ "subDir": "graalpython", "sourceDirs": ["src"], "dependencies": [ + "GRAALPYTHON", "truffle:TRUFFLE_API", ], "jacoco": "include", @@ -658,7 +659,6 @@ "GRAALPY_ABIFLAGS": "", "GRAALPY_EXT_SUFFIX": "", "GRAALPY_MULTIARCH": "", - "GRAALPY_SOABI": "", }, "results": [ "graalpy_versions" @@ -994,10 +994,20 @@ # otherwise they will not get included in both the resources jar and # the language jar. "GRAALPYTHON_VERSIONS_RES": { + "platformDependent": True, + "hashEntry": "META-INF/resources///versions.sha256", + "fileListEntry": "META-INF/resources///versions.files", "type": "dir", "layout": { - "./": "dependency:graalpy-versions/-//graalpy_versions", + "./META-INF/resources///graalpy_versions": "dependency:graalpy-versions/-//graalpy_versions", }, + "platforms": [ + "linux-amd64", + "linux-aarch64", + "darwin-amd64", + "darwin-aarch64", + "windows-amd64", + ], }, "GRAALPYTHON_VERSIONS_MAIN": { "type": "dir", @@ -1090,6 +1100,7 @@ "GRAALPYTHON_NATIVE_RESOURCES", ], "distDependencies": [ + "GRAALPYTHON", "truffle:TRUFFLE_API", ], "requires": [ @@ -1143,10 +1154,12 @@ "exports": [ "com.oracle.graal.python.* to org.graalvm.py.enterprise", "com.oracle.graal.python.builtins.objects.ssl to graalpython.bouncycastle", + "com.oracle.graal.python.runtime.platform to org.graalvm.py.resources", "com.oracle.graal.python.runtime.crypto", ], "uses": [ "com.oracle.graal.python.runtime.crypto.BouncyCastleSupport", + "com.oracle.graal.python.runtime.platform.GraalPyPlatformInfoProvider", ], }, "useModulePath": True, diff --git a/pom.xml b/pom.xml index a927d6a203..f438c4e514 100644 --- a/pom.xml +++ b/pom.xml @@ -97,6 +97,16 @@ SOFTWARE. com.oracle.graal.python.resources ${project.version} + + ${project.groupId} + com.oracle.graal.python + ${project.version} + + + org.graalvm.sdk + nativeimage + ${graalvm.version} + org.graalvm.truffle truffle-api @@ -107,11 +117,6 @@ SOFTWARE. truffle-dsl-processor ${graalvm.version} - - ${project.groupId} - com.oracle.graal.python - ${project.version} - org.graalvm.tools profiler-tool @@ -157,11 +162,6 @@ SOFTWARE. com.oracle.graal.python.bouncycastle ${project.version} - - org.graalvm.sdk - nativeimage - ${graalvm.version} - org.bouncycastle bcprov-jdk18on From c40baaf4ca0e785d425bf6f9054c23d6ae5f2642 Mon Sep 17 00:00:00 2001 From: Tim Felgentreff Date: Fri, 17 Jul 2026 09:38:14 +0200 Subject: [PATCH 3/3] Add ENOTSUP manually --- .../graal/python/builtins/objects/exception/OSErrorEnum.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/exception/OSErrorEnum.java b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/exception/OSErrorEnum.java index 6849fd35ae..705032dc51 100644 --- a/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/exception/OSErrorEnum.java +++ b/graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/exception/OSErrorEnum.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2026, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -82,6 +82,8 @@ public enum OSErrorEnum { * Manually are changed EWOULDBLOCK and EDEADLOCK and move before appropriate errors with the * same number, because ErrnoModuleBuiltins and PosixModuleBuiltins built a dictionary from this * enum. + * + * Manually added ENOTSUP as alias of EOPNOTSUPP */ EPERM(1, tsLiteral("Operation not permitted")), ENOENT(2, tsLiteral("No such file or directory")), @@ -178,6 +180,7 @@ public enum OSErrorEnum { EPROTONOSUPPORT(platformSpecific(93, 43), tsLiteral("Protocol not supported")), ESOCKTNOSUPPORT(platformSpecific(94, 44), tsLiteral("Socket type not supported")), EOPNOTSUPP(platformSpecific(95, 102), tsLiteral("Operation not supported on transport endpoint")), + ENOTSUP(platformSpecific(95, 102), tsLiteral("Operation not supported")), EPFNOSUPPORT(platformSpecific(96, 46), tsLiteral("Protocol family not supported")), EAFNOSUPPORT(platformSpecific(97, 47), tsLiteral("Address family not supported by protocol")), EADDRINUSE(platformSpecific(98, 48), tsLiteral("Address already in use")),