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.annotationsjar
+
+
+
+
+
+ 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..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.truffletruffle-api
@@ -66,4 +74,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.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.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.pluginsmaven-compiler-plugin
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/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")),
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/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}true3.14.1
+ 3.6.13.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.pluginsmaven-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.pluginsmaven-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/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 7a41ea2c56..f438c4e514 100644
--- a/pom.xml
+++ b/pom.xml
@@ -65,6 +65,7 @@ SOFTWARE.
17true3.14.1
+ 3.6.13.6.125.1.3
@@ -96,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.truffletruffle-api
@@ -106,11 +117,6 @@ SOFTWARE.
truffle-dsl-processor${graalvm.version}
-
- ${project.groupId}
- com.oracle.graal.python
- ${project.version}
- org.graalvm.toolsprofiler-tool
@@ -156,11 +162,6 @@ SOFTWARE.
com.oracle.graal.python.bouncycastle${project.version}
-
- org.graalvm.sdk
- nativeimage
- ${graalvm.version}
- org.bouncycastlebcprov-jdk18on
@@ -200,6 +201,11 @@ SOFTWARE.
${maven.compiler.target}
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+ ${build-helper-maven-plugin.version}
+ org.apache.maven.pluginsmaven-enforcer-plugin