Skip to content

Commit a4d886d

Browse files
[GR-59780] [GR-53985] Add ForNameRespectsClassLoader and integrate Crema in the class loading path.
PullRequest: graal/20083
2 parents f7d8674 + 1448047 commit a4d886d

File tree

141 files changed

+3350
-346
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

141 files changed

+3350
-346
lines changed
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
#
2+
# Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved.
3+
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
#
5+
# This code is free software; you can redistribute it and/or modify it
6+
# under the terms of the GNU General Public License version 2 only, as
7+
# published by the Free Software Foundation. Oracle designates this
8+
# particular file as subject to the "Classpath" exception as provided
9+
# by Oracle in the LICENSE file that accompanied this code.
10+
#
11+
# This code is distributed in the hope that it will be useful, but WITHOUT
12+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
# version 2 for more details (a copy is included in the LICENSE file that
15+
# accompanied this code).
16+
#
17+
# You should have received a copy of the GNU General Public License version
18+
# 2 along with this work; if not, write to the Free Software Foundation,
19+
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
#
21+
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
# or visit www.oracle.com if you need additional information or have any
23+
# questions.
24+
#
25+
import os
26+
import re
27+
from collections import OrderedDict
28+
from os.path import join, exists, relpath
29+
30+
import mx
31+
import mx_util
32+
33+
34+
class EspressoSVMShared(mx.JavaProject):
35+
def __init__(self, suite, name, deps, workingSets, theLicense=None, **attr):
36+
self.shadedProjects = attr.pop('shadedProjects')
37+
self.removeAnnotations = attr.pop('removeAnnotations', [])
38+
self.checkPackagePrefix = True
39+
packageMap = attr.pop('packageMap')
40+
self.packageMap = OrderedDict()
41+
for k in sorted(packageMap, key=str.__len__, reverse=True):
42+
self.packageMap[k + '.'] = packageMap[k] + '.'
43+
self.pathMap = OrderedDict((k.replace('.', os.sep), v.replace('.', os.sep)) for k, v in self.packageMap.items())
44+
javaCompliance = attr.pop('javaCompliance')
45+
super().__init__(suite, name, "", [], deps, javaCompliance, workingSets, suite.dir, theLicense, **attr)
46+
self.gen_src = join(self.get_output_root(), 'gen_src')
47+
self.srcDirs.append(self.gen_src)
48+
49+
def getBuildTask(self, args):
50+
jdk = mx.get_jdk(self.javaCompliance, tag=mx.DEFAULT_JDK_TAG, purpose='building ' + self.name)
51+
return EspressoSVMSharedBuildTask(args, self, jdk)
52+
53+
def resolveDeps(self):
54+
super().resolveDeps()
55+
self._resolveDepsHelper(self.shadedProjects)
56+
not_java_projects = [d for d in self.shadedProjects if not d.isJavaProject()]
57+
if not_java_projects:
58+
raise self.abort(f"shadedProjects must all be java projects, but the following are not: {not_java_projects}")
59+
60+
def get_checkstyle_config(self, resolve_checkstyle_library=True):
61+
return None, None, None
62+
63+
def shaded_deps(self):
64+
return self.shadedProjects
65+
66+
def _apply_package_map(self, original, is_path):
67+
map_dict = self.pathMap if is_path else self.packageMap
68+
for k, v in map_dict.items():
69+
if original.startswith(k):
70+
return v + original[len(k):]
71+
return original
72+
73+
def substitute_package_name(self, pkg):
74+
return self._apply_package_map(pkg, False)
75+
76+
def substitute_path(self, path):
77+
return self._apply_package_map(path, True)
78+
79+
def defined_java_packages(self):
80+
return set([self.substitute_package_name(pkg) for dep in self.shaded_deps() for pkg in dep.defined_java_packages()])
81+
82+
83+
class EspressoSVMSharedBuildTask(mx.JavaBuildTask):
84+
def saved_config_path(self):
85+
return join(self.subject.get_output_root(), 'config')
86+
87+
def config(self):
88+
config = str(sorted(self.subject.shaded_deps())) + '\n'
89+
config += str(self.subject.javaCompliance) + '\n'
90+
for pkg in sorted(self.subject.packageMap):
91+
config += f"{pkg}: {self.subject.packageMap[pkg]}\n"
92+
config += str(sorted(self.subject.removeAnnotations)) + '\n'
93+
return config
94+
95+
def _walk_files(self, create_shaded_dirs=False):
96+
for shaded_project in self.subject.shaded_deps():
97+
for src_dir in shaded_project.source_dirs():
98+
for dirpath, _, filenames in os.walk(src_dir):
99+
reldirpath = relpath(dirpath, src_dir)
100+
mapped_reldirpath = self.subject.substitute_path(reldirpath)
101+
if create_shaded_dirs and filenames:
102+
mx_util.ensure_dir_exists(join(self.subject.gen_src, mapped_reldirpath))
103+
for filename in filenames:
104+
shaded_relpath = join(mapped_reldirpath, filename)
105+
yield join(dirpath, filename), join(self.subject.gen_src, shaded_relpath), shaded_relpath
106+
107+
def needsBuild(self, newestInput):
108+
is_needed, reason = mx.ProjectBuildTask.needsBuild(self, newestInput)
109+
if is_needed:
110+
return True, reason
111+
config_path = self.saved_config_path()
112+
if not exists(config_path):
113+
return True, "Saved config file not found"
114+
config = self.config()
115+
with open(config_path, 'r', encoding='utf-8') as f:
116+
if f.read() != config:
117+
return True, "Configuration changed"
118+
for original, shaded, _ in self._walk_files():
119+
ts = mx.TimeStampFile(shaded)
120+
if ts.isOlderThan(original):
121+
return True, str(ts)
122+
if newestInput and ts.isOlderThan(newestInput):
123+
return True, str(ts)
124+
return False, None
125+
126+
def _collect_files(self):
127+
if self._javafiles is not None:
128+
# already collected
129+
return self
130+
javafiles = {}
131+
non_javafiles = {}
132+
output_dir = self.subject.output_dir()
133+
for _, shaded, shaded_relpath in self._walk_files():
134+
if shaded.endswith('.java'):
135+
classfile = output_dir + shaded_relpath[:-len('.java')] + '.class'
136+
javafiles[shaded] = classfile
137+
else:
138+
non_javafiles[shaded] = output_dir + shaded_relpath
139+
if hasattr(self.subject, 'copyFiles'):
140+
raise mx.abort('copyFiles is not supported', context=self.subject)
141+
self._javafiles = javafiles
142+
self._non_javafiles = non_javafiles
143+
self._copyfiles = {}
144+
return self
145+
146+
def clean(self, forBuild=False):
147+
super().clean()
148+
if exists(self.subject.gen_src):
149+
mx.rmtree(self.subject.gen_src)
150+
151+
def build(self):
152+
java_substitutions = [
153+
sub for orig, shad in self.subject.packageMap.items() for sub in [
154+
(re.compile(r'\b' + re.escape(orig) + r'(?=\.\w+)?\b'), shad),
155+
]
156+
]
157+
re_type_start = re.compile(r"\.[A-Z]")
158+
for annotation_type in self.subject.removeAnnotations:
159+
type_name_start = re_type_start.search(annotation_type).start()
160+
# remove `import com.Foo.Bar;`
161+
# remove `@Foo.Bar(*)`
162+
# remove `@Foo.Bar`
163+
# change `{@link Foo.Bar}` to `{@code Foo.Bar}`
164+
unqualified_type = annotation_type[type_name_start + 1:]
165+
java_substitutions += [
166+
(re.compile(r'^import\s+' + re.escape(annotation_type) + r'\s*;', re.MULTILINE), ''),
167+
(re.compile(r'@' + re.escape(unqualified_type) + r'(\(.*?\))?'), ''),
168+
(re.compile(r'\{@link ' + re.escape(unqualified_type) + r'\}'), '{@code ' + unqualified_type + '}'),
169+
]
170+
next_type_name_m = re_type_start.search(annotation_type, type_name_start + 1)
171+
if next_type_name_m:
172+
# remove `import com.Foo;`
173+
# remove `import static com.Foo.Bar;`
174+
# remove `@Bar(*)`
175+
# remove `@Bar`
176+
# change `{@link Bar}` to `{@code Bar}`
177+
next_type_name_start = next_type_name_m.start()
178+
next_unqualified_type = annotation_type[next_type_name_start + 1:]
179+
java_substitutions += [
180+
(re.compile(r'^import\s+' + re.escape(annotation_type[:next_type_name_start]) + r'\s*;', re.MULTILINE), ''),
181+
(re.compile(r'^import\s+static\s+' + re.escape(annotation_type) + r'\s*;', re.MULTILINE), ''),
182+
(re.compile(r'@' + re.escape(next_unqualified_type) + r'(\(.*?\))?'), ''),
183+
(re.compile(r'\{@link ' + re.escape(next_unqualified_type) + r'\}'), '{@code ' + next_unqualified_type + '}'),
184+
]
185+
assert not re_type_start.search(annotation_type, next_type_name_start + 1)
186+
187+
for original, shaded, _ in self._walk_files(True):
188+
with open(original, 'r', encoding='utf-8') as f_orig, open(shaded, 'w', encoding='utf-8') as f_shaded:
189+
for line in f_orig:
190+
for srch, repl in java_substitutions:
191+
line = re.sub(srch, repl, line)
192+
f_shaded.write(line)
193+
super().build()
194+
with open(self.saved_config_path(), 'w', encoding='utf-8') as f:
195+
f.write(self.config())
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
#
2+
# Copyright (c) 2025, 2025, Oracle and/or its affiliates. All rights reserved.
3+
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
#
5+
# This code is free software; you can redistribute it and/or modify it
6+
# under the terms of the GNU General Public License version 2 only, as
7+
# published by the Free Software Foundation. Oracle designates this
8+
# particular file as subject to the "Classpath" exception as provided
9+
# by Oracle in the LICENSE file that accompanied this code.
10+
#
11+
# This code is distributed in the hope that it will be useful, but WITHOUT
12+
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+
# version 2 for more details (a copy is included in the LICENSE file that
15+
# accompanied this code).
16+
#
17+
# You should have received a copy of the GNU General Public License version
18+
# 2 along with this work; if not, write to the Free Software Foundation,
19+
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+
#
21+
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+
# or visit www.oracle.com if you need additional information or have any
23+
# questions.
24+
#
25+
suite = {
26+
"mxversion": "7.38.0",
27+
"name": "espresso-shared",
28+
"version" : "25.0.0",
29+
"release" : False,
30+
"groupId" : "org.graalvm.espresso",
31+
"url" : "https://www.graalvm.org/reference-manual/java-on-truffle/",
32+
"developer" : {
33+
"name" : "GraalVM Development",
34+
"email" : "[email protected]",
35+
"organization" : "Oracle Corporation",
36+
"organizationUrl" : "http://www.graalvm.org/",
37+
},
38+
"scm" : {
39+
"url" : "https://github.com/oracle/graal/tree/master/espresso-shared",
40+
"read" : "https://github.com/oracle/graal.git",
41+
"write" : "[email protected]:oracle/graal.git",
42+
},
43+
44+
# ------------- licenses
45+
46+
"licenses": {
47+
"GPLv2": {
48+
"name": "GNU General Public License, version 2",
49+
"url": "http://www.gnu.org/licenses/old-licenses/gpl-2.0.html"
50+
},
51+
"UPL": {
52+
"name": "Universal Permissive License, Version 1.0",
53+
"url": "http://opensource.org/licenses/UPL",
54+
},
55+
"Oracle Proprietary": {
56+
"name": "ORACLE PROPRIETARY/CONFIDENTIAL",
57+
"url": "http://www.oracle.com/us/legal/copyright/index.html"
58+
},
59+
},
60+
"defaultLicense": "GPLv2",
61+
62+
# ------------- imports
63+
64+
"imports": {
65+
"suites": [
66+
{
67+
"name": "truffle",
68+
"subdir": True,
69+
},
70+
{
71+
"name" : "sdk",
72+
"subdir": True,
73+
},
74+
],
75+
},
76+
77+
# ------------- projects
78+
79+
"projects": {
80+
# Shared .class file parser
81+
"com.oracle.truffle.espresso.classfile": {
82+
"subDir": "src",
83+
"sourceDirs": ["src"],
84+
"dependencies": [
85+
"sdk:COLLECTIONS",
86+
"truffle:TRUFFLE_API",
87+
],
88+
"javaCompliance" : "17+",
89+
"checkstyle": "com.oracle.truffle.espresso.classfile",
90+
"checkstyleVersion": "10.21.0",
91+
},
92+
93+
# Shared link resolver
94+
"com.oracle.truffle.espresso.shared": {
95+
"subDir": "src",
96+
"sourceDirs": ["src"],
97+
"dependencies": [
98+
"com.oracle.truffle.espresso.classfile",
99+
],
100+
"javaCompliance" : "17+",
101+
"checkstyle": "com.oracle.truffle.espresso.classfile",
102+
},
103+
104+
# Shared code shaded for SVM
105+
"com.oracle.svm.espresso": {
106+
"class": "EspressoSVMShared",
107+
"shadedProjects": [
108+
"com.oracle.truffle.espresso.classfile",
109+
"com.oracle.truffle.espresso.shared",
110+
],
111+
"dependencies": [
112+
"sdk:COLLECTIONS",
113+
],
114+
"removeAnnotations": [
115+
"com.oracle.truffle.api.CompilerDirectives.CompilationFinal",
116+
"com.oracle.truffle.api.CompilerDirectives.TruffleBoundary",
117+
"com.oracle.truffle.api.nodes.ExplodeLoop",
118+
],
119+
"packageMap": {
120+
"com.oracle.truffle.espresso": "com.oracle.svm.espresso",
121+
},
122+
"eclipseformat": False,
123+
"javaCompliance" : "17+",
124+
},
125+
},
126+
127+
# ------------- distributions
128+
129+
"distributions": {
130+
"ESPRESSO_SHARED": {
131+
"moduleInfo" : {
132+
"name" : "org.graalvm.espresso.shared",
133+
"exports": [
134+
"* to org.graalvm.espresso",
135+
],
136+
},
137+
"description" : "Espresso shared code for runtime class loading",
138+
"subDir": "src",
139+
"dependencies": [
140+
"com.oracle.truffle.espresso.classfile",
141+
"com.oracle.truffle.espresso.shared",
142+
],
143+
"distDependencies": [
144+
"sdk:COLLECTIONS",
145+
"truffle:TRUFFLE_API",
146+
],
147+
"maven" : {
148+
"tag": ["default", "public"],
149+
},
150+
"useModulePath": True,
151+
"noMavenJavadoc": True,
152+
},
153+
"ESPRESSO_SVM": {
154+
"moduleInfo" : {
155+
"name" : "org.graalvm.espresso.shared.svm",
156+
"exports": [
157+
"* to org.graalvm.nativeimage.builder",
158+
],
159+
},
160+
"description" : "Espresso shared code for runtime class loading (shaded for SVM)",
161+
"subDir": "src",
162+
"dependencies": [
163+
"com.oracle.svm.espresso",
164+
],
165+
"distDependencies": [
166+
"sdk:COLLECTIONS",
167+
],
168+
"maven" : {
169+
"tag": ["default", "public"],
170+
},
171+
"useModulePath": True,
172+
"noMavenJavadoc": True,
173+
},
174+
}
175+
}

0 commit comments

Comments
 (0)