Skip to content

Commit 56eed3f

Browse files
committed
[GR-69706] Add support to build ESPRESSO_NI_NATIVE_STANDALONE with musl based toolchains
PullRequest: graal/22116
2 parents 0568c5b + 24017bc commit 56eed3f

File tree

4 files changed

+98
-53
lines changed

4 files changed

+98
-53
lines changed

espresso-compiler-stub/mx.espresso-compiler-stub/mx_espresso_compiler_stub.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,13 @@ def create_ni_standalone(base_standalone_name, register_distribution):
7979
if _find_native_image_command(espresso_java_home.java_home):
8080
# ESPRESSO_JAVA_HOME has native-image, keep that
8181
pass
82-
elif has_component('ni') and espresso_java_home.java_home == mx_sdk_vm.base_jdk().home:
82+
elif has_component('ni'):
8383
if graalvm_skip_archive():
8484
mx.abort("Cannot build NI standalones with GRAALVM_SKIP_ARCHIVE enabled")
8585

86+
if espresso_java_home.java_home != mx_sdk_vm.base_jdk(stage1=False).home:
87+
mx.abort(f"ESPRESSO_JAVA_HOME(={espresso_java_home.java_home}) must match JAVA_HOME (={mx_sdk_vm.base_jdk(stage1=True).home}) (or FINAL_STAGE_JAVA_HOME (={mx_sdk_vm.base_jdk(stage1=False).home}) if set)")
88+
8689
# substratevm is available and ESPRESSO_JAVA_HOME is JAVA_HOME, use GraalVM
8790
layout['./'][0]['source_type'] = 'extracted-dependency'
8891
layout['./'][0]['dependency'] = get_final_graalvm_distribution().qualifiedName()

sdk/mx.sdk/mx_sdk_vm.py

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@
7878
('jvm-3-compiler-threads', [], ['--jvm', '--engine.CompilerThreads=3'], 50),
7979
('native-3-compiler-threads', [], ['--native', '--engine.CompilerThreads=3'], 100)
8080
]
81-
_base_jdk = None
81+
_base_jdk_stage1 = None
82+
_base_jdk_final = None
8283

8384

8485
class AbstractNativeImageConfig(object, metaclass=ABCMeta):
@@ -262,6 +263,7 @@ def __init__(self,
262263
has_relative_home=True,
263264
jvm_configs=None,
264265
extra_native_targets=None,
266+
stage1_only=False,
265267
final_stage_only=False):
266268
"""
267269
:param suite mx.Suite: the suite this component belongs to
@@ -280,6 +282,7 @@ def __init__(self,
280282
'priority': -1, # 0 is invalid; < 0 prepends to the default configs; > 0 appends
281283
}
282284
:param extra_native_targets: list of str, enables extra targets in multi-target projects.
285+
:param stage1_only: bool, this component should be only included in the stage1 GraalVM, not in final GraalVM
283286
:param final_stage_only: bool, this component should be only included in the final GraalVM, not in stage1
284287
:type license_files: list[str]
285288
:type third_party_license_files: list[str]
@@ -305,6 +308,7 @@ def __init__(self,
305308
:type extra_installable_qualifiers: list[str] | None
306309
:type has_relative_home: bool
307310
:type jvm_configs: list[dict] or None
311+
:type stage1_only: bool
308312
:type final_stage_only: bool
309313
"""
310314
if dependencies is None:
@@ -340,8 +344,12 @@ def __init__(self,
340344
self.has_relative_home = has_relative_home
341345
self.jvm_configs = jvm_configs or []
342346
self.extra_native_targets = extra_native_targets
347+
self.stage1_only = stage1_only
343348
self.final_stage_only = final_stage_only
344349

350+
if stage1_only and final_stage_only:
351+
mx.abort("{}: Cannot set both `stage1_only` and `final_stage_only`".format(name))
352+
345353
if supported is not None or early_adopter:
346354
if stability is not None:
347355
raise mx.abort("{}: Cannot use `stability` attribute in combination with deprecated `supported` and `early_adopter` attributes".format(name))
@@ -545,16 +553,42 @@ def register_vm_config(config_name, components, suite, dist_name=None, env_file=
545553
def get_graalvm_hostvm_configs():
546554
return _graalvm_hostvm_configs
547555

556+
def base_jdk(stage1=True):
557+
global _base_jdk_stage1, _base_jdk_final
558+
559+
if _base_jdk_stage1 is None:
560+
_base_jdk_stage1 = mx.get_jdk(tag='default')
561+
562+
if stage1:
563+
return _base_jdk_stage1
564+
565+
if _base_jdk_final is None:
566+
final_stage_java_home = mx.get_env('FINAL_STAGE_JAVA_HOME')
567+
if final_stage_java_home:
568+
_base_jdk_final = mx.JDKConfig(final_stage_java_home)
548569

549-
def base_jdk():
550-
global _base_jdk
551-
if _base_jdk is None:
552-
_base_jdk = mx.get_jdk(tag='default')
553-
return _base_jdk
570+
assert _base_jdk_stage1.version == _base_jdk_final.version, f"version of JAVA_HOME ({_base_jdk_stage1.version}) and FINAL_STAGE_JAVA_HOME ({_base_jdk_final.version}) must match"
571+
assert _base_jdk_stage1.release_dict['MODULES'] == _base_jdk_final.release_dict['MODULES'], "JAVA_HOME and FINAL_STAGE_JAVA_HOME do not include the same set of modules"
572+
573+
try:
574+
# attempt to initialize JVMCI related attributes
575+
jdk_enables_jvmci_by_default(_base_jdk_final)
576+
except AssertionError as e:
577+
assert "Could not execute" in e.args[0]
578+
579+
# ._probe_jvmci_info() and .get_modules() need a working java launcher, which might not be the case for FINAL_STAGE_JAVA_HOME.
580+
# Copy infos from stage1 JAVA_HOME instead.
581+
setattr(_base_jdk_final, '.enables_jvmci_by_default', jdk_enables_jvmci_by_default(_base_jdk_stage1))
582+
setattr(_base_jdk_final, '.jvmciThreadsPerNativeLibraryRuntime', get_JVMCIThreadsPerNativeLibraryRuntime(_base_jdk_stage1))
583+
584+
setattr(_base_jdk_final, '.modules', _base_jdk_stage1.get_modules())
585+
else:
586+
_base_jdk_final = _base_jdk_stage1
587+
return _base_jdk_final
554588

555589

556-
def base_jdk_version():
557-
return base_jdk().javaCompliance.value
590+
def base_jdk_version(stage1=True):
591+
return base_jdk(stage1=stage1).javaCompliance.value
558592

559593
def get_jdk_version_for_profiles():
560594
jdk_version = mx.get_jdk().javaCompliance.value
@@ -564,7 +598,9 @@ def _probe_jvmci_info(jdk, attribute_name):
564598
if not hasattr(jdk, '.enables_jvmci_by_default'):
565599
out = mx.LinesOutputCapture()
566600
sink = lambda x: x
567-
mx.run([jdk.java, '-XX:+UnlockExperimentalVMOptions', '-XX:+PrintFlagsFinal', '-version'], out=out, err=sink)
601+
rc = mx.run([jdk.java, '-XX:+UnlockExperimentalVMOptions', '-XX:+PrintFlagsFinal', '-version'], out=out, err=sink, nonZeroIsFatal=False)
602+
if rc != 0:
603+
raise AssertionError(f"Could not execute {jdk.java}")
568604
enableJVMCI = False
569605
jvmciThreadsPerNativeLibraryRuntime = None
570606
for line in out.lines:
@@ -599,7 +635,7 @@ def _read_java_base_hashes(jdk):
599635
"""
600636
hashes = {}
601637
out = mx.LinesOutputCapture()
602-
mx.run([jdk.exe_path('jmod'), 'describe', join(jdk.home, 'jmods', 'java.base.jmod')], out=out)
638+
mx.run([base_jdk(stage1=True).exe_path('jmod'), 'describe', join(jdk.home, 'jmods', 'java.base.jmod')], out=out)
603639
lines = out.lines
604640
for line in lines:
605641
if line.startswith('hashes'):
@@ -948,7 +984,7 @@ def jlink_new_jdk(jdk, dst_jdk_dir, module_dists, ignore_dists,
948984

949985
with open(module_info_java, 'w') as fp:
950986
fp.write(module_info)
951-
mx.run([jdk.javac, '-d', module_build_dir,
987+
mx.run([base_jdk(stage1=True).javac, '-d', module_build_dir,
952988
'--limit-modules=java.base,' + ','.join(jmd.requires.keys()),
953989
'--module-path=' + os.pathsep.join((m.jarpath for m in modules)),
954990
module_info_java])
@@ -958,14 +994,14 @@ def jlink_new_jdk(jdk, dst_jdk_dir, module_dists, ignore_dists,
958994
if exists(jmd.get_jmod_path()):
959995
os.remove(jmd.get_jmod_path())
960996
if not use_upgrade_module_path:
961-
mx.run([jdk.javac.replace('javac', 'jmod'), 'create', '--class-path=' + module_build_dir, jmd.get_jmod_path()])
997+
mx.run([base_jdk(stage1=True).exe_path('jmod'), 'create', '--class-path=' + module_build_dir, jmd.get_jmod_path()])
962998

963999
modules.extend(synthetic_modules.keys())
9641000
module_names = frozenset((m.name for m in modules))
9651001
all_module_names = frozenset(list(jdk_modules.keys())) | module_names
9661002

9671003
# Now build the new JDK image with jlink
968-
jlink = [jdk.javac.replace('javac', 'jlink')]
1004+
jlink = [base_jdk(stage1=True).exe_path('jlink')]
9691005
jlink_persist = []
9701006

9711007
if jdk_enables_jvmci_by_default(jdk):
@@ -1100,6 +1136,8 @@ def get_jmod_path_with_specified_module_info(self, m):
11001136
if "Shared spaces are not supported in this VM" in out.data:
11011137
# GR-37047: CDS support in darwin-aarch64 jdk11 is missing.
11021138
assert mx.get_os() == 'darwin' and mx.get_arch() == 'aarch64' and jdk.javaCompliance == '11'
1139+
elif base_jdk(stage1=True) != jdk:
1140+
mx.log("Cross build, skip -Xshare. FINAL_STAGE_JAVA_HOME might not run on the build host")
11031141
else:
11041142
mx.log(out.data)
11051143
mx.abort('Error generating CDS shared archive')
@@ -1182,7 +1220,7 @@ def verify_graalvm_configs(suites=None, start_from=None, check_all=False):
11821220
base_name=mx_sdk_vm_impl._graalvm_base_name,
11831221
delimiter='_' if dist_name else '',
11841222
dist_name=dist_name,
1185-
jdk_version=mx_sdk_vm_impl._src_jdk_version
1223+
jdk_version=base_jdk_version(stage1=False)
11861224
).upper().replace('-', '_')
11871225
mx.log("{}Checking that the env file '{}' in suite '{}' produces a GraalVM distribution named '{}'".format('' if started else '[SKIPPED] ', _env_file, suite.name, graalvm_dist_name))
11881226

sdk/mx.sdk/mx_sdk_vm_impl.py

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ def add_dependencies(dependencies, excludes=True):
138138
components = dependencies[:]
139139
while components:
140140
component = components.pop(0)
141+
if component.stage1_only and not stage1:
142+
continue
141143
if component.final_stage_only and stage1:
142144
continue
143145
if component not in components_to_build and not (excludes and is_excluded(component)):
@@ -240,18 +242,6 @@ def _get_main_component(components):
240242
return main_component
241243

242244

243-
_src_jdk = mx_sdk_vm.base_jdk()
244-
_src_jdk_version = mx_sdk_vm.base_jdk_version()
245-
246-
# Example:
247-
# macOS:
248-
# _src_jdk_dir = /Library/Java/JavaVirtualMachines/oraclejdk1.8.0_221-jvmci-19.2-b02
249-
# _src_jdk_base = Contents/Home
250-
# Others:
251-
# _src_jdk_dir = $JAVA_HOME (e.g. /usr/lib/jvm/oraclejdk1.8.0_212-jvmci-19.2-b01)
252-
# _src_jdk_base = .
253-
_src_jdk_dir, _src_jdk_base = _get_jdk_base(_src_jdk)
254-
255245
""":type: dict[str, (str, str)]"""
256246
_parent_info_cache = {}
257247

@@ -282,6 +272,15 @@ def __init__(self, suite, name, deps, components, is_graalvm, exclLibs, platform
282272
self.stage1 = stage1
283273
self.skip_archive = stage1 or graalvm_skip_archive() # *.tar archives for stage1 distributions are never built
284274

275+
# Example:
276+
# macOS:
277+
# _src_jdk_dir = /Library/Java/JavaVirtualMachines/oraclejdk1.8.0_221-jvmci-19.2-b02
278+
# _src_jdk_base = Contents/Home
279+
# Others:
280+
# _src_jdk_dir = $JAVA_HOME (e.g. /usr/lib/jvm/oraclejdk1.8.0_212-jvmci-19.2-b01)
281+
# _src_jdk_base = .
282+
_src_jdk_dir, _src_jdk_base = _get_jdk_base(mx_sdk_vm.base_jdk(stage1=stage1))
283+
285284
layout = {}
286285
src_jdk_base = _src_jdk_base if add_jdk_base else '.'
287286
assert src_jdk_base
@@ -442,7 +441,7 @@ def _add_link(_dest, _target, _component=None, _dest_base_name=None):
442441
if stage1:
443442
# 1. we do not want a GraalVM to be used as base-JDK
444443
# 2. we don't need to check if the base JDK is JVMCI-enabled, since JVMCIVersionCheck takes care of that when the GraalVM compiler is a registered component
445-
check_versions(_src_jdk, expect_graalvm=False, check_jvmci=False)
444+
check_versions(mx_sdk_vm.base_jdk(stage1=stage1), expect_graalvm=False, check_jvmci=False)
446445

447446
# Add base JDK
448447
if mx.get_os() == 'darwin':
@@ -679,7 +678,7 @@ def _add_link(_dest, _target, _component=None, _dest_base_name=None):
679678
_add(layout, '<jre_base>/lib/graalvm/', ['dependency:' + d for d in sorted(graalvm_dists)], with_sources=True)
680679

681680
for _base, _suites in component_suites.items():
682-
_metadata = self._get_metadata(_suites)
681+
_metadata = self._get_metadata(_suites, stage1=stage1)
683682
_add(layout, _base + 'release', "string:{}".format(_metadata))
684683

685684
if "archive_factory" not in kw_args and self.skip_archive:
@@ -712,7 +711,7 @@ def needsUpdate(self, newestInput):
712711
return super(BaseGraalVmLayoutDistribution, self).needsUpdate(newestInput)
713712

714713
@staticmethod
715-
def _get_metadata(suites, parent_release_file=None, java_version=None):
714+
def _get_metadata(suites, parent_release_file=None, java_version=None, stage1=True):
716715
"""
717716
:type suites: list[mx.Suite]
718717
:type parent_release_file: str | None
@@ -735,7 +734,7 @@ def _get_metadata(suites, parent_release_file=None, java_version=None):
735734
else:
736735
_metadata_dict = OrderedDict()
737736

738-
_metadata_dict.setdefault('JAVA_VERSION', java_version or _src_jdk.version)
737+
_metadata_dict.setdefault('JAVA_VERSION', java_version or mx_sdk_vm.base_jdk(stage1=stage1).version)
739738
_metadata_dict.setdefault('OS_NAME', get_graalvm_os())
740739
_metadata_dict.setdefault('OS_ARCH', mx.get_arch())
741740
if mx.get_os_variant():
@@ -919,7 +918,7 @@ def _get_graalvm_configuration(base_name, components=None, stage1=False):
919918
name_prefix = '{base_name}{vm_dist_name}_java{jdk_version}'.format(
920919
base_name=base_name,
921920
vm_dist_name=('_' + vm_dist_name) if vm_dist_name else '',
922-
jdk_version=_src_jdk_version
921+
jdk_version=mx_sdk_vm.base_jdk_version(stage1=stage1)
923922
)
924923
name = '{name_prefix}{stage_suffix}'.format(name_prefix=name_prefix, stage_suffix='_stage1' if stage1 else '')
925924
else:
@@ -934,7 +933,7 @@ def _get_graalvm_configuration(base_name, components=None, stage1=False):
934933
else:
935934
m.update("not-jlinked".encode())
936935
short_sha1_digest = m.hexdigest()[:10] # to keep paths short
937-
base_dir = '{base_name}_{hash}_java{jdk_version}'.format(base_name=base_name, hash=short_sha1_digest, jdk_version=_src_jdk_version)
936+
base_dir = '{base_name}_{hash}_java{jdk_version}'.format(base_name=base_name, hash=short_sha1_digest, jdk_version=mx_sdk_vm.base_jdk_version(stage1=stage1))
938937
name = '{base_dir}{stage_suffix}'.format(base_dir=base_dir, stage_suffix='_stage1' if stage1 else '')
939938
base_dir += '_' + _suite.release_version()
940939
name = name.upper()
@@ -1590,11 +1589,12 @@ def with_source(dep):
15901589
return not isinstance(dep, mx.Dependency) or (_include_sources(dep.qualifiedName()) and dep.isJARDistribution() and not dep.is_stripped())
15911590
vendor_info = {'vendor-version': graalvm_vendor_version()}
15921591
out_dir = self.subject.output_directory()
1592+
stage1 = 'stage1' in self.subject.name
15931593

15941594
if _jlink_libraries():
15951595
use_upgrade_module_path = mx.get_env('MX_BUILD_EXPLODED') == 'true'
15961596

1597-
built = mx_sdk.jlink_new_jdk(_src_jdk,
1597+
built = mx_sdk.jlink_new_jdk(mx_sdk_vm.base_jdk(stage1=stage1),
15981598
out_dir,
15991599
self.subject.deps,
16001600
self.subject.jimage_ignore_jars,
@@ -1607,12 +1607,12 @@ def with_source(dep):
16071607
mx.warn("--no-jlinking flag used. The resulting VM will be HotSpot, not GraalVM")
16081608
if exists(out_dir):
16091609
mx.rmtree(out_dir)
1610-
shutil.copytree(_src_jdk.home, out_dir, symlinks=True)
1610+
shutil.copytree(mx_sdk_vm.base_jdk(stage1=stage1).home, out_dir, symlinks=True)
16111611
built = True
16121612

16131613
release_file = join(out_dir, 'release')
16141614
_sorted_suites = sorted(mx.suites(), key=lambda s: s.name)
1615-
_metadata = BaseGraalVmLayoutDistribution._get_metadata(_sorted_suites, release_file)
1615+
_metadata = BaseGraalVmLayoutDistribution._get_metadata(_sorted_suites, release_file, stage1=stage1)
16161616
with open(release_file, 'w') as f:
16171617
f.write(_metadata)
16181618

@@ -1656,7 +1656,7 @@ def _config(self):
16561656
# Save the path and timestamp of the JDK image so that graalvm-jimage
16571657
# is rebuilt if the JDK at JAVA_HOME is rebuilt. The JDK image file is
16581658
# always updated when the JDK is rebuilt.
1659-
src_jimage = mx.TimeStampFile(join(_src_jdk.home, 'lib', 'modules'))
1659+
src_jimage = mx.TimeStampFile(join(mx_sdk_vm.base_jdk().home, 'lib', 'modules'))
16601660
return [
16611661
f'include sources: {_include_sources_str()}',
16621662
f'strip jars: {mx.get_opts().strip_jars}',
@@ -2109,7 +2109,7 @@ def graalvm_home_relative_classpath(dependencies, start=None, with_boot_jars=Fal
21092109
if jimage_deps and _jlink_libraries() and _cp_entry in jimage_deps:
21102110
continue
21112111
if _cp_entry.isJdkLibrary() or _cp_entry.isJreLibrary():
2112-
jdk = _src_jdk
2112+
jdk = mx_sdk_vm.base_jdk(stage1=graal_vm.stage1)
21132113
if hasattr(_cp_entry, 'jdkStandardizedSince') and jdk.javaCompliance >= _cp_entry.jdkStandardizedSince:
21142114
continue
21152115
jdk_location = relpath(_cp_entry.classpath_repr(jdk), jdk.home)
@@ -2294,12 +2294,6 @@ def __str__(self):
22942294
return 'Building {}'.format(self.subject.name)
22952295

22962296

2297-
def _get_component_stability(component):
2298-
if _src_jdk_version not in (17, 20):
2299-
return "experimental"
2300-
return component.stability
2301-
2302-
23032297
def default_jvm_components():
23042298
"""
23052299
Components that, for now, must be included in the JVM.
@@ -2312,7 +2306,7 @@ def _get_jvm_cfg():
23122306
candidates = (['lib', 'jvm.cfg'], ['jre', 'lib', 'jvm.cfg'], ['jre', 'lib', mx.get_arch(), 'jvm.cfg'])
23132307
probed = []
23142308
for candidate in candidates:
2315-
jvm_cfg = join(_src_jdk.home, *candidate)
2309+
jvm_cfg = join(mx_sdk_vm.base_jdk().home, *candidate)
23162310
if exists(jvm_cfg):
23172311
return jvm_cfg
23182312
probed.append(jvm_cfg)
@@ -2761,6 +2755,7 @@ def register_main_dist(dist, label):
27612755
defaultBuild=False,
27622756
missing_export_target_action='warn',
27632757
default_to_jvmci='lib' if has_lib_graal else False,
2758+
stage1=False,
27642759
)
27652760
register_project(java_standalone_jimage)
27662761

@@ -2831,6 +2826,11 @@ def register_main_dist(dist, label):
28312826

28322827
def _needs_stage1_jimage(stage1_dist, final_dist):
28332828
assert isinstance(stage1_dist.jimage_jars, set) and isinstance(final_dist.jimage_jars, set)
2829+
2830+
if mx_sdk_vm.base_jdk(stage1=True) != mx_sdk_vm.base_jdk(stage1=False):
2831+
# cross-build, always need a stage1_jimage
2832+
return True
2833+
28342834
return stage1_dist.jimage_jars != final_dist.jimage_jars
28352835

28362836

@@ -3239,7 +3239,7 @@ def graalvm_show(args, forced_graalvm_dist=None):
32393239
print("Config name: {}".format(graalvm_dist.vm_config_name))
32403240
print("Components:")
32413241
for component in sorted(graalvm_dist.components, key=lambda c: c.name):
3242-
print(" - {} ('{}', /{}, {})".format(component.name, component.short_name, component.dir_name, _get_component_stability(component)))
3242+
print(" - {} ('{}', /{})".format(component.name, component.short_name, component.dir_name))
32433243

32443244
if forced_graalvm_dist is None:
32453245
# Custom GraalVM distributions with a forced component list do not yet support launchers and libraries.
@@ -3388,7 +3388,7 @@ def print_graalvm_vm_name(args):
33883388
"""Print the VM name of GraalVM"""
33893389
parser = ArgumentParser(prog='mx graalvm-vm-name', description='Print the VM name of GraalVM')
33903390
_ = parser.parse_args(args)
3391-
print(graalvm_vm_name(get_final_graalvm_distribution(), _src_jdk))
3391+
print(graalvm_vm_name(get_final_graalvm_distribution(), mx_sdk_vm.base_jdk(stage1=False)))
33923392

33933393
def graalvm_vm_name(graalvm_dist, jdk):
33943394
"""

0 commit comments

Comments
 (0)