Skip to content

Commit 1dc9395

Browse files
committed
[GR-76680] Add test using a GraalOS Python standalone.
PullRequest: graalpython/4665
2 parents 79a9c4a + ffb50ba commit 1dc9395

19 files changed

Lines changed: 991 additions & 126 deletions

File tree

ci.jsonnet

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
(import "ci/python-gate.libsonnet") +
66
(import "ci/python-bench.libsonnet") +
77
{
8-
overlay: "40bd8048e1a6ba45494605955ffe748ae4db20be",
8+
overlay: "30def35dbfc43256d57ad3b9b981d92718728e2a",
99
specVersion: "8",
1010
// Until buildbot issues around CI tiers are resolved, we cannot use them
1111
// tierConfig: self.tierConfig,
@@ -30,6 +30,9 @@
3030
BISECT_EMAIL_FROM: "",
3131
npm_config_registry: "",
3232
RODINIA_DATASET_ZIP: "",
33+
GRAALPY_GRAALOS_TOOLCHAIN_URL: "",
34+
GRAALPY_GRAALOS_RUNTIME_URL: "",
35+
GRAALPY_GRAALOS_ARTIFACT_BASE_URL: "",
3336
BUILDBOT_COMMIT_SERVICE: "",
3437
INTERNET_ACCESS_ENV: {},
3538
},
@@ -330,6 +333,15 @@
330333
"tox-example": gpgate_ee + require(GPYEE_NATIVE_STANDALONE) + platform_spec(no_jobs) + platform_spec({
331334
"linux:amd64:jdk-latest" : tier3,
332335
}),
336+
"python-svm-graalos-standalone-build": gpgate_ee + internet_access_env + platform_spec(no_jobs) + platform_spec({
337+
"linux:amd64:jdk-latest": tier3 + $.ol8 + task_spec({
338+
environment +: {
339+
GRAALPY_GRAALOS_TOOLCHAIN_URL: $.overlay_imports.GRAALPY_GRAALOS_TOOLCHAIN_URL,
340+
GRAALPY_GRAALOS_RUNTIME_URL: $.overlay_imports.GRAALPY_GRAALOS_RUNTIME_URL,
341+
GRAALPY_GRAALOS_ARTIFACT_BASE_URL: $.overlay_imports.GRAALPY_GRAALOS_ARTIFACT_BASE_URL,
342+
},
343+
}),
344+
}),
333345
},
334346

335347
local need_pgo = task_spec({runAfter: ["python-pgo-profile-post_merge-linux-amd64-jdk-latest"]}),

graalpython/com.oracle.graal.python.resources/src/com/oracle/graal/python/resources/PythonResource.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,8 @@ public final class PythonResource implements InternalResource {
9090
while ((ch = is.read()) != '\n' && ch != -1) {
9191
// skip ABI version
9292
}
93-
PYTHON_ABIFLAGS = ch == -1 ? "" : new String(is.readAllBytes(), StandardCharsets.US_ASCII).strip();
93+
String[] abiParts = ch == -1 ? new String[0] : new String(is.readAllBytes(), StandardCharsets.US_ASCII).split("\\R", 4);
94+
PYTHON_ABIFLAGS = abiParts.length > 0 ? abiParts[0].strip() : "";
9495
} catch (IOException e) {
9596
throw new RuntimeException(e);
9697
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
2+
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3+
#
4+
# The Universal Permissive License (UPL), Version 1.0
5+
#
6+
# Subject to the condition set forth below, permission is hereby granted to any
7+
# person obtaining a copy of this software, associated documentation and/or
8+
# data (collectively the "Software"), free of charge and under any and all
9+
# copyright rights in the Software, and any and all patent rights owned or
10+
# freely licensable by each licensor hereunder covering either (i) the
11+
# unmodified Software as contributed to or provided by such licensor, or (ii)
12+
# the Larger Works (as defined below), to deal in both
13+
#
14+
# (a) the Software, and
15+
#
16+
# (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if
17+
# one is included with the Software each a "Larger Work" to which the Software
18+
# is contributed by such licensors),
19+
#
20+
# without restriction, including without limitation the rights to copy, create
21+
# derivative works of, display, perform, and distribute the Software and make,
22+
# use, sell, offer for sale, import, export, have made, and have sold the
23+
# Software and the Larger Work(s), and to sublicense the foregoing rights on
24+
# either these or other terms.
25+
#
26+
# This license is subject to the following condition:
27+
#
28+
# The above copyright notice and either this complete permission notice or at a
29+
# minimum a reference to the UPL must be included in all copies or substantial
30+
# portions of the Software.
31+
#
32+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
33+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
34+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
35+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
36+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
37+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38+
# SOFTWARE.
39+
40+
import sysconfig
41+
import unittest
42+
43+
44+
def test_graalos_sqlite3_native_extension_smoke():
45+
soabi = sysconfig.get_config_var("SOABI") or ""
46+
if "graalos" not in soabi:
47+
raise unittest.SkipTest(f"requires GraalOS SOABI, got {soabi!r}")
48+
49+
import _sqlite3
50+
import sqlite3
51+
52+
assert _sqlite3.sqlite_version
53+
conn = sqlite3.connect(":memory:")
54+
try:
55+
conn.execute("create table values_for_sum(value integer)")
56+
conn.executemany("insert into values_for_sum(value) values (?)", [(1,), (2,), (3,)])
57+
assert conn.execute("select sum(value) from values_for_sum").fetchone()[0] == 6
58+
finally:
59+
conn.close()

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/PythonLanguage.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,9 @@ public final class PythonLanguage extends TruffleLanguage<PythonContext> {
203203
/** See {@code mx_graalpython.py:abi_version} */
204204
public static final String GRAALPY_ABI_VERSION;
205205
public static final String GRAALPY_ABIFLAGS;
206+
public static final String GRAALPY_SOABI;
207+
public static final String GRAALPY_EXT_SUFFIX;
208+
public static final String GRAALPY_MULTIARCH;
206209

207210
/* Magic number used to mark pyc files */
208211
public static final int MAGIC_NUMBER = 21000 + Compiler.BYTECODE_VERSION * 10;
@@ -252,9 +255,12 @@ public final class PythonLanguage extends TruffleLanguage<PythonContext> {
252255
default:
253256
RELEASE_LEVEL_STRING = tsLiteral("final");
254257
}
255-
String[] abiParts = new String(is.readAllBytes(), StandardCharsets.US_ASCII).split("\\R", 2);
258+
String[] abiParts = new String(is.readAllBytes(), StandardCharsets.US_ASCII).split("\\R", 5);
256259
GRAALPY_ABI_VERSION = abiParts[0].strip();
257260
GRAALPY_ABIFLAGS = abiParts.length > 1 ? abiParts[1].strip() : "";
261+
GRAALPY_SOABI = abiParts.length > 2 ? abiParts[2].strip() : "";
262+
GRAALPY_EXT_SUFFIX = abiParts.length > 3 ? abiParts[3].strip() : "";
263+
GRAALPY_MULTIARCH = abiParts.length > 4 ? abiParts[4].strip() : "";
258264
} catch (IOException e) {
259265
throw new RuntimeException(e);
260266
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/ImpModuleBuiltins.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -833,7 +833,7 @@ public abstract static class ExtensionSuffixesNode extends PythonBuiltinNode {
833833
@Specialization
834834
Object run(
835835
@Bind PythonLanguage language) {
836-
return PFactory.createList(language, new Object[]{PythonContext.get(this).getSoAbi(), T_EXT_SO, T_EXT_PYD});
836+
return PFactory.createList(language, new Object[]{PythonContext.get(this).getExtensionSuffix(), T_EXT_SO, T_EXT_PYD});
837837
}
838838
}
839839

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/SysModuleBuiltins.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@
6060
import static com.oracle.graal.python.builtins.modules.io.IONodes.T_R;
6161
import static com.oracle.graal.python.builtins.modules.io.IONodes.T_W;
6262
import static com.oracle.graal.python.builtins.modules.io.IONodes.T_WRITE;
63-
import static com.oracle.graal.python.builtins.objects.str.StringUtils.cat;
6463
import static com.oracle.graal.python.lib.PyTraceBackPrint.castToString;
6564
import static com.oracle.graal.python.lib.PyTraceBackPrint.classNameNoDot;
6665
import static com.oracle.graal.python.lib.PyTraceBackPrint.fileFlush;
@@ -119,7 +118,6 @@
119118
import static com.oracle.graal.python.nodes.StringLiterals.T_BASE_PREFIX;
120119
import static com.oracle.graal.python.nodes.StringLiterals.T_BIG;
121120
import static com.oracle.graal.python.nodes.StringLiterals.T_COMMA;
122-
import static com.oracle.graal.python.nodes.StringLiterals.T_DASH;
123121
import static com.oracle.graal.python.nodes.StringLiterals.T_DOT;
124122
import static com.oracle.graal.python.nodes.StringLiterals.T_EMPTY_STRING;
125123
import static com.oracle.graal.python.nodes.StringLiterals.T_JAVA;
@@ -561,7 +559,7 @@ public void initialize(Python3Core core) {
561559
if (os == PLATFORM_DARWIN) {
562560
addBuiltinConstant("_framework", FRAMEWORK);
563561
}
564-
final TruffleString gmultiarch = cat(PythonUtils.getPythonArch(), T_DASH, osName);
562+
final TruffleString gmultiarch = toTruffleStringUncached(PythonLanguage.GRAALPY_MULTIARCH);
565563
addBuiltinConstant("__gmultiarch", gmultiarch);
566564

567565
// Initialized later in postInitialize

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/capi/CApiContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1119,7 +1119,7 @@ public static Object loadCExtModule(Node location, PythonContext context, Module
11191119
CApiContext cApiContext = CApiContext.ensureCapiWasLoaded(location, context, spec.name, spec.path);
11201120
NativeLibrary library;
11211121

1122-
TruffleFile realPath = context.getPublicTruffleFileRelaxed(spec.path, context.getSoAbi()).getCanonicalFile();
1122+
TruffleFile realPath = context.getPublicTruffleFileRelaxed(spec.path, context.getExtensionSuffix()).getCanonicalFile();
11231123
String loadPath = cApiContext.nativeLibraryLocator.resolve(context, realPath);
11241124
getLogger(CApiContext.class).config(String.format("loading module %s (real path: %s) as native", spec.path, loadPath));
11251125
int dlopenFlags = context.getDlopenFlags();

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/copying/NativeLibraryLocator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ public static void replicate(TruffleFile venvDirectory, PythonContext context, i
149149
"but we are preparing %d copies. The extra copies will only be used if a different value " +
150150
"of the system property %s is set.", MAX_CEXT_COPIES, count, J_MAX_CAPI_COPIES));
151151
}
152-
String suffix = context.getSoAbi().toJavaStringUncached();
152+
String suffix = context.getExtensionSuffix().toJavaStringUncached();
153153
TruffleFile capiLibrary = context.getPublicTruffleFileRelaxed(context.getCAPIHome()).resolve(PythonContext.getSupportLibName("python-" + J_NATIVE));
154154
for (int i = 0; i < count; i++) {
155155
// Relocate the C API library

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonContext.java

Lines changed: 5 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,12 @@
2727

2828
import static com.oracle.graal.python.PythonLanguage.getPythonOS;
2929
import static com.oracle.graal.python.PythonLanguage.throwIfUnsupported;
30-
import static com.oracle.graal.python.annotations.PythonOS.PLATFORM_DARWIN;
3130
import static com.oracle.graal.python.annotations.PythonOS.PLATFORM_WIN32;
3231
import static com.oracle.graal.python.builtins.PythonBuiltinClassType.SystemError;
33-
import static com.oracle.graal.python.builtins.modules.SysModuleBuiltins.T_ABIFLAGS;
34-
import static com.oracle.graal.python.builtins.modules.SysModuleBuiltins.T_CACHE_TAG;
35-
import static com.oracle.graal.python.builtins.modules.SysModuleBuiltins.T__MULTIARCH;
3632
import static com.oracle.graal.python.builtins.modules.io.IONodes.T_CLOSED;
3733
import static com.oracle.graal.python.builtins.modules.io.IONodes.T_FLUSH;
3834
import static com.oracle.graal.python.builtins.objects.PythonAbstractObject.NATIVE_POINTER_FREED;
3935
import static com.oracle.graal.python.builtins.objects.PythonAbstractObject.UNINITIALIZED;
40-
import static com.oracle.graal.python.builtins.objects.str.StringUtils.cat;
4136
import static com.oracle.graal.python.builtins.objects.thread.PThread.GRAALPYTHON_THREADS;
4237
import static com.oracle.graal.python.nodes.BuiltinNames.T_PYEXPAT;
4338
import static com.oracle.graal.python.nodes.BuiltinNames.T_SHA3;
@@ -55,11 +50,8 @@
5550
import static com.oracle.graal.python.nodes.StringLiterals.J_EXT_DYLIB;
5651
import static com.oracle.graal.python.nodes.StringLiterals.J_EXT_SO;
5752
import static com.oracle.graal.python.nodes.StringLiterals.J_LIB_PREFIX;
58-
import static com.oracle.graal.python.nodes.StringLiterals.T_DASH;
5953
import static com.oracle.graal.python.nodes.StringLiterals.T_DOT;
6054
import static com.oracle.graal.python.nodes.StringLiterals.T_EMPTY_STRING;
61-
import static com.oracle.graal.python.nodes.StringLiterals.T_EXT_PYD;
62-
import static com.oracle.graal.python.nodes.StringLiterals.T_EXT_SO;
6355
import static com.oracle.graal.python.nodes.StringLiterals.T_JAVA;
6456
import static com.oracle.graal.python.nodes.StringLiterals.T_NATIVE;
6557
import static com.oracle.graal.python.nodes.StringLiterals.T_PATH;
@@ -151,7 +143,6 @@
151143
import com.oracle.graal.python.nodes.SpecialAttributeNames;
152144
import com.oracle.graal.python.nodes.SpecialMethodNames;
153145
import com.oracle.graal.python.nodes.WriteUnraisableNode;
154-
import com.oracle.graal.python.nodes.attributes.ReadAttributeFromModuleNode;
155146
import com.oracle.graal.python.nodes.attributes.ReadAttributeFromObjectNode;
156147
import com.oracle.graal.python.nodes.bytecode_dsl.PBytecodeDSLRootNode;
157148
import com.oracle.graal.python.nodes.call.CallNode;
@@ -807,7 +798,7 @@ public enum CApiState {
807798
@CompilationFinal private boolean nativeAccessAllowed;
808799
@CompilationFinal private NativeContext nativeContext;
809800

810-
private TruffleString soABI;
801+
private TruffleString extensionSuffix;
811802

812803
private static final class GlobalInterpreterLock extends ReentrantLock {
813804
private static final long serialVersionUID = 1L;
@@ -2932,31 +2923,11 @@ public boolean isFinalizing() {
29322923
}
29332924

29342925
@TruffleBoundary
2935-
public TruffleString getSoAbi() {
2936-
if (soABI == null) {
2937-
PythonModule sysModule = this.lookupBuiltinModule(T_SYS);
2938-
Object implementationObj = ReadAttributeFromModuleNode.getUncached().execute(sysModule, T_IMPLEMENTATION);
2939-
// sys.implementation.cache_tag
2940-
TruffleString cacheTag = (TruffleString) PyObjectGetAttr.executeUncached(implementationObj, T_CACHE_TAG);
2941-
TruffleString abiFlags = (TruffleString) ReadAttributeFromModuleNode.getUncached().execute(sysModule, T_ABIFLAGS);
2942-
// sys.implementation._multiarch
2943-
TruffleString multiArch = (TruffleString) PyObjectGetAttr.executeUncached(implementationObj, T__MULTIARCH);
2944-
2945-
// only use '.pyd' if we are on 'Win32-native'
2946-
TruffleString soExt;
2947-
if (getPythonOS() == PLATFORM_DARWIN) {
2948-
// not ".dylib", similar to CPython:
2949-
// https://github.com/python/cpython/issues/37510
2950-
soExt = T_EXT_SO;
2951-
} else if (getPythonOS() == PLATFORM_WIN32) {
2952-
soExt = T_EXT_PYD;
2953-
} else {
2954-
soExt = T_EXT_SO;
2955-
}
2956-
2957-
soABI = cat(T_DOT, cacheTag, abiFlags, T_DASH, T_NATIVE, T_DASH, multiArch, soExt);
2926+
public TruffleString getExtensionSuffix() {
2927+
if (extensionSuffix == null) {
2928+
extensionSuffix = toTruffleStringUncached(PythonLanguage.GRAALPY_EXT_SUFFIX);
29582929
}
2959-
return soABI;
2930+
return extensionSuffix;
29602931
}
29612932

29622933
public Thread getMainThread() {

graalpython/graalpy-versions/CMakeLists.txt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,17 @@ endif()
3535
if (NOT DEFINED GRAALPY_ABIFLAGS)
3636
set(GRAALPY_ABIFLAGS "")
3737
endif()
38+
if (NOT DEFINED GRAALPY_EXT_SUFFIX)
39+
message(FATAL_ERROR "GRAALPY_EXT_SUFFIX needs to be set")
40+
endif()
41+
if (NOT DEFINED GRAALPY_MULTIARCH)
42+
message(FATAL_ERROR "GRAALPY_MULTIARCH needs to be set")
43+
endif()
44+
if (NOT DEFINED GRAALPY_SOABI)
45+
message(FATAL_ERROR "GRAALPY_SOABI needs to be set")
46+
endif()
3847

3948
# Generates file 'graalpy_versions' with the given content.
4049
# The file will be created if it does not exist and will only be updated if the
4150
# content changes.
42-
file(GENERATE OUTPUT "graalpy_versions" CONTENT "${GRAALPY_VER}\n${GRAALPY_ABIFLAGS}")
51+
file(GENERATE OUTPUT "graalpy_versions" CONTENT "${GRAALPY_VER}\n${GRAALPY_ABIFLAGS}\n${GRAALPY_SOABI}\n${GRAALPY_EXT_SUFFIX}\n${GRAALPY_MULTIARCH}\n")

0 commit comments

Comments
 (0)